万字解析:带你走进五子棋(普通版)和三子棋的世界(C语言)

Posted C_Ryson

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了万字解析:带你走进五子棋(普通版)和三子棋的世界(C语言)相关的知识,希望对你有一定的参考价值。

今天,我们来再来实现一个大家都不陌生的小项目:三子棋。

1,三子棋

1,思路分析

写一个小项目,必不可少的是思路的构建。写一个游戏,我们首先需要一个菜单,这是最基本的,让用户来选择是否要玩这个游戏。如果要玩,就进入游戏主体的部分,不玩就直接退出。最简单的思路就是这样,而后一些细节的实现,比如游戏主体的实现需要在过程中配合去讲。

这里,我们将用到自己创建的头文件,以及多个.c文件,主要为了避免主函数中过于繁杂,庞大,我们将大部分功能封装成函数来实现。

2,代码实操

game.h文件中
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define ROW 3
#define COL 3
void Initialboard(char board[ROW][COL], int row, int col);
void Displayboard(char board[ROW][COL], int row, int col);
void playeremove(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);
char Isfull(char board[ROW][COL], int row, int col);

这里可以看到,我们将一些函数都放到这里声明,包括需要用到的一些库函数的头文件,这样,我们在.c文件中就只需要包含我们自己写的头文件就可以,简化程序。当然,不要忘记引用自己写的头文件需要使用双引号""

game.c文件
#include"game.h"
//初始化棋盘
void Initialboard(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++)
		{
			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++)
	{   
		if (i == 0)
		{
			for (j = 0; j < col; j++)
			{
				if (j == 0)
					printf("  %d  ",j);
				else
					printf(" %d  ", j);
			}
			printf("\\n");
		}
		printf("%d",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++)
			{
				if (j==0)
				printf(" ---");
				else
					printf("---");
				if (j < (col - 1))
					printf("|");
			}
		}
		printf("\\n");
	}
}
//实现玩家下棋
void playermove(char board[ROW][COL], int row, int col)
{
	int i, j;
	printf("请根据图示输入要走的坐标:");
	while (1)
	{   
		scanf("%d%d",&i,&j);
		if (i >= 0 && i < 3 && j >= 0 && j <3 && board[i][j] == ' ')
		{
			board[i][j] = '*';
			break;
		}
		else
			printf("输入有误,请重新输入。");
	}
}

void computermove(char board[ROW][COL], int  row, int col)
{
	while (1)
	{
		int i = rand() % row;
		int j = rand() % col;
		if (board[i][j] == ' ')
		{
			board[i][j] = '#';
			break;
		}
	}
}

char Iswin(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 - 2; j++)
		{
			if (board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2] && board[i][j] != ' ')
			{
				return board[i][j];
			}
		}
	}
	for (j = 0; j < col; j++)
	{
		for (i = 0; i < row - 2; i++)
		{
			if (board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j] && board[i][j] != ' ')
			{
				return board[i][j];
			}
		}
	}
	for (i = 0, j = 0; i < row - 2 && j < col - 2; i++, j++)
	{
		if (board[i][j] == board[i + 1][j+1] && board[i + 1][j+1] == board[i + 2][j+2] && board[i][j] != ' ')
		{
			return board[i][j];
		}
	}
	for (i = row-1, j = 0; i >=0 && j < col-2; i--, j++)
	{
		if (board[i][j] == board[i -1][j + 1] && board[i - 1][j + 1] == board[i -2][j + 2] && board[i][j] != ' ')
		{
			return board[i][j];
		}
	}
	return 'c';
}
char 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 'c';
		}
	}
	return 'e';
	 
}
三子棋.c文件
#include"game.h"
//说明:
//*是玩家走的棋子
//#是电脑走的棋子
void menu()
{
	printf("*****************\\n");
	printf("**1,play 0,exit**\\n");
	printf("*****************\\n");
	printf("请选择:");
}
void game()
{
	char win = 'c';
	char board[ROW][COL] = { 0};//创建棋盘
	Initialboard(board, ROW, COL);//初始化棋盘
	Displayboard(board, ROW, COL);//打印出棋盘的信息
	while (1)
	{
		//玩家走
		printf("玩家走\\n");
		playermove(board, ROW, COL);
		Displayboard(board, ROW, COL);
		win = Isfull(board, ROW, COL);
		win=Iswin(board,ROW,COL);
		if (win != 'c')
			break;
		//电脑走
		printf("电脑走\\n");
		computermove(board, ROW, COL);
		Displayboard(board, ROW, COL);
		win = Isfull(board, ROW, COL);
		win=Iswin(board,ROW,COL);
		if (win != 'c')
			break;
	}
	if (win == 'e')
		printf("平局\\n");
	else if (win == '*')
		printf("玩家赢\\n");
	else if (win == '#')
		printf("电脑赢\\n");
}
int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		//菜单,让用户选择
		menu();
		scanf("%d", &input);
		if (input != 0)
		{
			printf("游戏开始\\n");
			game();//游戏主体

		}

		else
		{
			printf("退出游戏\\n");
			break;
		}
	} while (input);

	return 0;
}

3,最后解释

这里将两个合起来一起说。首先,在三子棋.c文件中,我们实现了上面的基本思路,而进入游戏主体部分之后,我们需要的是创建一个棋盘来存放我们的信息。之后,初始化棋盘,打印棋盘。这里,我们使用了宏定义,直接定义ROW,COL,行和列,方便我们之后进行修改,来改变棋盘的大小。而后,就是进行三子棋的玩家和电脑的走法了,玩家走比较简单,我们在打印棋盘的时候就已经让棋盘上有标坐标了,玩家只需要根据坐标来选,在将信息存入就可以了。而电脑的走法就需要我们之前使用过的rand函数了,还记得吗,不记得的话大家可以回去看看

小项目的实现:猜数字小游戏+随机数生成器的实现_C_Ryson的博客-CSDN博客

用取模的方式限制住随机数的范围,我们就可以放入棋盘了。有了这两个之后,最重要的就是判断规则了,大家有兴趣的话,可以去看看​​​​​​C语言从入门到进阶(C语言入门搞定C语言C语言视频教程C语言入门到进阶C语言教程C语言教程C语言教程C语言入门教程C语言入教程C语言C语言视频C语言教程)_哔哩哔哩_bilibili

这里的规则是我自己写的,原本是想让其普适高一些,放大棋盘之后还能使用。结果发现,三子棋放大棋盘之后,先手的一定会赢,这让我之后想写的双人对战的梦想破灭了,于是,我就将其用到了五子棋(进阶版),这里碍于时间原因,就这两天写给大家吧,这里只写一下五子棋的普通版本有兴趣的话记得点个关注,明天来看哦。

在判断规则中,我们利用放进去数组元素的特点,直接返回就行,利用数组的元素来判断是否本局已经结束,而一开始,我们用变量win储存的字母c(continue)来表示游戏继续,如果win的值被改变,就证明游戏已经结束,可以跳出循环了。再进行判断的。同时,我们要注意到,因为棋盘的大小被我们所限定,还有可能出现一个问题是平局,也就是棋盘满的情况,所以我们还需要一个Isfull函数来判断一下,一旦棋盘上所有的元素都不在有空格,又还没分出胜负,那么就是平局了。这样,一个完整的判断规则就写完了。

接下来重点说一下我自己写的上面的规则,

我们知道三子棋要赢只需要有三个棋子在一条直线上,那么这时候,我们就可以创建两个变量,使其都在行和列范围内,并然后嵌套循环i,j,改变来判断竖列的,和横列的,再将i,j,同时改变,来判断斜着的直线。

这时候,不管棋盘变得多么大,判断规则依然成立。

之后的收尾,就是像上次猜数字游戏一样让用户选择是否继续玩就可以了。

2,五子棋(初阶版)

重头戏五子棋来啦。

1,思路分析

其实,五子棋的整体思路和三子棋差不多,整体构建的代码也类似,只是将判断规则放大,将棋盘放大而已,我们边看代码边说吧。

2,代码实现

首先,依然是自己的头文件。

game.h文件
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define ROW 5
#define COL 5
void Initialboard(char board[ROW][COL], int row, int col);
void Displayboard(char board[ROW][COL], int row, int col);
void playeremove(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);
char Isfull(char board[ROW][COL], int row, int col);

简化代码的运用,这里我们将ROW和COL定义成了5,当然,也可以自己定得更大,不过,跟电脑对战(还没升级的),太大的棋盘反而没什么用处。虽然升级也不算太好,毕竟本人才疏学浅,主要升级的思路只在于,让电脑在玩家下的棋的周围下,之后学得更多,在来进行优化吧,这里这个简陋的升级就不展示啦。

game.c文件
#define  _CRT_SECURE_NO_WARNINGS
#include"game.h"
//初始化棋盘
void Initialboard(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++)
		{
			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++)
	{
		if (i == 0)
		{
			for (j = 0; j < col; j++)
			{
				if (j == 0)
					printf("  %d  ", j);
				else
					printf(" %d  ", j);
			}
			printf("\\n");
		}
		printf("%d", 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++)
			{
				if (j == 0)
					printf(" ---");
				else
					printf("---");
				if (j < (col - 1))
					printf("|");
			}
		}
		printf("\\n");
	}
}
//实现玩家下棋
void playermove(char board[ROW][COL], int row, int col)
{
	int i, j;
	printf("请根据图示输入要走的坐标:");
	while (1)
	{
		scanf("%d%d", &i, &j);
		if (i >= 0 && i < 5 && j >= 0 && j <5 && board[i][j] == ' ')
		{
			board[i][j] = '*';
			break;
		}
		else
			printf("输入有误,请重新输入。");
	}
}

void computermove(char board[ROW][COL], int  row, int col)
{
	while (1)
	{
		int i = rand() % row;
		int j = rand() % col;
		if (board[i][j] == ' ')
		{
			board[i][j] = '#';
			break;
		}
	}
}

char Iswin(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 - 4; j++)
		{
			if (board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2] &&board[i][j+2]==board[i][j+3]&&board[i][j+3]==board[i][j+4]&& board[i][j] != ' ')
			{
				return board[i][j];
			}
		}
	}
	for (j = 0; j < col; j++)
	{
		for (i = 0; i < row - 4; i++)
		{
			if (board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j] && board[i + 2][j] == board[i + 3][j] && board[i + 3][j] == board[i + 4][j] && board[i][j] != ' ')
			{
				return board[i][j];
			}
		}
	}
	for (i = 0, j = 0; i < row - 4 && j < col - 4; i++, j++)
	{
		if (board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2] && board[i + 2][j + 2] == board[i + 3][j + 3] && board[i + 3][j + 3] == board[i + 4][j + 4]&& board[i][j] != ' ')
		{
			return board[i][j];
		}
	}
	for (i = row - 1, j = 0; i >= 0 && j < col - 4; i--, j++)
	{
	
		if (board[i][j] == board[i - 1][j + 1] && board[i - 1][j + 1] == board[i - 2][j + 2] && board[i - 2][j + 2] == board[i - 3][j + 3] && board[i - 3][j + 3] == board[i - 4][j + 4]&& board[i][j] != ' ')
		{
			return board[i][j];
		}
	}
	return 'c';
}
char 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 'c';
		}
	}
	return 'e';

}
五子棋(初阶).c文件
#define  _CRT_SECURE_NO_WARNINGS
#include"game.h"
//说明:
//*是玩家走的棋子
//#是电脑走的棋子
void menu()
{
	printf("*****************\\n");
	printf("**1,play 0,exit**\\n");
	printf("*****************\\n");
	printf("请选择:");
}
void game()
{
	char win = 'c';
	char board[ROW][COL] = { 0 };//创建棋盘
	Initialboard(board, ROW, COL);//初始化棋盘
	Displayboard(board, ROW, COL);//打印出棋盘的信息
	while (1)
	{
		//玩家走
		printf("玩家走\\n");
		playermove(board, ROW, COL);
		Displayboard(board, ROW, COL);
		win = Isfull(board, ROW, COL);
		win = Iswin(board, ROW, COL);
		if (win != 'c')
			break;
		//电脑走
		printf("电脑走\\n");
		computermove(board, ROW, COL);
		Displayboard(board, ROW, COL);
		win = Isfull(board, ROW, COL);
		win = Iswin(board, ROW, COL);
		if (win != 'c')
			break;
	}
	if (win == 'e')
		printf("平局\\n");
	else if (win == '*')
		printf("玩家赢\\n");
	else if (win == '#')
		printf("电脑赢\\n");
}
int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		//菜单,让用户选择
		menu();
		scanf("%d", &input);
		if (input != 0)
		{
			printf("游戏开始\\n");
			game();//游戏主体

		}

		else
		{
			printf("退出游戏\\n");
			break;
		}
	} while (input);

	return 0;
}

3,最后解读

这里,我们再次合起来说吧,大家也可以看到,实际上和三子棋的实现没有多大的区别,主要的改变,都在规则部分,我们拿出来细说。

char Iswin(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 - 4; j++)
		{
			if (board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2] &&board[i][j+2]==board[i][j+3]&&board[i][j+3]==board[i][j+4]&& board[i][j] != ' ')
			{
				return board[i][j];
			}
		}
	}
	for (j = 0; j < col; j++)
	{
		for (i = 0; i < row - 4; i++)
		{
			if (board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j] && board[i + 2][j] == board[i + 3][j] && board[i + 3][j] == board[i + 4][j] && board[i][j] != ' ')
			{
				return board[i][j];
			}
		}
	}
	for (i = 0, j = 0; i < row - 4 && j < col - 4; i++, j++)
	{
		if (board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2] && board[i + 2][j + 2] == board[i + 3][j + 3] && board[i + 3][j + 3] == board[i + 4][j + 4]&& board[i][j] != ' ')
		{
			return board[i][j];
		}
	}
	for (i = row - 1, j = 0; i >= 0 && j < col - 4; i--, j++)
	{
	
		if (board[i][j] == board[i - 1][j + 1] && board[i - 1][j + 1] == board[i - 2][j + 2] && board[i - 2][j + 2] == board[i - 3][j + 3] && board[i - 3][j + 3] == board[i - 4][j + 4]&& board[i][j] != ' ')
		{
			return board[i][j];
		}
	}
	return 'c';
}

可以看到,我们将规则又扩大了一些,从原本的三个扩大到了5个位置的相等,而之后同样也是返回数组里的元素,来帮助判断胜负。同时要注意不要越界访问了。

这就是今天的内容了,之后五子棋的进阶部分找时间再分享给大家,进阶部分更加精彩,有我自己捣鼓的一个简陋的登录系统(只是一个雏形,不能储存数据),以及玩家对战部分等,码字不易,大家点点关注,给我点个赞吧,我会坚持更新的。如果有错,请联系修改,你们的支持是我更新的动力。

参考资料:

五子棋图片 - 国内版 Bing images

三子棋图片 - 国内版 Bing images

以上是关于万字解析:带你走进五子棋(普通版)和三子棋的世界(C语言)的主要内容,如果未能解决你的问题,请参考以下文章

全网首发,一篇文章带你走进pycharm的世界----别再问我pycharm的安装和环境配置了!!!万字只为君一笑,赶紧收藏起来吧

❤️大学三年沉淀,把我的学习经验分享给你,爆肝万字带你走进编程世界!❤️

万字长文带你走进MySql优化(系统层面优化软件层面优化SQL层面优化)

整套资料Tomcat核心原理解析,带你走进服务器的世界!

C语言的三子棋

小边同学和你下三子棋(C语言)