6

linux实现 五子棋(人人对战)

 2 years ago
source link: https://blog.51cto.com/u_15787387/5784033
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

linux实现 五子棋(人人对战)

推荐 原创

萌新的日常 2022-10-21 17:06:50 ©著作权

文章标签 f5 d3 全局变量 文章分类 Linux 系统/运维 yyds干货盘点 阅读数289

对于 game 函数的解析

linux实现 五子棋(人人对战)_f5

进入game函数中,通过创建一个二维数组来打印棋盘,进入 do while 循环中,
策略是 先打印出棋盘, 然后先让用户1落子,进行判定,看是否需要继续,若需要则让
用户2落子,再进行判定,直到用户1/用户2赢,或者平局 跳出循环
linux实现 五子棋(人人对战)_d3_02
通过isover函数的返回值来确定进入switch语句中的那个case 中
最后打印出结果

playermove ——用户落子

linux实现 五子棋(人人对战)_全局变量_03

这里使用 全局变量 x y 会在下方说明,进入while(1)循环中,若碰到越界问题 和被占用问题 直接continue ,返回重新输入。
除此之外,直接将定义的变量who 赋值给 board[x-1][y-1]中,因为 无论是 用户1/用户2都是在game.h文件中用宏定义了的。
下标表示为 x-1,y-1,是因为我们设计的棋盘是从1开始的。

isover ——判定四种情况

linux实现 五子棋(人人对战)_d3_04

在isover函数中,还有一个函数chessout是用来计算特定方向的最大格式,这个我们等会再说,通过chessout函数记录最大连珠数后,通过判断加上本身的1是否大于5,若大于5,则有人赢,(用户1赢/用户2赢),
如果没人赢,判断下棋盘中是否有默认初始化的0,若有0则为继续,若没有0则平局。

chessout —— 求特定方向的连珠数

linux实现 五子棋(人人对战)_全局变量_05
linux实现 五子棋(人人对战)_f5_06

通过该图判断每次改变方向时,x y的变化
如果可以一直向某个方向变化且保持连珠,则count++
反之,直接break跳出循环,输出count
在循环中若该下标越界,也直接break
这里我们需要注意下,将原来的 坐标 x y 的值保存起来,用改变后的下标_x _y,与其值进行比较,若相等则说明可以连珠,若不相等 ,就直接break。

linux实现 五子棋(人人对战)_f5_07
这里的d 即为枚举变量,无论对应输入那个方向都可以接收

使用全局变量 x y 的原因

linux实现 五子棋(人人对战)_d3_08
linux实现 五子棋(人人对战)_全局变量_09

1.当使用 playermove函数表示使用户1/用户2落子时,此时的x y就分别代表在当前用户1/用户2在棋盘所显示的值,因为 PLAYER1(1) 与 PLAYER2(2) 都是被宏定义了值的。

  1. 当落子后,进入isover函数进行判定
    linux实现 五子棋(人人对战)_f5_10
    通过 x y 所对应棋盘下标的值,来确定是用户1,还是用户2

showboard—— 数组内容可视化

linux实现 五子棋(人人对战)_d3_11

这里需要注意的是,刚开始有一个空格的存在是为了 将棋盘的 x y 对齐

linux实现 五子棋(人人对战)_全局变量_12

初始化时,我们将棋盘显示的0记作 .

linux实现 五子棋(人人对战)_全局变量_13
用户1输入 坐标 1 1 ,显示处 x
linux实现 五子棋(人人对战)_d3_14

用户2输入 坐标 2 2,出现 o

1. game.c

 #include"game.h"
 int x = 0;
 int y = 0;
 void menu()
 {
  printf("******************\n");
  printf("*****1.play 0.exit\n");
  printf("******************\n");
 }
 void showboard(int board[][COL],int row,int col)
 {
   int i=0;
   int j=0;
   printf(" ");
   for(i=1;i<=col;i++)
   {
    printf("%3d",i);
   }
   printf("\n");
   for(i=0;i<row;i++)
   {
    printf("%2d",i+1);
    for(j=0;j<col;j++)
    {
     if(board[i][j]==0)
     {
     printf(" . ");
     }
     else if(board[i][j]==PLAYER1)
     {
      printf(" x ");
     }
     else
     {
      printf(" o ");
     }
    }
    printf("\n");
   }
 }

  
  //按照 x y作为起点,按照特定方向,求连续相对的最大格式
  int chesscount(int board[ROW][COL],int row,int col,enum dir d)//d为枚举变量 
  {
    int _x=x-1;//_x作为当前x的下标
    int _y=y-1;//_y作为当前y的下标
    int count=0;
    while(1)
  {

    switch(d)
    {
    case LEFT://左
    _y--;
    break;
    case RIGHT://右
    _y++;
    break;
    case UP://上
    _x--;
    break;
    case DOWN://下
    _x++;
    break;
    case LEFT_UP://左上
    _x--;
    _y--;
    break;
    case LEFT_DOWN://左下
    _x++;
    _y--;
    break;
    case RIGHT_UP://右上
    _x--;
    _y++;
    break;
    case RIGHT_DOWN://右下
    _x++;
    _y++;
    break;
    }
    if(_x<0||_x>row-1||_y<0||_y>col-1)// _x _y 都是下标,如果越界就跳出循环
    {
     break;
    }
    if(board[x-1][y-1]==board[_x][_y])//如果 改变后的下标 与用户的值相等,count++
    {
     count++;
    }
    else
    {
      break;
    }
  }
  return count;

 }

  int  isover(int board[][COL],int row,int col)
  {
     int count1=chesscount(board,row,col,LEFT)+chesscount(board,row,col,RIGHT)+1;//坐标所在的左右连接相同棋子数+本身棋子数1
     int count2=chesscount(board,row,col,UP)+chesscount(board,row,col,DOWN)+1;   //坐标所在的上下连接相同棋子数+本身棋子数1
     int count3=chesscount(board,row,col,LEFT_UP)+chesscount(board,row,col,RIGHT_DOWN)+1;//坐标所在的左上 与右下连接相同棋子数+本身棋子数1
     int count4=chesscount(board,row,col,LEFT_DOWN)+chesscount(board,row,col,RIGHT_UP)+1;//坐标所在的左下 与右上连接相同棋子数+本身棋子数1
     if(count1>=5||count2>=5||count3>=5||count4>=5)//说明有五子连珠的情况,有人赢
     {
       if(board[x-1][y-1]==PLAYER1)//因为设置的全局变量的x y,落子就判定,此时x y所对应棋盘的数字是 用户1(1)还是用户2(2)
       {
        return PLAYER1_WIN;//用户1赢
	}
        else
	{
	 return PLAYER2_WIN;//用户2赢
	 }
     }
     //没人赢,有两种情况1.继续 2.平局
     int i=0;
     int j=0;
     for(i=0;i<row;i++)//继续
     {
      for(j=0;j<col;j++)
      {
       if(board[i][j]==0)//有默认值0说明该坐标没有被下棋
       {
         return NEXT;
        }
      }
     }
     return DRAW;//平局
  }
  



 void playermove(int board[][COL],int row,int col ,int who)//用户1/用户2落子
 {
    while(1)
    {
     printf("player[%d] please Enter your pos# ",who);
     scanf("%d%d",&x,&y);
     if(x<1||x>row||y<1||y>col)//如果x y越界,就返回重新输入
     {
       printf("pos is not right!\n");
       continue;
     }
    else if(board[x-1][y-1]!=0)  //在棋盘中被占用,就重新输入
     {
      printf("棋盘被占用,重新输入\n");
      continue;
     }
     else
     {
     board[x-1][y-1]=who;  //此时的who 已经被宏定义 (用户1代表1, 用户2代表2)
     break;    
     }
    }
 }


 void game()
 {
  int board[ROW][COL];//定义一个二维数组
  memset(board,0,sizeof(board));//使用memset将二维数组初始化为0
  int result=0;
  do
  {
  showboard(board,ROW,COL);//显示棋盘

   playermove(board,ROW,COL,PLAYER1);//用户1进行下棋,落子

   result= isover(board,ROW,COL);//判定 共有四种情况 用户1赢 用户2赢 平局 继续
   if(NEXT!=result)//NEXT代表要继续,反之要出结果: 用户1赢 用户2赢 平局
   {  
      break;
   }
   showboard(board,ROW,COL);//将用户1下好的步 显示到棋盘中

    playermove(board,ROW,COL,PLAYER2);//用户2进行下棋,落子
    if(result!=NEXT)
    {
     break;
    }
    showboard(board,ROW,COL);//将用户2下好的步,显示到棋盘中

   }while(1);

   switch(result)
   {
    case PLAYER1_WIN: //用户1赢
     printf("用户1赢\n");
     break;
    case PLAYER2_WIN: //用户2赢
     printf("用户2赢\n");
     break;
    case DRAW:       //平局
     printf("平局\n");
     break;
   }
 }

2. game.h

#pragma once //为了防止头文件的多次重复利用
#include<stdio.h>
#include<string.h>
#define ROW 20
#define COL 20
#define NEXT 0
#define PLAYER1 1//默认用户1 的编号1
#define PLAYER2 2//默认用户2 的编号2
#define PLAYER1_WIN 1//表示用户1赢
#define PLAYER2_WIN 2//表示用户2赢
#define DRAW        3//表示平局
void showboard(int board[][COL],int row,int col);
void playermove(int board[][COL],int row, int col,int who);
int isover(int board[][COL],int row,int col);

enum dir
{
    LEFT,//左
    RIGHT,//右
    UP,//上
    DOWN,//下
    LEFT_UP,//左上
    LEFT_DOWN,//左下
    RIGHT_UP,//右上
    RIGHT_DOWN//右下
};

3.main.c

#include "game.h"
int main()
{
int result=0;
 do
 {
  menu();
  scanf("%d",&result);
  switch(result)
  {
    case 1:
      game();
      break;
    case 0:
      printf("程序结束\n");
      break;
    default:
      printf("输入错误,重新输入\n");
      break;
   }
 }
 while(result);

 return 0;
 }

4. makefile

game :main.c game.c
	gcc $^ -o $@ 
.PHONY:clean
clean:
	rm -f game
  • 收藏
  • 11评论
  • 分享
  • 举报

上一篇:替换空格问题


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK