网站建设资讯

NEWS

网站建设资讯

高质量C语言实现三子棋-创新互联

直入主题,为了实现一个三子棋小游戏,我们先来看一下三子棋是怎么玩的。

创新互联公司是一家网站设计制作、成都网站建设,提供网页设计,网站设计,网站制作,建网站,专业公司,网站开发公司,从2013年创立是互联行业建设者,服务者。以提升客户品牌价值为核心业务,全程参与项目的网站策划设计制作,前端开发,后台程序制作以及后期项目运营并提出专业建议和思路。

《三子棋》是一款古老的民间传统游戏,又被称为黑白棋、圈圈叉叉棋、井字棋、一条龙、九宫棋等。游戏分为双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子连成一条线的一方则视为胜利者。


为了给读者更直观的感受,接下来我们再来看一看用编程实现三子棋的成品是怎么样的。

接下来,我们将逐步实现三子棋这个小游戏,我会逐步细分到每一个函数保证读者的观感。


目录

一.打印菜单

二.实现主菜单功能

三.游戏函数

1.初始化棋盘

2.打印棋盘

3.玩家下棋

4.电脑下棋

5.判断输赢

(1)第一种方法

5.判断输赢

(2)第二种方法


一.打印菜单
#includevoid menu()
{
	printf("***********************************\n");
	printf("*********    1.三子棋     *********\n");
	printf("*********   0.退出游戏    *********\n");
	printf("***********************************\n");
}
int main()
{
	menu();
	return 0;
}

我们定义了一个函数menu()函数

名字:menu

类型: void(就如int类型返回整形,char类型返回字符类型,void类型就是无返回值)

返回值:无返回值

参数:无参数

功能:打印菜单

此函数只是打印菜单,没有需要说明的,读者自然能看懂。


运行截图:


二.实现主菜单功能
#includevoid menu()
{
	printf("***********************************\n");
	printf("*********    1.三子棋     *********\n");
	printf("*********   0.退出游戏    *********\n");
	printf("***********************************\n");
}
int main()
{
	int input = 0;//定义变量input接收输入值
	do {
		menu();
		printf("请选择->\n");
		scanf("%d", &input);
//---------------------------------------------
		switch (input)//通过switch读取input的值判断需要做什么
		{
		case 1:
			//game();//实现游戏的函数,暂时还没写
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入有误,请重新输入\n");
			break;
		}
//---------------------------------------------
	} while (input);//当input为0(退出游戏)时就跳出循环结束游戏,非0为真,继续循环
	return 0;
}

这一步只是利用do while循环和switch函数来实现主菜单功能,读者可以通过代码中的注释来读懂该段代码。


运行截图:(选择1并没有开始游戏是因为还没有开始写游戏本体代码)


三.游戏函数 1.初始化棋盘

三子棋是一个3乘3的棋盘,所以很容易想到用一个存放字符的类型为char的二维数组来实现,在游戏开始前,棋盘里应该都是空格,所以我们应该先创建一个char类型的二维数组并全部初始化为空格。

在此之前我们先定义一个game函数(类型为void),这个函数的功能是实现我们游戏本体的。

#define ROW 3
#define COL 3
void game()//定义游戏函数
{
	char board[3][3];//创建char类型的3乘3的数组
	InitBoard(board, ROW, COL);//这是初始化棋盘的函数
}

注意!这里我用了define来定义了ROW(行)和COL(列)均为3,这样可以增加代码的可读性。之后我将不会再显示这两行代码,也请读者记好这两行代码,这将使你受益匪浅。

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] = ' ';
		}
	}
}

这里的小写row和col均是形参,值分别等于ROW和COL的

我们定义了一个函数Initboard()函数

名字:Initboard

类型: void(就如int类型返回整形,char类型返回字符类型,void类型就是无返回值)

返回值:无返回值

参数:3个参数,char类型的二维数组board,int类型的row,int类型的col。

功能:初始化棋盘

我采用遍历(对数组每一个元素都进行访问)的形式将数组每个元素都初始化为了空格。

这里我们也可以使用一个库函数进行初始化。 

memset函数(需要引入头文件string.h)

功能:作用是将某一块内存中的内容全部设置为指定的值, 这个函数通常为新申请的内存做初始化工作。

memset(&board[0][0], ' ', row * col * sizeof(board[0][0]));
//第一个参数是一个地址,第二个参数是一个字符,也可以是一个值,第三个参数是字节数

2.打印棋盘

棋盘初始化之后我们就要打印棋盘了,下面是棋盘的图片。

可以看出棋盘是由一些 ‘-’ 和 ‘|’ 来打印的,下面我来为个位读者仔细分析这个棋盘。

(画图技术不好还请读者谅解)

我们可以将棋盘分为三组,每一组如图所示,一组分为上半部分和下半部分。

void PrintBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i< row; i++)//循环3次
	{
		for (j = 0; j< col; j++)//这个for打印的是上半部分,循环3次
		{
			printf(" %c |", board[i][j]);//结构为(空格)(数组的空格)(空格)(|)

		}
		printf("\n");

		for (j = 0; j< col; j++)//这个for打印的是下半部分,循环3次
		{
			printf("---|");//结构为(-)(-)(-)(|)
		}
		printf("\n");
	}
}

这里的小写row和col均是形参,值分别等于ROW和COL的

我们定义了一个函数printboard()函数

名字:printboard

类型: void(就如int类型返回整形,char类型返回字符类型,void类型就是无返回值)

返回值:无返回值

参数:3个参数,char类型的二维数组board,int类型的row,int类型的col。

功能:打印棋盘

这一段结合注释也希望读者能够看懂,可以自己结合上面的图画图分析。

运行截图:

很明显,这个棋盘和最开始演示的棋盘有亿些不同多了最右边一列和最底部的一行。这里的解决办法是加一个限制条件,打印每一行的最后一组时那一列不打印,打印最后一组时那一行也不打印。

void PrintBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i< row; i++)//循环3次
	{
		for (j = 0; j< col; j++)//这个for打印的是上半部分,循环3次
		{
			printf(" %c ", board[i][j]);//结构为(空格)(数组的空格)(空格)
			if (j + 1< col)//打印上半部分的最后一列时不打印(|)
				printf("|");
		}
		printf("\n");
		if (i + 1< row)//打印最后一组时不打印下半部分
		{
			for (j = 0; j< col; j++)//这个for打印的是下半部分,循环3次
			{
				printf("---");//结构为(-)(-)(-)
				if (j + 1< col)//打印下半部分的最后一列时不打印(|)
					printf("|");
			}
			printf("\n");
		}
	}
}

运行截图:


3.玩家下棋

这一块就比较简单了,我们需要接收玩家下达的指令,并且检查玩家给出的坐标是否超出棋盘或者该坐标是否已经有棋子了,判断一个坐标有无棋子就是判断该坐标是否为空格。

void Player(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("玩家下棋,请选择你的坐标\n");
	while (1)//循环,当棋子正确落下时跳出循环结束玩家下棋阶段
	{
		scanf("%d %d", &x, &y);//接收玩家下达的坐标
		if (x - 1 >= 0 && x - 1< row && y - 1 >= 0 && y - 1< col)//检查是否超出棋盘
		{
			if (board[x - 1][y - 1] != ' ')//检查该坐标是否有棋子
			{
				printf("你选择的地方已经有棋子了,请重新选择\n");
				continue; //当棋子没有正常落下时继续循环,直到棋子正确落下
			}
			board[x - 1][y - 1] = '*';
			break;//当棋子正确落下时跳出循环结束玩家下棋阶段
		}
		else
			printf("你选择的坐标非法,请重新选择\n");//当棋子没有正常落下时继续循环,直到棋子正确落下
	}
	printf("------------------------\n");
}

这里的小写row和col均是形参,值分别等于ROW和COL的

我们定义了一个函数player()函数

名字:Player

类型: void(就如int类型返回整形,char类型返回字符类型,void类型就是无返回值)

返回值:无返回值

参数:3个参数,char类型的二维数组board,int类型的row,int类型的col。

功能:玩家下棋

注意玩家下棋时的坐标是从1开始,而数组的下标是从零开始,所以我们需要将玩家输入的坐标减1。

运行截图:


4.电脑下棋

电脑下棋我们可以使用rand函数,通过取余ROW和COL来随机出电脑下棋的坐标,因为是取余得到的坐标,所以我们不用担心坐标是否会超出棋盘,只需判断该坐标处是否有棋子就行。

这里需要介绍一下rand函数的使用方法,简单来说就是首先需要一个srand函数来设置随机数生成器,srand里面的参数需要随时变化,这里我们可以让srand函数调用时间戳,就实现了随机数的生成。(rand函数生成的随机数范围是0-32767)

#include//rand和srand函数需要的头文件
#include//time函数需要的头文件
int main()
{
	int input = 0;//定义变量input接收输入值
	srand((unsigned int)time(NULL));//设置随机数生成器
	do {
		menu();
		printf("请选择->\n");
		scanf("%d", &input);
//---------------------------------------------
		switch (input)//通过switch读取input的值判断需要做什么
		{
		case 1:
			game();//实现游戏的函数
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入有误,请重新输入\n");
			break;
		}
//---------------------------------------------
	} while (input);//当input为0(退出游戏)时就跳出循环结束游戏,非0为真,继续循环
	return 0;
}

srand函数的参数是(unsigned int)所以就强制类型转换 ,time函数参数是指针,我们可以传一个空指针进去NULL。

void Computer(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("电脑下棋->\n");
	while (1)//循环和玩家下棋道理一样
	{
		x = rand() % row;//随机值取余row(3)得到 0 - 2的随机值
		y = rand() % col;//随机值取余row(3)得到 0 - 2的随机值
		if (board[x][y] == ' ')//判断该坐标是否有棋子
		{
			board[x][y] = '#';
			break;//成功下棋,跳出循环
		}
	}
}

这里的小写row和col均是形参,值分别等于ROW和COL的

我们定义了一个函数Computer()函数

名字:Computer

类型: void(就如int类型返回整形,char类型返回字符类型,void类型就是无返回值)

返回值:无返回值

参数:3个参数,char类型的二维数组board,int类型的row,int类型的col。

功能:电脑下棋

这里只需注意取余以及判断是否有棋子。 

运行截图: 


5.判断输赢 (1)第一种方法

三子棋输赢规则:“率先将自己的三个棋子连成一条线(横线、数线、斜线)的一方则视为胜利者。”

这里我有两种方法,这里先介绍比较容易理解的方法一。

思路:通过判断函数的返回值来确定是谁赢了,以及是否平局,或者是否还能继续下棋。

无论是电脑还是玩家下完棋都应该进行一次判断,下面是游戏函数的代码。

我们定义:‘*’是玩家赢,‘#’是电脑赢,‘Q’是平局,‘C’是继续下棋。

void game()//定义游戏函数
{
	char board[3][3];//创建char类型的3乘3的数组
	char ret = 0;//创建变量接收Judge函数的返回值
	InitBoard(board, ROW, COL);//这是初始化棋盘的函数
	while (1)//每一轮是玩家下棋,判断输赢,电脑下棋,判断输赢。循环每一轮直到有一方赢或者平局
	{
		PrintBoard(board, ROW, COL);//打印棋盘函数
		Player(board, ROW, COL);//玩家下棋函数
		ret = Judge(board, ROW, COL);//接收Judge函数的返回值
		if (ret != 'C')//判断还能不能继续下棋
		{
			break;
		}
		Computer(board, ROW, COL);//电脑下棋函数
		ret = Judge(board, ROW, COL);//接收Judge函数的返回值
		if (ret != 'C')//判断还能不能继续下棋
		{
			break;
		}
	}
	if ('*' == ret)//根据Judge函数的返回值判断结果
	{
		printf("玩家赢\n");
	}
	else if ('#' == ret)
	{
		printf("电脑赢\n");
	}
	else if ('Q' == ret)
	{
		printf("平局\n");
	}
}

下面是判断函数的代码:

char Judge(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i< row; i++)
	{
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')//判断每一行棋子是不是相同并且不是空格
		{
			return board[i][0];//返回的字符则代表着是玩家还是电脑
		}
	}
	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 (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')//判断另一条对角线棋子是不是相同并且不是空格
	{
		return board[1][1];//返回的字符则代表着是玩家还是电脑
	}
	if (IsFull(board, row, col))//判断是否平局(遍历数组看是否还有空格)
	{
		return 'Q';
	}
	return 'C';	//游戏继续
}

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] == ' ')//遍历数组看是否还有空格
			{
				return 0;
			}
		}
	}
	return 1;
}

这里的小写row和col均是形参,值分别等于ROW和COL的

我们定义了一个函数Judge()函数

名字:Judge

类型: char(就如int类型返回整形,char类型返回字符类型,void类型就是无返回值)

返回值:字符形

参数:3个参数,char类型的二维数组board,int类型的row,int类型的col。

功能:判断输赢


我们定义了一个函数IsFull()函数

名字:IsFull

类型: int(就如int类型返回整形,char类型返回字符类型,void类型就是无返回值)

返回值:整形

参数:3个参数,char类型的二维数组board,int类型的row,int类型的col。

功能:判断是否平局

运行截图如下:

到这里三子棋基本就写完了,下面是一些可以改进的方法和判断函数的第二种写法。

有兴趣的读者可以继续阅读,非常感谢你能看到这里,有任何疑问或者有可以改进的地方也可以在评论区指出,如果你对我的文章认可的话也可以点个赞。

全部代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include#include#include#define ROW 3
#define COL 3
void menu()
{
	printf("***********************************\n");
	printf("*********    1.三子棋     *********\n");
	printf("*********   0.退出游戏    *********\n");
	printf("***********************************\n");
}

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 PrintBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i< row; i++)//循环3次
	{
		for (j = 0; j< col; j++)//这个for打印的是上半部分,循环3次
		{
			printf(" %c ", board[i][j]);//结构为(空格)(数组的空格)(空格)
			if (j + 1< col)//打印上半部分的最后一列时不打印(|)
				printf("|");
		}
		printf("\n");
		if (i + 1< row)//打印最后一组时不打印下半部分
		{
			for (j = 0; j< col; j++)//这个for打印的是下半部分,循环3次
			{
				printf("---");//结构为(-)(-)(-)
				if (j + 1< col)//打印下半部分的最后一列时不打印(|)
					printf("|");
			}
			printf("\n");
		}
	}
}

void Player(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("玩家下棋,请选择你的坐标\n");
	while (1)//循环,当棋子正确落下时跳出循环结束玩家下棋阶段
	{
		scanf("%d %d", &x, &y);//接收玩家下达的坐标
		if (x - 1 >= 0 && x - 1< row && y - 1 >= 0 && y - 1< col)//检查是否超出棋盘
		{
			if (board[x - 1][y - 1] != ' ')//检查该坐标是否有棋子
			{
				printf("你选择的地方已经有棋子了,请重新选择\n");
				continue; //当棋子没有正常落下时继续循环,直到棋子正确落下
			}
			board[x - 1][y - 1] = '*';
			break;//当棋子正确落下时跳出循环结束玩家下棋阶段
		}
		else
			printf("你选择的坐标非法,请重新选择\n");//当棋子没有正常落下时继续循环,直到棋子正确落下
	}
	printf("------------------------\n");
}

void Computer(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("电脑下棋->\n");
	while (1)//循环和玩家下棋道理一样
	{
		x = rand() % row;//随机值取余row(3)得到 0 - 2的随机值
		y = rand() % col;//随机值取余row(3)得到 0 - 2的随机值
		if (board[x][y] == ' ')//判断该坐标是否有棋子
		{
			board[x][y] = '#';
			break;//成功下棋,跳出循环
		}
	}
}

char Judge(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i< row; i++)
	{
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')//判断每一行棋子是不是相同并且不是空格
		{
			return board[i][0];//返回的字符则代表着是玩家还是电脑
		}
	}
	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 (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')//判断另一条对角线棋子是不是相同并且不是空格
	{
		return board[1][1];//返回的字符则代表着是玩家还是电脑
	}
	if (IsFull(board, row, col))//判断是否平局(遍历数组看是否还有空格)
	{
		return 'Q';
	}
	return 'C';	//游戏继续
}

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] == ' ')//遍历数组看是否还有空格
			{
				return 0;
			}
		}
	}
	return 1;
}

void game()//定义游戏函数
{
	char board[3][3];//创建char类型的3乘3的数组
	char ret = 0;//创建变量接收Judge函数的返回值
	InitBoard(board, ROW, COL);//这是初始化棋盘的函数
	while (1)//每一轮是玩家下棋,判断输赢,电脑下棋,判断输赢。循环每一轮直到有一方赢或者平局
	{
		PrintBoard(board, ROW, COL);//打印棋盘函数
		Player(board, ROW, COL);//玩家下棋函数
		ret = Judge(board, ROW, COL);//接收Judge函数的返回值
		if (ret != 'C')//判断还能不能继续下棋
		{
			break;
		}
		Computer(board, ROW, COL);//电脑下棋函数
		ret = Judge(board, ROW, COL);//接收Judge函数的返回值
		if (ret != 'C')//判断还能不能继续下棋
		{
			break;
		}
	}
	if ('*' == ret)//根据Judge函数的返回值判断结果
	{
		printf("玩家赢\n");
	}
	else if ('#' == ret)
	{
		printf("电脑赢\n");
	}
	else if ('Q' == ret)
	{
		printf("平局\n");
	}
	PrintBoard(board, ROW, COL);//打印棋盘函数
}

int main()
{
	int input = 0;//定义变量input接收输入值
	srand((unsigned int)time(NULL));
	do {
		menu();
		printf("请选择->\n");
		scanf("%d", &input);
		//---------------------------------------------
		switch (input)//通过switch读取input的值判断需要做什么
		{
		case 1:
			game();//实现游戏的函数
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入有误,请重新输入\n");
			break;
		}
		//---------------------------------------------
	} while (input);//当input为0(退出游戏)时就跳出循环结束游戏,非0为真,继续循环
	return 0;
}

5.判断输赢 (2)第二种方法

这种方法判断行列时使用了两个for

判断对角线和棋盘上是否有空格和第一种方法类似。

与第一种代码比较谁好谁坏这就靠读者自己判断了。

char judge(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	int flag = 0;//标志,判断三个棋子是否相同
	for (i = 0; i< row; i++)
	{
		for (j = 0, flag = 1; j< col - 1; j++)//标志初始化为1
		{
			if (board[i][j] != board[i][j + 1] || board[i][j] == ' ')//判断每一行棋子是否相同并且不是空格
			{
				flag = 0;//当满足上述条件就意味着三个棋子不相同,flag为0
				break;
			}
		}
		if (flag)//flag为1时说明三个棋子相同,返回的字符则代表着是电脑赢还是玩家赢
			return board[i][j];
	}
	for (j = 0; j< col; j++)
	{
		for (i = 0, flag = 1; i< row - 1; i++)//标志初始化为1
		{
			if (board[i][j] != board[i + 1][j] || board[i][j] == ' ')//判断每一列棋子是否相同并且不是空格
			{
				flag = 0;//当满足上述条件就意味着三个棋子不相同,flag为0
				break;
			}
		}
		if (flag)//flag为1时说明三个棋子相同,返回的字符则代表着是电脑赢还是玩家赢
			return board[i][j];
	}
	for (i = 0, j = 0; i< row - 1; i++, j++)
	{
		if (board[i][j] == ' ' || board[i][j] != board[i + 1][j + 1])//判断对角线棋子是否相同并且不是空格
			break;
		if (i == row - 2)//该条件满足说明斜对角线三个棋子相同
			return board[i][j];
	}
	for (i = 0, j = col - 1; i< row - 1; i++, j--)
	{
		if (board[i][j] == ' ' || board[i][j] != board[i + 1][j - 1])//判断另一条对角线棋子是否相同并且不是空格
			break;
		if (i == row - 2)//该条件满足说明斜对角线三个棋子相同
			return board[i][j];
	}
	for (i = 0; i< row; i++)
	{
		for (j = 0; j< col; j++)
		{
			if (board[i][j] == ' ')//判断棋盘上是否有空格没有空格说明能继续下棋
				return 'C';
		}
	}
	return 'E';//能走到这里说明前面判断没有任何人赢并且棋盘上没有空格,平局
}

这里的小写row和col均是形参,值分别等于ROW和COL的

我们定义了一个函数Judge()函数

名字:Judge

类型: char(就如int类型返回整形,char类型返回字符类型,void类型就是无返回值)

返回值:字符形

参数:3个参数,char类型的二维数组board,int类型的row,int类型的col。

功能:判断输赢

这种办法稍微有点复杂,不过是基于第一种方法的另一个思路。


下面是游戏函数:

void game()//定义游戏函数
{
	char board[3][3];//创建char类型的3乘3的数组
	char flag = 0;//创建变量接收Judge函数的返回值
	InitBoard(board, ROW, COL);//这是初始化棋盘的函数
	while (1)//每一轮是玩家下棋,判断输赢,电脑下棋,判断输赢。循环每一轮直到有一方赢或者平局
	{
		PrintBoard(board, ROW, COL);//打印棋盘函数
		Player(board, ROW, COL);//玩家下棋函数
		flag = judge(board, ROW, COL);
		if (flag != 'C')
			break;
		Computer(board, ROW, COL);//电脑下棋函数
		flag = judge(board, ROW, COL);
		if (flag != 'C')
			break;
	}
	if (flag == '*')
		printf("玩家胜利\n");
	else if (flag == '#')
		printf("电脑胜利\n");
	else
		printf("平局\n");
	PrintBoard(board, ROW, COL);
}

到这里第二种方法也介绍完了。然后这样所有代码都在一个项目里难免有些乱,需要修改某些函数时也会比较麻烦,所以我们可以吧游戏函数里面的函数定义放在一个新的文件里,名叫game.c而为了这些函数能在我的主项目test.c文件里起作用,我还需要创建一个头文件,名叫game.h。这样分成模块化的封装函数不仅好修改代码,而且可读性也有了一定提升。

封装好了之后的代码如下:

test.c

#include"game.h"//引用自己创建的头文件,""是查找非标准库里面的头文件,<>是查找标准库里面的头文件
void game()
{
	char board[ROW][COL] = {0};
	int flag = 0;
	InitBoard(board, ROW, COL);
	while (1)
	{
		PrintBoard(board, ROW, COL);
		printf("\n");
		Player(board, ROW, COL);
		flag = judge(board, ROW, COL);
		if (flag != 'C')
			break;
		Computer(board, ROW, COL);
		flag = judge(board, ROW, COL);
		if (flag != 'C')
			break;
	}
	if (flag == '*')
		printf("玩家胜利\n");
	else if (flag == '#')
		printf("电脑胜利\n");
	else
		printf("平局\n");
	PrintBoard(board, ROW, COL);
}
int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do {
		menu();
		printf("请选择->\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入有误,请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}

game.h

#include#include#include#include#define ROW 3
#define COL 3
//各个函数的声明
void menu();
void InitBoard(char board[ROW][COL], int row, int col);
void PrintBoard(char board[ROW][COL], int row, int col);
void Player(char board[ROW][COL], int row, int col);
void Computer(char board[ROW][COL], int row, int col);
char judge(char board[ROW][COL], int row, int col);

game.c

#include"game.h"
void menu()
{
	printf("***********************************\n");
	printf("*********    1.三子棋     *********\n");
	printf("*********   0.退出游戏    *********\n");
	printf("***********************************\n");
}
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 PrintBoard(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 + 1< col)
				printf("|");
		}
		printf("\n");
		if (i + 1< row)
		{
			for (j = 0; j< col; j++)
			{
				printf("---");
				if (j + 1< col)
					printf("|");
			}
			printf("\n");
		}
	}
}
void Player(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("玩家下棋,请选择你的坐标\n");
	while (1)
	{
		scanf("%d %d", &x, &y);
		if (x - 1 >= 0 && x - 1< row && y - 1 >= 0 && y - 1< col)
		{
			if (board[x - 1][y - 1] != ' ')
			{
				printf("你选择的地方已经有棋子了,请重新选择\n");
				continue;
			}
			board[x - 1][y - 1] = '*';
			break;
		}
		else
			printf("你选择的坐标非法,请重新选择\n");
	}
	printf("------------------------\n");
}
void Computer(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("电脑下棋->\n");
	while (1)
	{
		x = rand() % row;
		y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}
char judge(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	int flag = 0;
	for (i = 0; i< row; i++)
	{
		for (j = 0,flag = 1; j< col - 1; j++)
		{
			if (board[i][j] != board[i][j + 1] || board[i][j] == ' ')
			{
				flag = 0;
				break;
			}
		}
		if(flag)
		return board[i][j];
	}
	for (j = 0; j< col; j++)
	{
		for (i = 0,flag = 1; i< row - 1; i++)
		{
			if (board[i][j] != board[i + 1][j] || board[i][j] == ' ')
			{
				flag = 0;
				break;
			}
		}
		if (flag)
		return board[i][j];
	}
	for (i = 0, j = 0; i< row - 1; i++, j++)
	{
		if (board[i][j] == ' ' || board[i][j] != board[i + 1][j + 1])
			break;
		if (i == row - 2)
			return board[i][j];
	}
	for (i = 0, j = col - 1; i< row - 1; i++, j--)
	{
		if (board[i][j] == ' ' || board[i][j] != board[i + 1][j - 1])
			break;
		if (i == row - 2)
		return board[i][j];
	}
	for (i = 0; i< row; i++)
	{
		for (j = 0; j< col; j++)
		{
			if (board[i][j] == ' ')
				return 'C';
		}
	}
	return 'E';
}

本次的三子棋编写就到这里,感谢各位读者的观看!

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


网页标题:高质量C语言实现三子棋-创新互联
网址分享:http://njwzjz.com/article/icjoe.html