C语言实现井字棋详解

编辑: admin 分类: c#语言 发布时间: 2021-12-12 来源:互联网
目录
  • 1.主函数
  • 2.menu菜单
  • 3.test函数
  • 4.game函数(1)
    • 4.1数据存储的二维数组:InitBoard
    • 4.2棋盘的打印:DisplayBoard
    • 4.3玩家下棋:PlayerMove
    • 4.4电脑下棋 :ComputerMove
    • 4.5输赢的判断 ;Win
    • 4.6平局的判定 :FULL
  • 5.game函数
    • 总结

      1.主函数

      这个代码很长,我们可以把它全部写在主函数里面。但是十分不推荐这么做。以后工作以后,很多时候我们负责的只是一个板块,汇总时只需要主函数调用每个人写的函数就能完成复杂项目。在这里我们先写主函数。

      #include<stdio.h>
      #include<time.h>
      #define ROW 3
      #define COL 3
      //这是对于行和列的初始化
      int main()
      {
      test();
      return 0;
      }

      2.menu菜单

      菜单十分容易完成

      void menu()
      {
      printf("输入1开始游戏");
      printf("输入0开始游戏");
      }

      3.test函数

      主函数中引用了test函数,我们现在写一个test函数,返回类型void,选择用do while循环来完成大部分函数

      void text()
      {
      int input = 0;
      srand((unsigned int)time(NULL));
      do
       {
        switch(input)
        {
         case 1:
           game();
           break;
         case 2:
           printf("退出游戏\n");
           break;
         default:
           printf("选择错误,请重新输入\n");
           break;
        }
       }while(input);
      }

      4.game函数(1)

      game函数内部仍然需要引用许多函数,对于一个三乘三的棋盘来说,有以下的步骤:

      数据存储到一个字符的二维数组中,玩家下棋是'*',电脑下棋是'#'数组的内容应该是全部空格

      初始化棋牌

      打印棋盘

      下棋

      4.1数据存储的二维数组:InitBoard

      这个函数的作用是把该二维数组全部初始化成为空格

      void InitBoard(char arr[ROW][COL],int row,int col)
      //这里的大写的BOW COL是传入的数组的值,小写的bow col是新的行和列
      {
       int i = 0;
       int j = 0;
       for(i = 0;i<row;i++)
       {
        for(j = 0;j<col;j++)
        {
         board[i][j] = ' ';
        }
       }
      }

      4.2棋盘的打印:DisplayBoard

      这个函数是把棋盘的形状打印出来

      void DisplayBoard(char board[ROW][COL], int row, int col)
      {
      	int i = 0;
      	int j = 0;
      	for (i = 0; i < row; i++)
      	{
      		for (j = 0; j < col; j++)
      		{
      			printf(" %c ", board[i][j]);
      			if (j < col - 1)
      			{
      				printf("|");
      			}
      		}
      		printf("\n");
      		if (i < row - 1)
      		{
      			for (j = 0; j < col; j++)
      			{
      				printf("---");
      					if (j < col - 1)
      					{
      						printf("|");
      					}
      			}
      		}
      		printf("\n");
      	}
      }

      4.3玩家下棋:PlayerMove

      先写玩家下棋:思路是如果玩家输入的地址原来为空格,那么就把这个位置重新定义为 *

      void PlayerMove(char board[ROW][COL],int row,int col)
      {
       printf("玩家下棋");
       int x = 0;
       int y = 0;
       while(1)
       {
         scanf("%d %d",&x,&y);
         if(x>=1&&x<=row&&y>=1&&y<=col)//防止输入非法棋子位置
         {
           if(board[x-1][y-1] == ' ')//注意这里的x-1和y-1,玩家在输入的时候输入的假如是1 2,那么给电脑的值就是0 1,这么做是为了与二维数组的下标对应
           {
             board[x-1][y-1] = '*';//注意这里只有一个等号!!!与上面不同,这里是重新定义而上面是相等的时候
             break;
           }
           else
           {
             printf("该坐标被占用,请重新输入\n");
           }
         }
         else
         {
          printf("输入非法,请重新输入");
         }
        }
      }

      4.4电脑下棋 :ComputerMove

      再写电脑下棋:思路是如果电脑输入的地址原来为空格,那么就把这个位置重新定义为 #,只不过不同的是电脑输入的x和y是用rand()%3设置出来的随机值,所以我们还要在前面的test函数中放下srand的设置。

      void ComputerMove(char board[ROW][COL],int row,int col)
      {
       int x = 0;
       int y = 0;
       printf("电脑下棋\n");
       while(1)
       {
        x = rand()%ROW//此时ROW为3,即x等于0到2的随机值
        y = rand()%COL//此时COL为3,即Y等于0到2的随机值
        if(board[x][y] == '')
        {
          board[x][y] = '#';
          break;
        }
       }
      }

      4.5输赢的判断 ;Win

      我们要有判断输赢的代码,并且初始化一个值让其接受返回值

      玩家赢 - '*'
      电脑赢 - '#'
      平均 --- 'Q'
      继续 ----'C'

      char Win(char board[ROW][COL], int row, int col)
      {
       int i = 0;
       for (i = 0; i < row; i++)//看一下横着的/竖着的3个符号是否相等,返回一个值让game()中的ret接收
      	{
      		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1]!='')
      		{
      			return board[i][1];
      		}
      	}
       for (i = 0; i < col; i++)
      	{
      		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i]!=' ')
      		{
      			return board[0][i];
      		}
      	}
      		if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1]!=' ')
      		{
      			return board[1][1];
      		}
       if(1 == FULL(board,row,col))
       {
        return 'Q';//如果经过FULL函数判定棋盘满了那么返回一个Q让ret接收,否则返回C
       }
        return 'C';
      }

      4.6平局的判定 :FULL

      因为要返回值,所以这个函数用int类型存放数据

      int Full(char board[ROW][COL], int row, int col)
      {
       int i = 0;
       int j = 0;
       for(i = 0;i<row;i++)
        {
         for(j = 0;j<col;j++)
          {
            if(board[i][j] == ' ')
            {
               return 0;//返回值为0
            }
          }  
        }
        return 1;//如果棋盘满了则返回1
      }

      5.game函数

      现在可以把所有的函数引用了

      void game()
      {
      	char board[ROW][COL] = {0};
      	InitBoard(board, ROW, COL);
      	DisplayBoard(board, ROW, COL);
      	char ret = 0;//初始化ret,ret为前面说的那个返回值
          //判断输赢的代码
          //玩家赢 - '*'
          //电脑赢 - '#'
          //平均 --- 'Q'
          //继续 ----'C'
      	while (1)
      	{
      		PlayerMove(board, ROW, COL);
      		DisplayBoard(board, ROW, COL);
      		ret = Win(board, ROW, COL);
      		if (ret != 'C')
      		{
      			break;
      		}
      		ComputerMove(board, ROW, COL);
      		DisplayBoard(board, ROW, COL);
      		ret = Win(board, ROW, COL);
      		if (ret != 'C')
      		{
      			break;
      		}
      	}
       if (ret == '*')//到这里才分别判定返回ret的所有值
      	{
      		printf("恭喜你你赢了!\n");
      	}
      	else if(ret == '#')
      	{
      		printf("很遗憾你输了!\n");
      	}
      	else
      	{
      		printf("平局\n");
      	}
      	printf("\n");
      }

      总结

      可以吧game.c和test.c分别当做两个源文件,test.c中引用game.c,这样代码也会更加清晰。不管有多少函数需要引用,只需要写出函数的本体再引用,这样一个庞大的代码就被我们拆分成了一段一段小代码,难度也就没那么大了。

      本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注海外IDC网的更多内容!

      【本文来源:迪拜服务器 转载请说明出处】