c语言实践——三子棋

目录

前言

一、游戏的基本流程

1. 打印菜单,玩家选择

2.游戏开始

 (1)初始化棋盘

(2)打印棋盘

(3)玩家下棋

(4)电脑下棋

(5)判断输赢

 二、代码实操

1.创建文件,引用头文件

 2. 编写主函数和主要函数

(1)主函数

(2)主函数中的test函数和菜单函数

(3)游戏主要框架

3.各分支代码的实现

(1)初始化棋盘

(2)打印棋盘

 (3)玩家下棋

(4)电脑下棋

(5)判断输赢

 三、运行效果


前言

三子棋是我们生活中进行的两人游戏。棋盘有九个位置,采用回合制,只要一方先下够三个连续的棋子就算赢。是一种比较简单的小游戏。接下来,我们就尝试一下用c语言简单滴实现这个游戏的逻辑。

一、游戏的基本流程

4a9f7f1282924b1dbf6503272aeb430e.gif

用代码写三子棋首先要将这个游戏拆分成许多具体的模块,再分别用代码实现。

我们可以将三子棋小游戏拆分成以下几个模块:

1. 打印菜单,玩家选择

在玩家进入游戏之前需要有菜单提供玩家一些选项,用来确定玩家是否要进行游戏。因此,在每次游戏开始之前和结束之后都要出现这个菜单。

2.游戏开始

进入游戏后的整个过程,可以进一步拆分为以下几个模块:

3b6ee72fe1c64878b2d83db4d53da08a.gif

(搁着套娃呢 )

 (1)初始化棋盘

在正式开始下棋之前,我们需要一个棋盘,上面没放任何东西。棋盘上的行和列对应的位置,恰好可以用二维数组很好地表示出来。

(2)打印棋盘

想要让初始化后的棋盘让玩家看到,就需要将棋盘打印出来。但是不能只打印初始化的数组,还需要用线条修饰让它看着是棋盘。另外,这个过程在后面下棋过程中需要反复使用,需要具备一定的兼容性,以方便地展示不一样的棋盘。

(3)玩家下棋

玩家下棋时是有自己的意识的,这时就需要让玩家输入,电脑接收以实现下棋的效果。此外,已经下过棋或没有在棋盘上的坐标不能下棋,但玩家可能不知道,因此需要提醒。而且,一般情况下人想的坐标是比数组下标多 1 的,别忘了减去哦。

(4)电脑下棋

我们现在只是学习三子棋的基本逻辑,可以让电脑下棋位置随机(当然,如果大佬能让电脑更牛,可以写出来让俺见识一下嘿嘿)。这个随机数可以用rand与srand来实现,注意只需取随机数除以三的余数即可得到数组的下标。

(5)判断输赢

每次电脑下完棋或者玩家下完棋都需要判断一次输赢。如果玩家的棋子先连起来,就是玩家赢。反之,则电脑赢。但是不要忘记了,这种游戏还有可能出现平局。如果棋盘满了且没有任何一方胜利,就判为平局。如果以上情况都没发生,就继续游戏。

好了,基本流程已经梳理完毕,接下来开始用代码实现吧!

680d1e861f454e93878350512dd6d228.gif

 二、代码实操

1.创建文件,引用头文件

这里我们为了更好地展示,将头文件一次全部展示,但其实在实操过程中可以边写边引用。

首先我们要创建两个 .c 文件,一个 .h 文件,前者用来写函数,后者用来写声明。如下:

96387b0cbf6c4072a4bcb9980ef33fe9.png

 61ff27d86f814732a7a5e18a39afc197.png

aa871decbb5c4aa08049fc09abdce861.png

 2. 编写主函数和主要函数

我们将主函数和主要函数写入文件test.c文件中,主要流程如下:

(1)主函数

如下:

int main()
{
	test();
	return 0;
}

(2)主函数中的test函数和菜单函数

对应前面的“打印菜单,玩家选择”部分

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


void test()
{
	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);
}

(3)游戏主要框架

对应前面的“游戏开始”部分

//游戏的整个算法实现
void game()
{
	char ret = 0;
	//数组-存放走出的棋盘信息
	char board[ROW][COL] = {0};//全部空格
	//初始化棋盘
	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");
	}
}

这里将判断输赢的函数返回值设置为“*”、“#”、“C”、“Q”可以使我们在后面写该函数更加方便。

3.各分支代码的实现

我们将各分支代码写入文件game.c文件中,主要流程如下:

(1)初始化棋盘

对应前面的“初始化棋盘”部分

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

(2)打印棋盘

对应前面的“打印棋盘”部分

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++)
		{
			//1. 打印一行棋盘位置的字符
			printf(" %c ", board[i][j]);
			if (j < col - 1)
				printf("|");
		}
		printf("\n");
		//2. 打印分割线
		if (i < row - 1)
		{
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j<col-1)
					printf("|");
			}
			printf("\n");
		}
			
	}
}

 (3)玩家下棋

对应前面的“玩家下棋”部分

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);
		//要判断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 ComputerMove(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)判断输赢

对应前面的“判断输赢”部分

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][1] != ' ')
		{
			return board[i][1];
		}
	}
	//判断竖着的
	for (i = 0; i < col; i++)
	{
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
		{
			return board[1][i];
		}
	}
	//判断两个对角线
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
		return board[1][1];
	if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ')
		return board[1][1];
	//判断是否平局
	if (1 == IsFull(board, ROW, COL))
	{
		return 'Q';
	}
	//继续
	return 'C';
}

这里要判断棋盘是否满了,所以要额外写一个判断棋盘是否下满的函数。也可以直接写,但是使用if语句时不太方便。这里专门用一个新函数来写。

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;//满了
}

 注意在函数的过程中或者写完之后,记得在 .h 文件中声明哦!

到此为止,我们的三子棋代码就全部写完了,让我们来看看效果吧!

eefa95501bb2460c949eb4b3f6113100.gif

 三、运行效果

153e2ab024d747dfbab94dfe28400315.png

09b93c48c971446592f24f4902d819ea.png

 是不是很好玩呀!不知道你能不能连续三次和电脑平局呢?快去试试吧!

d2767d2e69e14a6690cba06b6efb6958.gif

  • 21
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 19
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值