【C语言】手把手实现n子棋游戏(超详细捏)

1. n子棋游戏简介

两个玩家轮流在棋盘上放置棋子,谁先在横、竖或者斜方向上连成n个棋子,谁就获胜。如果棋盘下满但是没分出胜负则平局。
本篇文章要实现的是在n x n大小的棋盘中玩家与电脑下n子棋(不做图形界面)
下图是以三子棋为例。
Alt

2. 实现n子棋游戏函数前

本篇使用C语言实现n子棋。第二节内容只用代码实现玩游戏前后的流程。

2.1. 应用多文件的形式写代码

创建一个头文件(.h文件),两个源文件(.c文件)。各个文件的功能:

  • text.c文件:测试游戏
  • game.c文件:游戏函数的具体实现
  • game.h文件:游戏函数的声明

2.2. 游戏菜单

首先先不考虑n子棋游戏的具体实现,先在test.c文件中梳理玩游戏前后的流程
C语言程序的执行从main函数开始,所以先把main函数敲上。

//test.c文件

int main()
{
    
    

	return 0;
}

游戏开始前先写一个菜单函数,显示游戏菜单,方便玩家选择。这里使用了printf,scanf函数需要包含#include<stdio.h>文件。然后让玩家输入模式,玩家输入1就开始游戏,玩家输入0结束游戏:

//test.c文件

#include<stdio.h>

void menu()
{
    
    
	printf("#####################\n");
	printf("####   1.Play    ####\n");
	printf("####   0.Exit    ####\n");
	printf("#####################\n");
}

int main()
{
    
    
	int mode = 0;
	menu();//调用菜单
	printf("请输入模式(1/0):");
	scanf("%d", &mode);
	return 0;
}

2.3. 根据玩家输入执行不同分支

首先要对玩家输入的值进行判断。因为玩家有可能输入除了1和0以外的数字,所以有3个分支。这里用switch语句实现。

//test.c文件

#include<stdio.h>

void menu()
{
    
    
	printf("#####################\n");
	printf("####   1.Play    ####\n");
	printf("####   0.Exit    ####\n");
	printf("#####################\n");

}


int main()
{
    
    
	int mode = 0;
	menu();
	printf("请输入模式(1/0):");
	scanf("%d", &mode);

	switch (mode)
	{
    
    
	case 1:			
		printf("开始游戏\n");//游戏的实现先忽略
		break;
	case 0:
		printf("退出游戏\n");
		break;
	default:
		printf("输入错误,请重新输入\n");
		break;
	}
	
	return 0;
}

如果玩完一局还想再玩的话需要用到循环。因为第一局可以直接从打印菜单开始执行,所以循环语句比较适合用do while语句。函数的判断条件直接看玩家输入的值,如果是0,0为假,正好会跳出循环。如果是1或其他数字,都需要继续执行循环体。

//test.c文件

#include<stdio.h>

void menu()
{
    
    
	printf("#####################\n");
	printf("####   1.Play    ####\n");
	printf("####   0.Exit    ####\n");
	printf("#####################\n");
}


int main()
{
    
    
	int mode = 0;
	do
	{
    
    
		menu();
		printf("请输入模式(1/0):");
		scanf("%d", &mode);

		switch (mode)
		{
    
    
		case 1:
			printf("开始游戏\n");//游戏的实现先忽略
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (mode);
	
	return 0;
}

这就是在开始游戏前需要考虑的流程。把switch语句中case 1里printf(“开始游戏\n”);语句下加上game函数,下面的章节主要实现game函数,即n子棋游戏的具体实现,

//test.c文件

#include<stdio.h>

void menu()
{
    
    
	printf("#####################\n");
	printf("####   1.Play    ####\n");
	printf("####   0.Exit    ####\n");
	printf("#####################\n");
}

void game()
{
    
    
	//n子棋的具体实现
}


int main()
{
    
    
	int mode = 0;
	do
	{
    
    
		menu();
		printf("请输入模式(1/0):");
		scanf("%d", &mode);

		switch (mode)
		{
    
    
		case 1:
			printf("开始游戏\n");
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (mode);
	
	return 0;
}

测试如下:
Alt

3. n子棋游戏函数game();的具体实现

第3节的代码主要针对game函数。

//test.c文件

void game()
{
    
    
	//n子棋的具体实现
}

3.1. 初始化棋盘 InitBoard

下棋的过程中要存储玩家和电脑棋子的位置,需要用到二维数组。还没开始下棋之前让二维数组中的每个元素存储空格。为了方便分析,棋盘的行数(ROW)和列数(COL)先指定为3,也就是先默认为3子棋。
从这一步开始要同步处理test.c文件,game.c文件和game.h文件(包含自己创造的头文件用双引号 #include"game.h")

  1. 调用InitBoard函数(在test.c文件中的game函数中):
//test.c文件

//因为test.c文件和game.c文件都需要调用printf函数,直接把#include<stdio.h>放在game.h文件里,
//然后在game.c和test.c两个文件中包含 #include"game.h" 即可
#include"game.h"

void game()
{
    
    
	//定义一个二维数组存储棋子
	char board[ROW][COL] = {
    
    0};

	//初始化棋盘
	InitBoard(board, ROW, COL);
}
  1. 声明InitBoard函数(在game.h文件中声明):
//game.h文件

//因为test.c文件和game.c文件都需要调用printf函数,直接把#include<stdio.h>放在game.h文件里,
//然后在game.c和test.c两个文件中包含 #include"game.h" 即可
#include<stdio.h>
#define ROW 3
#define COL 3

void InitBoard(char board[ROW][COL],int row,int col);

在game.h中定义行数(ROW)和列数(COL)的原因:为了方便改变棋盘的行数和列数。想下5子棋只要把ROW和COL的3改成5即可。

  1. 定义InitBoard函数(在game.c文件中实现):
//game.c文件

//因为test.c文件和game.c文件都需要调用printf函数,直接把#include<stdio.h>放在game.h文件里,
//然后在game.c和test.c两个文件中包含 #include"game.h" 即可
#include"game.h"

void InitBoard(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++)
   	{
    
    
   		board[i][j] = ' ';
   	}
   }
}

3.2. 棋盘的设计与打印 DisplayBoard

只有玩家看到棋盘了才能下棋。我们需要设计一个棋盘让玩家既看得到在棋盘又能看得到棋盘上面的棋子,而不是只显示棋子。

  • 棋盘设计:
    如果下的是三子棋,那么三子棋的棋盘样式如下,红色框框表示棋子的位置,黑色的字符表示棋盘的形状。一行打印数据,一行打印分割线
    Alt
    Alt

代码实现如下:

  1. DisplayBoard函数的调用:
//test.c文件

#include"game.h"//包含自己写的头文件

void game()
{
    
    
	//定义一个二维数组存储棋子
	char board[ROW][COL] = {
    
    0};

	//初始化棋盘
	InitBoard(board, ROW, COL);

	//棋盘的打印
	DisplayBoard(board, ROW, COL);
}
  1. DisplayBoard函数的声明:
//game.h文件

#include<stdio.h>
#define ROW 3
#define COL 3

void InitBoard(char board[ROW][COL],int row,int col);
void DisplayBoard(char board[ROW][COL],int row,int col);
  1. DisplayBoard函数的定义(实现):
//game.c文件

#include"game.h"//包含自己写的头文件

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");
	}
}

测试如下:
Alt
如果想要玩5子棋只需改动game.h文件里的行数和列数即可。
Alt

3.3. 玩家下棋 PlayerMove

玩家如何下棋?
因为没有做图形化界面,玩家需要在终端以输入坐标的形式把棋子落在要下的地方,坐标如下,以三子棋为例:
Alt
左上角为坐标 1 1 ,表示第一行第一列。从上到下行数依次增加,从左到右列数依次增加。
代码实现:

  1. PlayerMove函数的调用,这里默认让玩家先下棋:
//test.c文件

void game()
{
    
    
	//定义一个二维数组存储棋子
	char board[ROW][COL] = {
    
    0};
	//初始化棋盘
	InitBoard(board, ROW, COL);
	//棋盘的打印
	DisplayBoard(board, ROW, COL);

	//玩家下棋
	PlayerMove(board, ROW, COL);
	//玩家下棋之后要让玩家看到此时棋盘上面的棋子
	DisplayBoard(board, ROW, COL);
}

2.PlayerMove函数的声明:

//game.h文件

#include<stdio.h>
#define ROW 3
#define COL 3

void InitBoard(char board[ROW][COL],int row,int col);
void DisplayBoard(char board[ROW][COL],int row,int col);
void PlayerMove(char board[ROW][COL],int row,int col);

3.PlayerMove函数的定义(实现), 需要考虑玩家下棋的合法性,如果不合法则需要让玩家重新输入,所以需要用到循环。这里指定玩家的棋子为 * :

//game.c文件

#include"game.h"

void PlayerMove(char board[ROW][COL], int row, int col)
{
    
    
	printf("玩家下棋\n");
	while (1)
	{
    
    
		printf("请输入要落子的坐标:");
		int x = 0;
		int y = 0;
		scanf("%d %d", &x, &y);
		//需要判断玩家下棋的合法性,如果不合法,需要重新下
	    //1.如果落子的位置超出棋盘范围,需要重新下
	    //2.落子时需要判断该位置是不是空格,不是空格需要重新
		if ((x >= 1) && (x <= row) && (y >= 1) && (y <= col) && (board[x - 1][y - 1] == ' '))
		{
    
    
			board[x - 1][y - 1] = '*';
			break;
		}
		else
		{
    
    
			printf("该位置已有棋子或者该位置超出棋盘的范围,请重新落子。\n");
		}
	}
}

测试如下:
Alt
把行数和列数改成5,测试如下:
Alt

3.4. 电脑下棋 ComputerMove

先不考虑电脑下棋时的复杂算法,这里只用两个简单的随机数作为电脑下棋的坐标,以实现电脑下棋。C语言的随机数用rand函数,使用rand函数之前需要先在main函数调用srand函数,参数是time函数(time函数的返回值强制转换为unsigned int类型以获取时间戳,不要忘了rand函数,srand函数和time函数都要包含头文件)。

在test.c文件中的主函数里调用srand函数:

//test.c文件

#include"game.h"//包含自己写的头文件

int main()
{
    
    
	int mode = 0;
	
	//使用rand函数之前需要先在main函数调用srand函数
	srand((unsigned int)time(NULL));
	
	do
	{
    
    
		menu();
		printf("请输入模式(1/0):");
		scanf("%d", &mode);

		switch (mode)
		{
    
    
		case 1:
			printf("开始游戏\n");
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (mode);
	
	return 0;
}

在game.h文件里包含rand函数,srand函数和time函数的头文件:

//game.h文件

#include<stdio.h>//printf,scanf
#include<stdlib.h>//rand,srand
#include<time.h>//time

电脑下棋的完整代码实现:

  1. ComputerMove函数的调用:
//test.c文件

#include"game.h"//包含自己写的头文件

void game()
{
    
    
	//定义一个二维数组存储棋子
	char board[ROW][COL] = {
    
    0};
	//初始化棋盘
	InitBoard(board, ROW, COL);
	//棋盘的打印
	DisplayBoard(board, ROW, COL);
	//玩家下棋
	PlayerMove(board, ROW, COL);
	//玩家下棋之后要让玩家看到此时棋盘上面的棋子
	DisplayBoard(board, ROW, COL);

	//电脑下棋
	ComputerMove(board, ROW, COL);
	//电脑下棋之后要让玩家看到此时棋盘上面的棋子
	DisplayBoard(board, ROW, COL);
}
  1. ComputerMove函数的声明:
//game.h文件

#include<stdio.h>//printf,scanf
#include<stdlib.h>//rand,srand
#include<time.h>//time

#define ROW 5
#define COL 5

void InitBoard(char board[ROW][COL],int row,int col);
void DisplayBoard(char board[ROW][COL],int row,int col);
void PlayerMove(char board[ROW][COL],int row,int col);
void ComputerMove(char board[ROW][COL], int row, int col);

3.ComputerMove函数的定义(实现),注意电脑要把棋下在没有棋的地方,有棋的话要重新下,这里指定电脑的棋子为 # :

//game.c文件

#include"game.h"//包含自己写的头文件

void ComputerMove(char board[ROW][COL], int row, int col)
{
    
    
	printf("电脑下棋\n");
	while (1)
	{
    
    
		int x = 0;
		int y = 0;
		x = rand() % row;//取余row的数一定在0到row之间,col同理
		y = rand() % col;
		if (board[x][y] == ' ')
		{
    
    
			board[x][y] = '#';
			break;
		}
	}
}

测试如下:
三子棋:
Alt
五子棋:

Alt
此时玩家和电脑都只能下一次,在test.c文件的game函数里加个循环就能连续轮流下一次:

//test.c文件

#include"game.h"//包含自己写的头文件

void game()
{
    
    
	//定义一个二维数组存储棋子
	char board[ROW][COL] = {
    
    0};
	//初始化棋盘
	InitBoard(board, ROW, COL);
	//棋盘的打印
	DisplayBoard(board, ROW, COL);
	while (1)
	{
    
    
		//玩家下棋
		PlayerMove(board, ROW, COL);
		//玩家下棋之后要让玩家看到此时棋盘上面的棋子
		DisplayBoard(board, ROW, COL);
		//电脑下棋
		ComputerMove(board, ROW, COL);
		//电脑下棋之后要让玩家看到此时棋盘上面的棋子
		DisplayBoard(board, ROW, COL);
	}
}

再测试,行数和列数设为3:
Alt
此时已经可以实现多次轮流下棋了,接下来再写一个判断输赢的函数即可,整个n子棋游戏快要实现了!!!

3.5.判断输赢 Iswin

这里需要回顾游戏规则:两个玩家轮流在棋盘上放置棋子,谁先在横、竖或者斜方向上连成n个棋子,谁就获胜。如果棋盘下满但是没分出胜负则平局。所以其中一个玩家下了棋之后其实有4种情况:

  1. 玩家赢了
  2. 电脑赢了
  3. 平局
  4. 没分出胜负,继续下棋

我们可以写一个Iswin函数用来判断比赛情况,Iswin函数通过返回不同的值执行不同的步骤:

  • 玩家赢: 返回 ’ * ’
  • 电脑赢: 返回 ‘ # ’
  • 平局: 返回 ’ D ’
  • 继续: 返回 ’ C ’

Iswin函数的调用如下:

//test.c文件

#include"game.h"//包含自己写的头文件

void game()
{
    
    
   //定义一个二维数组存储棋子
   char board[ROW][COL] = {
    
    0};
   //初始化棋盘
   InitBoard(board, ROW, COL);
   //棋盘的打印
   DisplayBoard(board, ROW, COL);
   while (1)
   {
    
    
   	//玩家下棋
   	PlayerMove(board, ROW, COL);
   	//玩家下棋之后要让玩家看到此时棋盘上面的棋子
   	DisplayBoard(board, ROW, COL);
   	//判断
   	if (Iswin(board, ROW, COL) != 'C')
   		break;

   	//电脑下棋
   	ComputerMove(board, ROW, COL);
   	//电脑下棋之后要让玩家看到此时棋盘上面的棋子
   	DisplayBoard(board, ROW, COL);
   	//判断
   	if (Iswin(board, ROW, COL) != 'C')
   		break;
   }

   //判断比赛结果
   if (Iswin(board, ROW, COL) == '*')
   	printf("恭喜玩家获胜!!!\n");
   else if (Iswin(board, ROW, COL) == '#')
   	printf("电脑获胜。\n");
   else if(Iswin(board, ROW, COL) == 'D')
   	printf("双方平局。\n");
}

Iswin函数调用记得在game.h文件中声明:

//game.h文件

#include<stdio.h>//printf,scanf
#include<stdlib.h>//rand,srand
#include<time.h>//time

#define ROW 3
#define COL 3

void InitBoard(char board[ROW][COL],int row,int col);
void DisplayBoard(char board[ROW][COL],int row,int col);
void PlayerMove(char board[ROW][COL],int row,int col);
void ComputerMove(char board[ROW][COL], int row, int col);
char Iswin(char board[ROW][COL],int row,int col);

值得注意的是:Iswin函数有返回字符类型,所以返回类型是char而不是void

Iswin函数的实现要考虑:

  1. 判断横向是否有n个相同的棋子
  2. 判断纵向是否有n个相同的棋子
  3. 判断右斜方向上是否有n个相同的棋子
  4. 判断左斜方向上是否有n个相同的棋子
  5. 判断平局(棋盘下满棋了,但是没分出胜负)
  6. 如果以上情况都不满足,继续游戏

Iswin函数的定义(实现):

//game.h文件

#include"game.h"

char Iswin(char board[ROW][COL], int row, int col)
{
    
    
	int i = 0;
	int j = 0;

	//1. 判断横方向是否有n个相同的棋子
	for (i = 0; i < row; i++)
	{
    
    
		//默认第i行已有n个相同的棋子
		int flag = 1;

		if (board[i][0] != ' ')
		{
    
    
			//把第i行的第一列做对照
			char contrast = board[i][0];
			for (j = 1; j < col; j++)
			{
    
    
				if (board[i][j] != contrast)
				{
    
    
					//第i行有不同的棋子,flag会发生改变
					flag = 0;
				}
			}
			//flag没有发生改变,说明第i行有n个相同的棋子,返回n个相同的棋子的符号
			if (flag == 1)
				return contrast;
		}
	}


	//2. 判断纵方向是否有n个相同的棋子
	for (i = 0; i < col; i++)
	{
    
    
		//默认第i列已有n个相同的棋子
		int flag = 1;

		if (board[0][i] != ' ')
		{
    
    
			//把第i列的第一行做对照
			char contrast = board[0][i];
			for (j = 1; j < row; j++)
			{
    
    
				if (board[j][i] != contrast)
				{
    
    
					//第i列有不同的棋子,flag会发生改变
					flag = 0;
				}
			}
			//flag没有发生改变,说明第i列有n个相同的棋子,返回n个相同的棋子的符号
			if (flag == 1)
				return contrast;
		}
	}


	//默认右斜方向上已有n个相同的棋子
	int flag = 1;
	if (board[0][0] != ' ')
	{
    
    
		//3. 判断右斜方向上是否有n个相同的棋子
		for (i = 1; i < row; i++)
		{
    
    
			//把board[0][0]位置的棋子做对照(左上角)
			char contrast = board[0][0];
			if (board[i][i] != contrast)
			{
    
    
				//右斜方向上有不同的棋子,flag会发生改变
				flag = 0;
			}
		}
		//flag没有发生改变,说明右斜方向上有n个相同的棋子,返回n个相同的棋子的符号
		if (flag == 1)
			return board[0][0];
	}
	

	//上面已经定义了flag,下面只需赋值1给flag即可
	flag = 1;
	if (board[0][COL-1] != ' ')
	{
    
    
		//4. 判断左斜方向上是否有n个相同的棋子
		for (i=1 , j=col-2; (i<row) && (j>=0); i++, j--)
		{
    
    
			//把board[0][COL-1]位置的棋子做对照(右上角)
			char contrast = board[0][col - 1];
			if (board[i][j] != contrast)
			{
    
    
				//左斜方向上有不同的棋子,flag会发生改变
				flag = 0;
			}
		}
		//flag没有发生改变,说明左斜方向上有n个相同的棋子,返回n个相同的棋子的符号
		if (flag == 1)
			return board[0][COL - 1];
	}

	//5. 判断平局
	if (Isfull(board, ROW, COL))
		return 'D';

	//6. 如果以上情况都不满足,继续游戏
	return 'C';
}

在第5种情况----判断平局中,因为前4种情况是判断谁胜谁负,没分出胜负就只需判断棋盘是否满了,所以可以再写一个Isfull函数用来判断棋盘是否满了。

//game.c文件

#include"game.h"

int Isfull(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] == ' ')
				//如果有空格,说明棋盘没下满,返回0
				return 0;
		}
	}
	//如果程序能走到这一步,说明棋盘上面已经没有空格了,返回1
	return 1;
}

测试(这次测试可以完整的玩若干次n子棋游戏了,这次测试我把ROW和COL调为3):
Alt
当然,五子棋也是可以的,只要在game.h文件中把ROW和COL调成5即可。
Alt

4.完整代码(可复制)

完整代码分三个文件,一个头文件,两个源文件

4.1. game.h

#include<stdio.h>//printf,scanf
#include<stdlib.h>//rand,srand
#include<time.h>//time

#define ROW 5
#define COL 5

void InitBoard(char board[ROW][COL],int row,int col);
void DisplayBoard(char board[ROW][COL],int row,int col);
void PlayerMove(char board[ROW][COL],int row,int col);
void ComputerMove(char board[ROW][COL], int row, int col);
char Iswin(char board[ROW][COL],int row,int col);

4.2. game.c

#include"game.h"

void InitBoard(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++)
		{
    
    
			board[i][j] = ' ';
		}
	}
}

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");
	}
}

void PlayerMove(char board[ROW][COL], int row, int col)
{
    
    
	printf("玩家下棋\n");
	while (1)
	{
    
    
		printf("请输入要落子的坐标:");
		int x = 0;
		int y = 0;
		scanf("%d %d", &x, &y);
		//需要判断玩家下棋的合法性,如果不合法,需要重新下
	    //1.如果落子的位置超出棋盘范围,需要重新下
	    //2.落子时需要判断该位置是不是空格,不是空格需要重新
		if ((x >= 1) && (x <= row) && (y >= 1) && (y <= col) && (board[x - 1][y - 1] == ' '))
		{
    
    
			board[x - 1][y - 1] = '*';
			break;
		}
		else
		{
    
    
			printf("该位置已有棋子或者该位置超出棋盘的范围,请重新落子。\n");
		}
	}
}

void ComputerMove(char board[ROW][COL], int row, int col)
{
    
    
	printf("电脑下棋\n");
	while (1)
	{
    
    
		int x = 0;
		int y = 0;
		x = rand() % row;
		y = rand() % col;
		if (board[x][y] == ' ')
		{
    
    
			board[x][y] = '#';
			break;
		}
	}
}

int Isfull(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] == ' ')
				//如果有空格,说明棋盘没下满,返回0
				return 0;
		}
	}
	//如果程序能走到这一步,说明棋盘上面已经没有空格了,返回1
	return 1;
}

char Iswin(char board[ROW][COL], int row, int col)
{
    
    
	int i = 0;
	int j = 0;

	//1. 判断横方向是否有n个相同的棋子
	for (i = 0; i < row; i++)
	{
    
    
		//默认第i行已有n个相同的棋子
		int flag = 1;

		if (board[i][0] != ' ')
		{
    
    
			//把第i行的第一列做对照
			char contrast = board[i][0];
			for (j = 1; j < col; j++)
			{
    
    
				if (board[i][j] != contrast)
				{
    
    
					//第i行有不同的棋子,flag会发生改变
					flag = 0;
				}
			}
			//flag没有发生改变,说明第i行有n个相同的棋子,返回n个相同的棋子的符号
			if (flag == 1)
				return contrast;
		}
	}


	//2. 判断纵方向是否有n个相同的棋子
	for (i = 0; i < col; i++)
	{
    
    
		//默认第i列已有n个相同的棋子
		int flag = 1;

		if (board[0][i] != ' ')
		{
    
    
			//把第i列的第一行做对照
			char contrast = board[0][i];
			for (j = 1; j < row; j++)
			{
    
    
				if (board[j][i] != contrast)
				{
    
    
					//第i列有不同的棋子,flag会发生改变
					flag = 0;
				}
			}
			//flag没有发生改变,说明第i列有n个相同的棋子,返回n个相同的棋子的符号
			if (flag == 1)
				return contrast;
		}
	}


	//默认右斜方向上已有n个相同的棋子
	int flag = 1;
	if (board[0][0] != ' ')
	{
    
    
		//3. 判断右斜方向上是否有n个相同的棋子
		for (i = 1; i < row; i++)
		{
    
    
			//把board[0][0]位置的棋子做对照(左上角)
			char contrast = board[0][0];
			if (board[i][i] != contrast)
			{
    
    
				//右斜方向上有不同的棋子,flag会发生改变
				flag = 0;
			}
		}
		//flag没有发生改变,说明右斜方向上有n个相同的棋子,返回n个相同的棋子的符号
		if (flag == 1)
			return board[0][0];
	}
	

	//上面已经定义了flag,下面只需赋值1给flag即可
	flag = 1;
	if (board[0][COL-1] != ' ')
	{
    
    
		//4. 判断左斜方向上是否有n个相同的棋子
		for (i=1 , j=col-2; (i<row) && (j>=0); i++, j--)
		{
    
    
			//把board[0][COL-1]位置的棋子做对照(右上角)
			char contrast = board[0][col - 1];
			if (board[i][j] != contrast)
			{
    
    
				//左斜方向上有不同的棋子,flag会发生改变
				flag = 0;
			}
		}
		//flag没有发生改变,说明左斜方向上有n个相同的棋子,返回n个相同的棋子的符号
		if (flag == 1)
			return board[0][COL - 1];
	}

	//5. 判断平局
	if (Isfull(board, ROW, COL))
		return 'D';

	//6. 如果以上情况都不满足,继续游戏
	return 'C';
}

4.3. test.c

#include"game.h"//包含自己写的头文件

void menu()
{
    
    
	printf("#####################\n");
	printf("####   1.Play    ####\n");
	printf("####   0.Exit    ####\n");
	printf("#####################\n");
}

void game()
{
    
    
	//定义一个二维数组存储棋子
	char board[ROW][COL] = {
    
    0};
	//初始化棋盘
	InitBoard(board, ROW, COL);
	//棋盘的打印
	DisplayBoard(board, ROW, COL);
	while (1)
	{
    
    
		//玩家下棋
		PlayerMove(board, ROW, COL);
		//玩家下棋之后要让玩家看到此时棋盘上面的棋子
		DisplayBoard(board, ROW, COL);
		//判断
		if (Iswin(board, ROW, COL) != 'C')
			break;

		//电脑下棋
		ComputerMove(board, ROW, COL);
		//电脑下棋之后要让玩家看到此时棋盘上面的棋子
		DisplayBoard(board, ROW, COL);
		//判断
		if (Iswin(board, ROW, COL) != 'C')
			break;
	}

	//判断比赛结果
	if (Iswin(board, ROW, COL) == '*')
		printf("恭喜玩家获胜!!!\n");
	else if (Iswin(board, ROW, COL) == '#')
		printf("电脑获胜。\n");
	else if(Iswin(board, ROW, COL) == 'D')
		printf("双方平局。\n");
}


int main()
{
    
    
	int mode = 0;

	srand((unsigned int)time(NULL));
	do
	{
    
    
		menu();
		printf("请输入模式(1/0):");
		scanf("%d", &mode);

		switch (mode)
		{
    
    
		case 1:
			printf("开始游戏\n");
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (mode);
	
	return 0;
}

结语

非常感谢您能够阅读完这篇文章,如果有任何建议或纠正欢迎在评论区留言。如果您认为这篇文章对您有所收获,点一个小小的赞就是我创作的巨大动力,谢谢!

猜你喜欢

转载自blog.csdn.net/weixin_73276255/article/details/131375749