【C语言】三子棋小游戏

 

目录

一、三子棋游戏介绍

二、代码分装

三、代码实现步骤

1.制作菜单menu函数以及游戏运行逻辑流程

2.初始化棋盘InitBoard函数

3.打印棋盘DisplayBoard函数

4.玩家下棋PlayerMove函数

 5.电脑下棋ComputerMove函数

6. 判断输赢IsWin函数

四、三子棋完整代码 


一、三子棋游戏介绍

   三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉棋、一条龙、井字棋等。游戏分为双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子走成一条线就视为胜利,而对方就算输了,但是三子棋在很多时候会出现和棋的局面。

    下面作者将带着大家一起用C语言实现一个三子棋的小游戏。

二、代码分装

源文件:

test.c: 整个游戏相关的测试

game.c: 实现游戏的相关函数

头文件:

game.h: 相关函数的声明,整个代码要引用的头文件以及宏定义

三、代码实现步骤

1.制作菜单menu函数以及游戏运行逻辑流程

  • 首先在 test.c 中定义一个menu函数打印菜单,提示玩家1开始游戏,0退出游戏。
  • scanf接收玩家输入并用switch判断,1即开始游戏,0则退出游戏,非1非0则提示选择错误,重新选择。而为了能够让用户重新选择以及结束一局游戏后能够再来一盘,需要使用do while语句将它们包含起来。

 test.c

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

void game()
{
	printf("三子棋\n");
}

int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏!\n");
			break;
		default:
			printf("选择错误,重新选择!\n");
			break;
		}
	} while (input);
	return 0;
}

运行代码检测游戏运行逻辑流程

2.初始化棋盘InitBoard函数

  • 首先三子棋是九个格子,即需要创建一个3x3的数组。为了方便未来修改代码数值,头文件 game.h 中定义ROW(行),COL(竖),然后在 test.c 中引用头文件 game.h即可。
  • 在game函数中创建棋盘board数组,开始的时候,数组的内容应该都是空格,为了方便后续使用,创建一个初始化棋盘函数InitBoard。
  • game.h 中定义InitBoard函数,并在 game.c 中实现函数。

 game.h

#include <stdio.h>

#define ROW 3
#define COL 3

//初始化棋盘
void InitBoard(char board[ROW][COL],int row,int col);

game.c 

//初始化棋盘
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.打印棋盘DisplayBoard函数

接下来创建一个打印棋盘函数DisplayBoard来查看一下初始化是否完成。同样的:在 game.h 中定义DisplayBoard函数,并在 game.c 中实现函数。

首先看棋盘效果图:

思路如下:先打印数据行,再打印分割行

1、数据行打印形式:空格数据空格竖杠

当到达最后一列时不打印竖杠

2、分割行打印形式:---|

当到达最后一列时不打印竖杠,并且当到达最后一行时,不打印分割行

 game.h

//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);

game.c

//打印棋盘
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.玩家下棋PlayerMove函数

game.h 中定义PlayerMove函数,并在 game.c 中实现函数。

game.h

//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col);

 game.c

需要考虑坐标被占用的情况以及输入非法坐标的情况。

使用while循环嵌套输入部分与判断部分,这样当输入错误或者输入的坐标被占用时,可以重新输入。当输入正确时且没被占用,则在该坐标里将 空格 改为 * 。

//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("玩家下棋\n");

	while (1)
	{
		printf("请输入要下棋的坐标:>");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (board[x - 1][y - 1] == ' ') //玩家的输入对应数组的下标需要-1
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else
			{
				printf("该坐标被占用,请输入其他坐标\n");
			}
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
	}
}

需要注意的是,因为玩家下棋的坐标范围是1-3的,而数组中的范围是0-2,因此需要将玩家输入的数-1得到对应的数组下标,才能执行正确。

 5.电脑下棋ComputerMove函数

    这里电脑的下棋策列是随机下棋,因此首先需要生成随机数,这就需要用到srand函数、rand函数和time函数,关于srand函数、rand函数和time函数之间的知识点,我在往期的博客中有进行讲解,感兴趣的可以前往:【C语言】猜数字小游戏——深度刨析rand函数生成随机数_Hacynn的博客-CSDN博客查看,在这里就不过多赘述。

使用srand和rand需要包含 stdlib.h 头文件,使用time需要包含 time.h 头文件。并且在main函数中调用srand生成随机种子,这样rand函数便可以生成随机数。

 game.h

//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col);

game.c

//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
	printf("电脑下棋\n");
	int x = 0;
	int y = 0;

	while (1)
	{
		x = rand() % row;
		y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}

当完成这一步时,三子棋游戏就大概完成了,玩家和电脑可以相互下棋,但是缺少了获胜的条件,因此还需要设置一个获胜条件来停止游戏。

6. 判断输赢IsWin函数

这里我们先要考虑判断IsWin函数需要返回几种结果:

1、玩家获胜===》函数返回*

2、电脑获胜===》函数返回#

3、平局       ===》函数返回Q

4、游戏继续===》函数返回C

 game函数

void game()
{
	int ret = 0;
	char board[ROW][COL];
	InitBoard(board, ROW, COL);
	DisplayBoard(board, ROW, COL);

	while (1)
	{
		//玩家
		PlayerMove(board, ROW, COL);//玩家下棋
		DisplayBoard(board, ROW, COL);//打印棋盘结果
		ret = IsWin(board, ROW, COL);//判断输赢
		if (ret != 'C')
		{
			break;
		}

		//电脑
		ComputerMove(board, ROW, COL);//电脑下棋
		DisplayBoard(board, ROW, COL);//打印棋盘结果
		ret = IsWin(board, ROW, COL);//判断输赢
		if (ret != 'C')
		{
			break;
		}
	}
	if (ret == '*')
		printf("玩家赢!\n");
	else if (ret == '#')
		printf("电脑赢!\n");
	else
		printf("平局!\n");
}

 判断IsWin函数返回的值并返回提示或者继续游戏。

game.h

//判断输赢
char IsWin(char board[ROW][COL], int row, int col);

game.c

//判断是否为满
static 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;
}

//判断输赢
char IsWin(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';//继续
}

其中需要注意的是,IsFull函数仅是用来判断数组是否已满,未满返回0满返回1。而且IsFull只辅助于IsWin函数,不被其他函数调用,因此可以在前面加static修饰。

四、三子棋完整代码 

test.c

#define _CRT_SECURE_NO_WARNINGS 1


#include "game.h"

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

void game()
{
	int ret = 0;
	char board[ROW][COL];
	InitBoard(board, ROW, COL);
	DisplayBoard(board, ROW, COL);

	while (1)
	{
		//玩家
		PlayerMove(board, ROW, COL);//玩家下棋
		DisplayBoard(board, ROW, COL);//打印棋盘结果
		ret = IsWin(board, ROW, COL);//判断输赢
		if (ret != 'C')
		{
			break;
		}

		//电脑
		ComputerMove(board, ROW, COL);//电脑下棋
		DisplayBoard(board, ROW, COL);//打印棋盘结果
		ret = IsWin(board, ROW, COL);//判断输赢
		if (ret != 'C')
		{
			break;
		}
	}
	if (ret == '*')
		printf("玩家赢!\n");
	else if (ret == '#')
		printf("电脑赢!\n");
	else
		printf("平局!\n");
}

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请选择:>");
		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 <stdio.h>
#include <time.h>
#include <stdlib.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);

//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col);

//判断输赢
char IsWin(char board[ROW][COL], int row, int col);

game.c

#define _CRT_SECURE_NO_WARNINGS 1

#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)
{
	int x = 0;
	int y = 0;
	printf("玩家下棋\n");

	while (1)
	{
		printf("请输入要下棋的坐标:>");
		scanf("%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");
		}
	}
}

//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
	printf("电脑下棋\n");
	int x = 0;
	int y = 0;

	while (1)
	{
		x = rand() % row;
		y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}

//判断是否为满
static 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;
}

//判断输赢
char IsWin(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';//继续
}

 此次的三子棋小游戏的内容就到此为止了,相信大家也能够做出属于自己的三子棋小游戏,这个游戏最重要的是代码思维而不是代码本身,理解代码思维能够得到更大的提升。

如果觉得作者写的不错,求给作者一个大大的点赞支持一下,你们的支持是我更新的最大动力!

 

相关推荐

  1. C语言三子游戏(棋盘)

    2023-12-10 04:30:01       30 阅读
  2. C语言三子游戏

    2023-12-10 04:30:01       31 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-10 04:30:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-10 04:30:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-10 04:30:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-10 04:30:01       18 阅读

热门阅读

  1. linux命令积累

    2023-12-10 04:30:01       35 阅读
  2. 如何检查mysql表里,某个字段是否存在相同值?

    2023-12-10 04:30:01       39 阅读
  3. ANSYS 有限元分析 后处理 结点解与单元解

    2023-12-10 04:30:01       43 阅读
  4. 数据库基础学习03计算机二级-第三章 数据定义

    2023-12-10 04:30:01       40 阅读