【C语言实现小游戏篇】一起来回忆童年,写一写你童年的井字棋吧~ [ C语言实现 ] [ 超详细,超清楚 ] [ 有代码 ]

井字棋


⭕️ 井字棋,又被称为三子棋。相信大家小时候都玩过这个游戏。童年的游戏,让我这个菜鸟动手用代码来实现一下,一起来寻找快乐吧! ❌
勇敢牛牛

在文章的末尾有全部的代码!?
菜鸟


1. ⭕️井字棋演示

?先看一下代码实现井字棋后的界面演示吧? ⤵️井字棋演示


2. ⭕️游戏代码实现

怂

2.1 ❌ 游戏选择菜单

井字棋菜单
我们的游戏菜单简洁明了⤵️
选 1,? 开始游戏 ?
选 0,? 退出游戏 ?

从我们的演示来看,选择游戏,一局游戏结束后,还可以继续选择。
我们可以选择循环来实现?重复游玩?。

int main()
{
	int input = 0;
	do
	{
		//选择菜单
		printf("*********************************n");
		printf("********     1. play     ********n");
		printf("********     0. exit     ********n");
		printf("*********************************n");
		printf("请选择序号:>");
		scanf("%d", &input);
	} while(input);

	return 0;
}

? 关于为什么do while循环的条件是我们输入的 input
? 是因为我们想实现
? 输入 1 进行游戏,游戏完后还可以继续选择,可以进入下次循环继续选择;
? 输入 0 退出游戏,结束循环;
? 输入其他数字,就直接进入下一次循环,重新选择
? 所以循环的条件需要在我们输入 0 的时候为 假,在输入其他数字的时候为 真,直接用 input 的值可以直接判断

这样我们的菜单就会出现了,还可以进行选择⤵️
菜单选择的演示
但是很明显仅仅一个菜单我们并不能进行游戏,所以我们还要实现一个游戏本体的代码。并且在选择 1 的时候,可以执行这些代码。

我们可以写一个 game() 函数来实现游戏的功能,并且使用 switch 语句来实现,选择 1 开始游戏

那么上面的代码就可以更新了⤵️

int main()
{
	int input = 0;
	do
	{
		//选择菜单
		printf("*********************************n");
		printf("********     1. play     ********n");
		printf("********     0. exit     ********n");
		printf("*********************************n");
		printf("请选择序号:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			//游戏本体函数
			game();
			break;
		case 0:
			printf("退出成功!");
			break;
		default:
			printf("选择错误,请重新选择!n");
			break;
		}
	} while(input);

	return 0;
}

现在我们就实现了游戏菜单和选择:

✅ 输入 1 , input == 1 ? 开始游戏 ? , 游戏结束后再次进入循环 , 可重复游玩
✅ 输入 0 , input == 0 ? 退出游戏 ? , 循环条件判断为 假 , 退出循环 , 程序结束
✅ 输入其他 , input != 0 && input != 1 ? 选择错误 ? , 循环条件判断为 真 , 进入下次循环 , 重新选择


2.2 ❌ 游戏本体

?上面的代码,我们实现了游戏菜单和选择,接下来我们需要用代码实现一下游戏的游玩内容!?

那么 game() 函数到底需要有什么内容呢?

2.2.1 游戏本体思路 ?

让我们先来捋一遍思路⤵️

? 首先,我们下棋需要一个棋盘,可用 char board[3][3]; 申请一个二维字符数组实现。
? 还需要将棋盘内容,初始化为 ' ' 。可以自定义一个函数 来初始化棋盘。可以命名为InitiBoard(); //棋盘初始化函数
? 之后我们需要将棋盘的内容,打印出来显示在屏幕上,具体长这样➡️空棋盘打印 同样可以自定义一个函数来实现。 可以命名为DisplayBoard(); //棋盘打印函数
? 然后玩家就可以输入落子的坐标来和 ?️笨笨的电脑?️ 下棋了!所以这里我们需要自定义 3 个函数,来实现 玩家落子、电脑落子、判断输赢 这三个功能。
PlayerMove(); //玩家落子函数
ComputerMove(); //电脑落子函数
IsWin(); //判断结束函数
那么具体的逻辑就是 ⤵️
? 选择 1
? 打印空棋盘
? 输入坐标
? 判断游戏输赢(玩家赢、电脑赢、平局、未分输赢)
? 打印玩家和电脑落子后的棋盘
? 未分输赢则继续
? 已分输赢则重新菜单选择

逻辑捋清楚了,我们来逐个实现函数

2.2.2 各函数的实现 ?

InitiBoard(); ? 棋盘初始化函数

void InitiBoard(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] = ' ';
		}
	}//两重 for 循环实现二维数组初始化
}

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)
		{//打印一行数组后 需要再打印一行 横分割线
			int j = 0;
			for (j = 0; j < col; j++)
			{
				printf("---");		
				if (j < col - 1)
					printf("|");
			}
			printf("n");
		}
	}
}

这个函数可以实现棋盘的打印,如果打印空棋盘结果就是 ➡️空棋盘打印描述


PlayerMove(); ? 玩家落子函数

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)
		{//输入的坐标需要在棋盘内,即 1 <= x,y <= col(行 或 列)
			if (board[x-1][y-1] == ' ')		//判断落子位置是否为空
			{
				board[x-1][y-1] = '*';
				break;
			}
			else
				printf("坐标占用,请重新输入!n");
		}
		else	//输入坐标不在棋盘内
			printf("非法坐标,请重新输入!n");
	}
}

这个函数可以实现玩家输入坐标落子 ➡️玩家落子棋盘


ComputerMove(); ? 电脑落子函数

void ComputerMove(char board[ROW][COL], int row, int col)
{//电脑落子函数,传参:数组地址,棋盘行,棋盘列
	printf("电脑走:>n");
	while (1)
	{
		int x = rand() % row;		//生成随机行坐标
		int y = rand() % col;		//生成随机列坐标
	//rand() 函数可以生成一个随机数 对行或者列 求余就可以,生成一个合法(1 <= x,y <= row)的坐标
	//rand() 函数使用前,需要用 srand() 函数通过 参数改变系统提供的种子值,从而可以使得每次调用rand函数生成的值随机
		if (board[x][y] == ' ')		//判断落子坐标是否为 空
		{
			board[x][y] = '#';
			break;
		}
	}
}

IsWin(); ? 判断结束函数

//返回值为 '*' 玩家赢
//返回值为 '#' 电脑赢
//返回值为 'Q' 平局
//返回值为 'C' 游戏继续
char IsWin(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	//判断 行有无连子
	for (i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
			return board[i][1];			//返回数组内容,数组内容即为获胜者
	}
	//判断 列有无连子
	for (j = 0; j < col; j++)
	{
		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ')
			return board[1][j];			//返回数组内容,数组内容即为获胜者
	}
	//判断 对角线有无连子
	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];
	
	int ret = IsFull(board, row, col);
		//判断 平局
		// IsFull 返回值 为 1 棋盘满  平局
		//		  返回值 为 0 期盼未满  游戏继续
	if (ret == 1)
		return 'Q';		//平局返回 Q

	return 'C';			//无胜方、无平局,返回C 游戏继续
}
IsFull(); ? 判断平局函数 (棋盘是否已满)
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;
				break;
			}
		}
	}
	return 1;	//无空,即棋盘以下满,则返回 1
}

game(); ? 游戏本体函数

void game()
{//棋盘的行和列,可以设置全局符号常量	ROW 和 COL 以便后期更改
	int j = 0;
	int i = 0;
	char ret;
	char board[ROW][COL];		//设置棋盘
	//初始化 数组
	InitiBoard(board, ROW, COL);
	
	//打印 棋盘
	DisplayBoard(board, ROW, COL);
	while (1)
	{//循环落子、打印,直到分出胜负后 break; 结束循环
		//玩家下棋
		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");
	DisplayBoard(board, ROW, COL);		//打印分出输赢时候的 棋盘
	printf("n");
}

至此,我们所需要自定义的所有函数就已经全部实现了;然后需要做的就是按照我们的逻辑合理运用函数来实现完整的游戏。

2.2.3 游戏的实现(所有代码) ?

按照我们已经分析过的逻辑

具体的逻辑 ⤵️
? 选择 1
? 打印空棋盘 或 退出 或 重新选择
? 输入坐标
? 判断游戏输赢(玩家赢、电脑赢、平局、未分输赢)
? 打印玩家和电脑落子后的棋盘
? 未分输赢则继续
? 已分输赢则重新菜单选择

按照逻辑将所有代码组合起来 ⤵️

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ROW 3		//符号常量 行 == 3
#define COL 3		//符号常量 列 == 3

void InitiBoard(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)
		{
			int j = 0;
			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");
	while (1)
	{
		int x = rand() % row;
		int 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] == ' ')
			{
				return 0;
				break;
			}
		}
	}
	return 1;
}

//返回值为 '*' 玩家赢
//返回值为 '#' 电脑赢
//返回值为 'Q' 平局
//返回值为 'C' 游戏继续
char IsWin(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	//判断 行
	for (i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
			return board[i][1];	
	}
	//判断 列
	for (j = 0; j < col; j++)
	{
		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ')
			return board[1][j];
	}
	//判断 对角线
	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];
	//判断 平局
	// IsFull 返回值 为 1 棋盘满  平局
	//		  返回值 为 0 期盼未满  游戏继续
	int ret = IsFull(board, row, col);
	if (ret == 1)
		return 'Q';

	return 'C';
}

void game()
{
	int j = 0;
	int i = 0;
	char ret;
	char board[ROW][COL];
	//初始化 数组
	InitiBoard(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");
	DisplayBoard(board, ROW, COL);
	printf("n");
}

int main()
{
	int input = 0;
	//随机值前的调用
	srand((unsigned int)time(NULL));
	do
	{
		mune();
		printf("请选择序号:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			//游戏本体函数
			game();
			break;
		case 0:
		printf("退出成功!");
			break;
		default:
			printf("选择错误,请重新选择!n");
			break;
		}
	} while(input);

	return 0;
}

这就是 ? 井字棋游戏 ? 的所有代码了!


? 本篇博客到这里就结束了!?

求点赞 ? 关注 ? 评论 ? 收藏 ⭐️ 啊!!
求点赞 ? 关注 ? 评论 ? 收藏 ⭐️ 啊!!
求点赞 ? 关注 ? 评论 ? 收藏 ⭐️ 啊!!

球球了

? 这里是井字棋所有代码的网址(封装后的:头文件、函数文件、主函数文件)⤵️

? https://github.com/DxytJuly3/problem-of-learning/tree/Learn-C/Study_Dayly/chess ?
? https://gitee.com/xyt-g/problem-of-learning/tree/master/chess ?

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>