三子棋游戏(c语言---数组)

今天又来写一款小游戏,名字是三子棋,这个游戏就是在九宫格内双方轮流下棋,最终能连成一条线的玩家获胜,若棋盘下满依然没决出胜负那么就是平局。

三子棋游戏制作

目录

1.游戏思路详解及前期准备工作

2.设计一个游戏开始界面

3.编写游戏函数主体

                (1)初始化棋盘

                (2)打印棋盘

                (3)玩家下棋

                (4)电脑下棋

       (5)判断输赢

       (6)建立循环

4.总结

1.游戏思路详解及前期准备工作

根据最近学的数组的知识,我们可以利用数组来建立一个九宫格(二维数组),那么先以3X3的为例,玩家和电脑要轮流在九宫格下棋,那么就意味着玩家和电脑在3x3的二维数组中轮流填充。这次,我们可以用到一个新的方法来写三子棋,也是未来所要用到的就是多文件写程序。

多文件写程序,除了我们日常中经常使用的test.c之外,我们还可以创建其他的.c文件,但是在一个工程中只能有一个主函数,所以我们在一个工程的其他.c或者说是源文件中我们要创建属于该源文件对应的头文件。

下面我们将用这个三子棋的例子来详细说一下多文件写程序。

首先,我们要两个源文件,一个是测试程序,一个是游戏程序。

三子棋游戏(c语言---数组)_第1张图片

 如上图,我们的test.c是测试源文件,而game.c是游戏源文件,所以我们要创建相应的头文件game.h(最好与对应源文件名相同,方便引用),头文件主要作用是函数的定义和一些变量的定义。注意头文件有对应的格式,画箭头的语句是一定要写的。

三子棋游戏(c语言---数组)_第2张图片

 创建好了之后,就开始我们的程序编写了。

和上次设计的游戏开始思路相同,我们先要设计一个游戏开始界面来让玩家选择,然后再用游戏函数替换掉那个输出函数。

2.设计一个游戏开始界面(在test.c)

#include 
void menu()
{
	printf("********************\n");
	printf("*******1. play******\n");
	printf("*******0. exit******\n");
	printf("********************\n");
}

int main()
{
	int input = 0;
	do
	{
	menu();
	printf("请输入:>");
	scanf("%d", &input);
	switch (input)
	{
		case 1:
			printf("三子棋(游戏主体)\n");
			break;
		case 0:
			printf("游戏结束\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
	}
	} while (input);
	return 0;
}

可见我们在选择1时就可以进入游戏,接下来的任务就是写一个game()来替换printf("三子棋")

3.编写游戏主体函数(game())

(1)初始化棋盘

首先,我们创建一个二维数组(可以先3x3的),但是我们考虑到可以使用更大的棋盘,所以在这里我们可以用变量的形式方便以后编辑,我们创建两个变量ROW(代表行)和COL(代表列),在game.h中将变量定义好,当然我们要在test.c文件中包含game.h才能使用。

 三子棋游戏(c语言---数组)_第3张图片

 然后我们要初始化棋盘,创建一个函数void Initboard(char board[ROW][COL], int row, int col);(在game.h中),然后一个嵌套循环来初始化数组。注意括号里面的是传递的参数(形参)。

 下一步

 最后在游戏编写程序(game.c)中来写函数体

三子棋游戏(c语言---数组)_第4张图片

 这就是一个函数多文件的使用,下面的函数都是这样编写的,就不一一列举了。

(2)打印棋盘

接下来就是我们需要将棋盘打印出来,那么我们还是一样创建一个函数void DisplayBoard(char board[ROW][COL], int row, int col);(跟上面步骤一样),接下考虑函数体怎么写。

我们可以观察一下棋盘,

三子棋游戏(c语言---数组)_第5张图片

 那么可以先理解为每个元素都是_ _ _|的形式,我们在第二个横线上就可以下棋了。先填充内容为

 %c (方便输入数据)在我们填好内一列容后,记得换行,然后我们发现,最后一行和最后一列有多余的部分,这时我们可以用一个判断语句(if)来使多余部分去掉。综合以上,该函数体内容为

void DisplayBoard(char board[ROW][COL], int row, int col)        //以单个格子为对象来打印棋盘
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		//打印数据(格子里面的内容)
		int j = 0;
		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");
	}
	
}

(3)玩家下棋

接下来开始解决玩家下棋问题,还是一样,创建一个函数void plyaer_move(char board[ROW][COL], int row, int col),我们知道,玩家需要输入相应的坐标就可以下棋,这里有个小细节,玩家是对大众的,他们输入的应该是1~ROW或COL,但是数组下标是从0~ROW-1或COL-1,所以我们可以创建一个临时变量来将用户的习惯转换成正确数组下标。然后要考虑越界的问题,当用户输入的数据越界时就得让用户重新输入(可以使用if语句)。最后如果这里已经有棋子了,也需要让用户重新输入,最终代码如下:

void plyaer_move(char board[ROW][COL], int row, int col)
{
	while (1)
	{
	int x = 0;
	int y = 0;
	printf("玩家下棋\n");
	printf("请输入坐标:>");
	scanf_s("%d %d", &x, &y);
	
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			//开始下棋--判断下的位置有没有被下过
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else
			{
				printf("坐标非法,请重新输入!\n");
			}
		}
		else
		{
				printf("坐标非法,请重新输入!\n");
		}
	}
	

}

(4)电脑下棋

接下来到了比较复杂的地方了,就是让电脑下棋。思路是让电脑随机生成一组坐标,然后下棋。还是一样先创建一个函数void computer_move(char board[ROW][COL], int row, int col)。

首先,我们解决如何让电脑随机生成一组坐标的问题,这时候就得用到我们生成随机数的一个常见办法,那就是使用rand函数生成随机数,在rand函数使用过程中我们还必须使用srand函数,在使用时有个问题就是srand函数返回值总是刷新太慢,我们这个时候就可以使用time函数,它的返回值是当前时间戳的转换值,我们将其实参定为空指针,这样我们就可以得到一个实时刷新的随机值了,这个最好放在主函数中,因为我们每运行一次时间间隔较长,产生的随机值更随机。

然后,我们将得到的返回值去%ROW,这样得到的数在0~ROW-1中,接下来我们就只要电脑下在空白的地方就行了。具体函数体如下:

void computer_move(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;
			}
	}
}

(5)判断输赢

最后一步就是判断输赢了,这里我们可以创建一个判断输赢的函数,将他的返回值作为判断的标准,我的设计是这样三子棋游戏(c语言---数组)_第6张图片为什么要这样设置,因为这个在后面的编程中可以为我们省下很多繁琐的步。

我们先创建一个判断输赢的函数char is_win(char board[ROW][COL], int row, int col),我们知道,三子赢的话要么是行成一条线,要么就是列成一条线,要么就是对角线成一条线,所以我们可以用三个循环判断语句来分别判断行,列,对角线。这时候就可以解释刚刚为什么要那样设置返回值了,如果这些相同的是'*'的话,返回值就是'*',即玩家赢,同理电脑赢也是如此。

那么下满了该怎么判断呢?我们可以在game.c创建一个临时的函数,因为它是与判断输赢的函数配套的,所以我们可以直接将它写到game.c中,还是用判断语句,如果有没有填充的地方就返回0,全部填满的话就是返回1,那么再写一个判断语句就可以了。

最后就是不满足所有情况的话即继续下,即返回'c'。在游戏测试文件(test.c)这边,我们要写一个判断语句来判断谁赢。具体函数如下:


static int is_full(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			if (board[i][j] == ' ')
			{
				return 0;
			}
		}
	}
	return 1;
}

//判断输赢
char is_win(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[0][0] != ' ')
	{
		return board[0][0];
	}
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
	{
		return board[0][2];
	}
	//判断平局---如果棋盘满了且不满足以上条件的话就是平局,没满就继续下
	if (is_full(board, row, col) == 1)
	{
		return 'Q';
	}
	return 'C';
}

(6)建立循环

总结上文,我们已经写好了一次游戏的过程,我们可以写一个循环来不断重复游戏过程,最终game函数为:

void game()
{
	srand((unsigned int)time(NULL));
	char ret = 0;
	//存放玩家和电脑下棋数据---九宫格---3 × 3的二维数组
	char board[ROW][COL] = {0};
	//初始化棋盘
	Initboard(board, ROW, COL);
	//打印棋盘
	DisplayBoard(board, ROW, COL);
	while (1)
	{
		//玩家下棋
		plyaer_move(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		//判断输赢
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
			
		//电脑下棋
		computer_move(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
			
	}
	if (ret == '*')
	{
		printf("玩家赢了!\n");
	}
	else if (ret == '#')
	{
		printf("电脑赢了!\n");
	}
	else
	{
		printf("这是一个平局,请重新开始!\n");
	}
	DisplayBoard(board, ROW, COL);
}

4.总结

综上,其实简单来看就是一个数组的填充,难点在于如何让电脑随机下棋,如何判断输赢。最终代码如下:王亮懿/c语言学习https://gitee.com/wang-liangyi/c-language-learning.git

你可能感兴趣的:(游戏,c语言,开发语言)