资讯专栏INFORMATION COLUMN

C语言初阶学习——扫雷小游戏(递归)

zhonghanwen / 2397人阅读

摘要:目录前言前言前期的准备前期的准备游戏代码的具体实现游戏代码的具体实现完整版的扫雷小游戏代码完整版的扫雷小游戏代码总结总结前言扫雷是一款大众类的益智小游戏,于年发行。

目录

前言

前期的准备

游戏代码的具体实现

1、text.c

2、game.h

3、game.c

完整版的扫雷小游戏代码:

1、game.h

2、text.c

3、game.c

总结


前言

      《扫雷》是一款大众类的益智小游戏,于1992年发行。游戏目标是在最短的时间内根据点击格子出现的数字找出所有非雷格子,同时避免踩雷,踩到一个雷即全盘皆输。

      而现在,学习了已有的知识后,我们不仅有能力自己用代码写出简单的三字棋小游戏,还可以写一些稍稍简单的扫雷了。怎么样,虽然比不上用鼠标稍稍点击就可以判断的发行版本,但是也可以是使自己感到满足了。好了,话不多说,让我们一起去了解扫雷的代码实现吧!(本篇博客和上一篇三字棋博客的大致方向是差不多的,如果大家先看一看上一篇博客的话效果会跟好哦)。

前期的准备

和上一篇博客一样,同样需要模块化的思想,将其分成3个模块:text.c,game.c,game.h。

text.c:游戏的测试逻辑(主函数;游戏的逻辑实现)

game.c:游戏的实现逻辑(各种所需要的函数的实现)

game.h:游戏实现函数的声明;行号、列号的声明;头文件的包含


游戏的思路:

1.使用do...while循环,让游戏至少执行一次,打印出菜单模块,设计菜单函数;玩家进入游戏后,可以根据自己的选择决定是否来玩游戏。提示用户输入,根据输入值来确定后续的游戏进程(1代表玩游戏,0代表退出,其他需要重新选择)。

2.熟练的使用数组和函数。若只创建一个棋盘,把雷放上去之后,玩家就可以直接看见,没有任何的可玩性,所以我们需要两个棋盘。一个用来我们内部实现的,存放一些雷,而另一个则是给玩家看的。

3创建完以后呢,就可以放置一些雷在内部数组中。

4.最后,完成坐标的输入;对雷的排查,每排查一个雷所展现在玩家眼前不同的棋盘,以及踩到雷或是扫雷成功的提示和算法实现。

游戏代码的具体实现

1、text.c

主函数:

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

test()函数的具体实现: 

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");		}	} while (input);}

菜单界面(可调于test函数):

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

游戏函数:

void game(){	//创建布置雷的信息的数组(内部,不给玩家看)	char mine[ROWS][COLS] = { 0 };	//创建排查雷的信息的数组(外部,给玩家看的)	char show[ROWS][COLS] = { 0 };	//初始化棋盘	InitBoard(mine, ROWS, COLS, "0");//把内部全部初始化为0	InitBoard(show, ROWS, COLS, "*");//把外部全部初始化为*	//DisplayBoard(mine, ROW, COL);(打印这个棋盘可以自己调试用,但不给玩家看)	//DisplayBoard(show, ROW, COL);	//布置雷	SetMine(mine, ROW, COL);	//打印棋盘(想要打印中间的9*9的棋盘,但传过去的是11*11的整个数组)	DisplayBoard(show, ROW, COL);	//排查雷	FineMine(mine, show, ROW, COL);}

2、game.h

//头文件的包含#include #include #include //符号的声明#define ROW 9#define COL 9#define ROWS ROW+2#define COLS COL+2#define EASY_COUNT 10//函数的声明//初始化棋盘void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);//打印棋盘void DisplayBoard(char board[ROWS][COLS], int row, int col);//布置雷void SetMine(char mine[ROWS][COLS], int row, int col);//排查雷void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

3、game.c

这个是整个游戏的最重要的一步(各个函数的作用在上面的游戏函数写了,我就直接上代码了)。

void InitBoard(char board[ROWS][COLS], int rows, int cols, char set){	int i = 0;	int j = 0;	for (i = 0; i < rows; i++)	{		for (j = 0; j < cols; j++)		{			board[i][j] = set;		}	}} void DisplayBoard(char board[ROWS][COLS], int row, int col){	int i = 0;	int j = 0;	//打印列号,因为之前打印了个行号,所以让第一列是0,但得多打印一行,	//所以前面i=0,后面i<=row	for (i = 0; i <= row; i++)	{		printf("%d ", i);	}	printf("/n");	for (i = 1; i <= row; i++)	{		//打印行号		printf("%d ", i);		//打印棋盘		for (j = 1; j <= col; j++)		{			printf("%c ", board[i][j]);		}		printf("/n");	}} void SetMine(char mine[ROWS][COLS], int row, int col){	int count = EASY_COUNT;	while (count)	{		int x = rand() % row + 1;		int y = rand() % col + 1;		if (mine[x][y] == "0")		{			mine[x][y] = "1";			count--;		}	}} static int get_mine_count(char mine[ROWS][COLS], int x, int y){	return mine[x - 1][y - 1] +		mine[x - 1][y] +		mine[x - 1][y + 1] +		mine[x][y - 1] +		mine[x][y + 1] +		mine[x + 1][y - 1] +		mine[x + 1][y] +		mine[x + 1][y + 1] -		8 * "0";} void open_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y){	int count = get_mine_count(mine, x, y);	if (count == 0)	{		show[x][y] = " ";		if (show[x - 1][y - 1] == "*")			open_mine(mine, show, x - 1, y - 1);		if (show[x - 1][y] == "*")			open_mine(mine, show, x - 1, y);		if (show[x - 1][y + 1] == "*")			open_mine(mine, show, x - 1, y + 1);		if (show[x][y - 1] == "*")			open_mine(mine, show, x, y - 1);		if (show[x][y + 1] == "*")			open_mine(mine, show, x, y + 1);		if (show[x + 1][y - 1] == "*")			open_mine(mine, show, x + 1, y - 1);		if (show[x + 1][y] == "*")			open_mine(mine, show, x + 1, y);		if (show[x + 1][y + 1] == "*")			open_mine(mine, show, x + 1, y + 1);	}	else		show[x][y] = get_mine_count(mine, x, y) + "0";} void FineMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col){	int x = 0;	int y = 0;	int win = 0;	while (win < row * col - EASY_COUNT)	{		printf("请输入要排查雷的坐标:>");		scanf("%d %d",&x, &y);		//判断坐标是否合法		if (x >= 1 && x <= row && y >= 1 && y <= col)		{			//踩雷			if (mine[x][y] == "1")			{				printf("很遗憾,你被炸死了/n");				DisplayBoard(mine, row, col);				break;			}			//未踩雷			else			{				//int count = get_mine_count(mine, x, y);				//show[x][y] = count + "0";//使用递归后不需要这两个了,在open_mine中实现了这                                            //些功能				open_mine(mine, show, x, y);//如果输入坐标附近无雷,则向四周展开直到遇到雷				DisplayBoard(show, ROW, COL);//每次排雷后再次打印棋盘				win++;			}		}		else		{			printf("坐标非法,请重新输入/n");		}	}	if (win == row * col - EASY_COUNT)	{		printf("恭喜你,排雷成功/n");		DisplayBoard(mine, row, col);	}}

上面使用递归实现的,如果不想实现展开的话,可以这样做(删除open_mine,并且解除上面注释的内容)

//open_mine函数删除全部内容void open_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y) void FineMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col){	int x = 0;	int y = 0;	int win = 0;	while (win < row * col - EASY_COUNT)	{		printf("请输入要排查雷的坐标:>");		scanf("%d %d",&x, &y);		//判断坐标是否合法		if (x >= 1 && x <= row && y >= 1 && y <= col)		{			//踩雷			if (mine[x][y] == "1")			{				printf("很遗憾,你被炸死了/n");				DisplayBoard(mine, row, col);				break;			}			//未踩雷			else			{				int count = get_mine_count(mine, x, y);				show[x][y] = count + "0";                //使用上面这两个				//open_mine(mine, show, x, y);//删除该函数				DisplayBoard(show, ROW, COL);//每次排雷后再次打印棋盘				win++;			}		}		else		{			printf("坐标非法,请重新输入/n");		}	}	if (win == row * col - EASY_COUNT)	{		printf("恭喜你,排雷成功/n");		DisplayBoard(mine, row, col);	}}

完整版的扫雷小游戏代码:

1、game.h

//头文件的包含#include #include #include //符号的声明#define ROW 9#define COL 9#define ROWS ROW+2#define COLS COL+2#define EASY_COUNT 10//函数的声明//初始化棋盘void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);//打印棋盘void DisplayBoard(char board[ROWS][COLS], int row, int col);//布置雷void SetMine(char mine[ROWS][COLS], int row, int col);//排查雷void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

2、text.c

#include "game.h"void menu(){	printf("***********************/n");	printf("*****  1. play     ****/n");	printf("*****  0. exit     ****/n");	printf("***********************/n");}void game(){	//创建布置雷的信息的数组(内部,不给玩家看)	char mine[ROWS][COLS] = { 0 };	//创建排查雷的信息的数组(外部,给玩家看的)	char show[ROWS][COLS] = { 0 };	//初始化棋盘	InitBoard(mine, ROWS, COLS, "0");//把内部全部初始化为0	InitBoard(show, ROWS, COLS, "*");//把外部全部初始化为*	//DisplayBoard(mine, ROW, COL);(打印这个棋盘可以自己调试用,但不给玩家看)	//DisplayBoard(show, ROW, COL);	//布置雷	SetMine(mine, ROW, COL);	//打印棋盘(想要打印中间的9*9的棋盘,但传过去的是11*11的整个数组)	DisplayBoard(show, ROW, COL);	//排查雷	FineMine(mine, show, ROW, COL);}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");		}	} while (input);}int main(){	test(); 	return 0;}

3、game.c

#include "game.h" void InitBoard(char board[ROWS][COLS], int rows, int cols, char set){	int i = 0;	int j = 0;	for (i = 0; i < rows; i++)	{		for (j = 0; j < cols; j++)		{			board[i][j] = set;		}	}} void DisplayBoard(char board[ROWS][COLS], int row, int col){	int i = 0;	int j = 0;	//打印列号,因为在之前打印了个行号,所以让第一列是0,但得多打印一行,	//所以前面i=0,后面i<=row	for (i = 0; i <= row; i++)	{		printf("%d ", i);	}	printf("/n");	for (i = 1; i <= row; i++)	{		//打印行号		printf("%d ", i);		//打印棋盘		for (j = 1; j <= col; j++)		{			printf("%c ", board[i][j]);		}		printf("/n");	}} void SetMine(char mine[ROWS][COLS], int row, int col){	int count = EASY_COUNT;	while (count)	{		int x = rand() % row + 1;		int y = rand() % col + 1;		if (mine[x][y] == "0")		{			mine[x][y] = "1";			count--;		}	}} static int get_mine_count(char mine[ROWS][COLS], int x, int y){	return mine[x - 1][y - 1] +		mine[x - 1][y] +		mine[x - 1][y + 1] +		mine[x][y - 1] +		mine[x][y + 1] +		mine[x + 1][y - 1] +		mine[x + 1][y] +		mine[x + 1][y + 1] -		8 * "0";} void open_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y){	int count = get_mine_count(mine, x, y);	if (count == 0)	{		show[x][y] = " ";		if (show[x - 1][y - 1] == "*")			open_mine(mine, show, x - 1, y - 1);		if (show[x - 1][y] == "*")			open_mine(mine, show, x - 1, y);		if (show[x - 1][y + 1] == "*")			open_mine(mine, show, x - 1, y + 1);		if (show[x][y - 1] == "*")			open_mine(mine, show, x, y - 1);		if (show[x][y + 1] == "*")			open_mine(mine, show, x, y + 1);		if (show[x + 1][y - 1] == "*")			open_mine(mine, show, x + 1, y - 1);		if (show[x + 1][y] == "*")			open_mine(mine, show, x + 1, y);		if (show[x + 1][y + 1] == "*")			open_mine(mine, show, x + 1, y + 1);	}	else		show[x][y] = get_mine_count(mine, x, y) + "0";} void FineMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col){	int x = 0;	int y = 0;	int win = 0;	while (win < row * col - EASY_COUNT)	{		printf("请输入要排查雷的坐标:>");		scanf("%d %d",&x, &y);		//判断坐标是否合法		if (x >= 1 && x <= row && y >= 1 && y <= col)		{			//踩雷			if (mine[x][y] == "1")			{				printf("很遗憾,你被炸死了/n");				DisplayBoard(mine, row, col);				break;			}			//未踩雷			else			{				open_mine(mine, show, x, y);//如果输入坐标附近无雷,则向四周展开直到遇到雷				DisplayBoard(show, ROW, COL);//每次排雷后再次打印棋盘				win++;			}		}		else		{			printf("坐标非法,请重新输入/n");		}	}	if (win == row * col - EASY_COUNT)	{		printf("恭喜你,排雷成功/n");		DisplayBoard(mine, row, col);	}}

总结

 本次博客到这里就接近尾声了,有啥不足的地方,欢迎提出来一起共同进步哦!如果喜欢这篇博客的话,欢迎铁汁们动动你们的小手,一键三连哦!

 

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/123504.html

相关文章

  • 实现初阶扫雷

    摘要:通过二维数组的学习以及之前学的一些知识,实现初阶扫雷小游戏。整体思路菜单一把不够,再来一把利用二维数组创建两个的棋盘,那为什么不是呢,下面代码有解释。中进行函数调用和部分函数实现。 通过二维数组的学习以及之前学的一些知识,实现初阶扫雷(9×9)小游戏。                    ...

    WilsonLiu95 评论0 收藏0
  • C语言实现游戏】(二)扫雷递归实现排雷)

    摘要:玩家选择开始游戏后,出现雷盘,并且随机布置雷。雷盘的数组大小为,方便计算扫雷时周围雷的数量,并防止数组越界。放置布置的雷的信息放置排查出雷的信息初始化雷盘初始化展示界面打印展示界面效果如下布置雷随机在数组中让十个变成作为雷。 目录 前言 一、游戏思路 二、游戏框架 1.菜单界面 1.菜单:...

    U2FsdGVkX1x 评论0 收藏0
  • 详细讲解 —— 数组(C语言初阶

    摘要:也可以理解成二维数组有三个元素,每个元素是一个一维数组我们可以把二维数组想象成一个几行几列的数组但是本质上的二维数组是一列的。数组名,计算整个数组的大小,内部单独放一个数组名,数组名表示整个数组。数组名,数组名表示整个数组。 目录 1. 一维数组 1.1 数组的创建和初始化 数组的创建: 数...

    Backache 评论0 收藏0
  • C语言实现【扫雷游戏】拓展版

    摘要:作者时间网站地址摘要语言实现我们小时候玩过的扫雷游戏,最近看到了一些扫雷游戏的简单实现,但是总有功能上的缺失,玩起来不那么的原汁原味,因此我增加了一些新功能确保玩家首次排雷一定不会炸死。 ...

    JayChen 评论0 收藏0
  • 扫雷1.0(递归实现)

    摘要:头文件部分进行符号常量的声明,宏定义等源文件和用时需要引用。包括布置雷区,埋雷,扫雷,判断输赢等。游戏规则扫雷就是要把所有非地雷的格子揭开即胜利踩到地雷格子就算失败。一次就可以完成两次函数调用的实现。这是因为防止在扫雷的时候数组越界。 ...

    CoderDock 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<