资讯专栏INFORMATION COLUMN

[ C语言 ] 扫雷 ------> 用C语言实现game2

I_Am / 3432人阅读

摘要:函数游戏菜单请选择扫雷游戏退出游戏选择错误解析函数内部利用时间戳,形成随机数,主要目的是实现游戏中地雷的随机埋放。


前言

本篇文章使用C语言实现简单小游戏---扫雷。(文章最后有完整代码链接

想必大多数人都玩过或者了解过扫雷的游戏规则,但是在这里,我们在一起重温一下扫雷的游戏规则,也更好的让我们了解程序的实现目的。

扫雷:扫雷就是要把所有非地雷的格子揭开即胜利;踩到地雷格子就算失败。游戏主区域由很多个方格组成。使用鼠标左键随机点击一个方格,方格即被打开并显示出方格中的数字;方格中数字则表示其周围的8个方格隐藏了几颗雷。

在了解游戏规则后,我们就用C语言来实现这个简单小游戏。

这是我们解决资源管理器内所创建的文件,下来我们就进入代码内部。


一,游戏使用到的头文件和游戏声明

1.头文件的包含

#include #include #include 

2.符号的声明

#define ROW 9#define COL 9#define ROWS ROW+2#define COLS COL+2#define EASY_COUNT 10

3.函数的声明

初始化棋盘

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);

二,游戏测试

1. 主函数

和三子棋一样,主函数仍然简单,函数内部调用test()测试函数。

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

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

解析test()函数内部:

A. srand((unsigned int )time(NULL))  

利用时间戳,形成随机数,主要目的是实现游戏中地雷的随机埋放。

B.menu() 游戏菜单

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

创建菜单,实现效果演示:

 C:switch case 选择语句:

使用此语句实现玩家的自主选择,当输入1时进行扫雷游戏,当输入0时,退出游戏。显示效果如下:

     

3.game()函数

game()函数是主要游戏实现函数,以下是game函数主要是实现逻辑图和实现顺序

 这里先让大家看一下完整代码,实现顺序如上所示:

下面主要进入我们的游戏实现逻辑当中......划重点

三,游戏实现

1.创建棋盘

// 创建数组	// 创建雷的数组(mine)   显示的数组(show)    两个数组一样规模 一样类型	char mine[ROWS][COLS] = { 0 }; // 存放布置好的雷的信息	char show[ROWS][COLS] = { 0 }; // 存放排查出的雷的信息

在这里我们需要创建2个相同大小,相同类型的二维数组。

问:我们为什么要创建2个相同的数组呢?
答:是因为我们在玩扫雷的时候我们首先看到的是一个未知得棋盘,不知道哪里埋放着雷,如果我们触碰到雷结束游戏后,我们需要给玩家呈现这局游戏所有点位的情况,这样以便于玩家清楚所有雷都在那里,为什么死,因此我们需要两个棋盘才能完成这项任务。

在这里我们创建了11X11大小的棋盘,但是只显示9X9大小的棋盘也就是81个格子,打算埋放10颗雷,玩家可以在头文件自行更改雷的个数。

问:我们显示9X9大小的棋盘,为什么创建11X11大小的棋盘?

答:这是因为扫雷游戏规则中,我们在排雷的过程中,会显示周围8个格子的雷的个数,如果创建一个9X9的格子,那当我们在边角的时候,我们周围的格子不够8个,但是我们还要访问周围8个格子,这时候我们必然会造成数组越界问题,具体情况如下图所示,这时候我们如果创建11X11的棋盘,对11X11的棋盘都初始化为字符" 0 ", 我们只显示内部的9X9的格子,我们依然不会影响游戏,并且也解决了数组越界的问题。

如图所示,我们假设要查找坐标为(9,9)格子周围8个格子的雷的个数,如果我们还只是9X9的格子,我们图中的红色阴影区域就处于数组的范围之外,因为我们需要创建11X11的棋盘,就可以轻松化解这个问题。

2.初始化棋盘

    // 初始化mine数组为全"0"	InitBoard(mine,ROWS,COLS,"0");//初始化--->棋盘函数	// 初始化show数组为全"*"	InitBoard(show,ROWS,COLS,"*");//初始化--->棋盘函数

和三子棋一样,我们依然自定义函数InitBoard(),具体代码如下:

void InitBoard(char board[ROWS][COLS], int rows, int cols, char set){	int i = 0, j = 0;	for (i = 0; i < rows; i++)	{		for (j = 0; j < cols; j++)		{			board[i][j] = set;		}	}}

在这里我们对第一块mine棋盘全部初始化为字符 " 0 " (注意这里是字符0,不是数字0),我们对第二块show棋盘全部初始化为字符" * " ,最终玩家首先会看到一幅全是字符" * "的棋盘,这样也符合游戏规则。

3.打印棋盘

自定义函数DisplayBoard(),具体代码如下:

void DisplayBoard(char board[ROWS][COLS], int row, int col){	int i = 0, j = 0;	//列号的打印	for (i = 0; i <= col; 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");	}}

这样通过调用DisplayBoard()函数我们可以检查一下,我们刚才所创建和初始化的棋盘是否符合我们的要求,我们打印棋盘演示如下:

 我们发现,打印出来的棋盘也完全符合我们的要求,我们也只需要最终将show棋盘显示给玩家即可。

4.布置雷

在这里我们自定义函数SetMine()函数,具体代码如下:

// 布置雷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--;		}	}}

我们对此代码进行分析:

A:如何实现随机布雷?

答:我们创建rand函数,利用时间戳生成随机数,因为我们所创建的棋盘大小是9X9大小,我们我们只需要给生成的随机数模上row(col)即可得到0~row-1 ,因此我们再 +1 即可得到一个在0~row(col)的随机数,从而实现随机布雷。

我们设定count个雷,如果我们埋下一颗雷,我们就count-1,同时我们将初始化的字符" 0 " 变成字符" 1 " , 只有我们识别到目标格子是字符 " 0 " 时才会埋雷,这也解决了在同一位置重复埋雷的问题。 

假设我们随机埋下10颗雷,演示一下棋盘:

 我们发现,我们随机埋下了10颗雷,并且也改成了字符" 1 "

5.排雷

自定义函数FindMine(),具体代码如下所示:

// 排查雷void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col){	int x = 0, y = 0;	int win = 0;	while (win");		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			{				//计算x,y坐标周围有几个雷				int n = get_mine_count(mine,x,y);				show[x][y] = n+"0"; // 数字+"0"可以转换成对应的ASCII				DisplayBoard(show, row, col);				win++;			}		}		else		{			printf("输入坐标非法,无法排雷,请重新输入/n");		}	}	if (win == row * col - EASY_COUNT)	{		printf("恭喜你,排雷成功/n");		DisplayBoard(mine, row,col);	}}

其中调用了get_mine_count函数,其代码如下:

static int get_mine_count(char mine[ROWS][COLS],int x,int y){	return mine[x - 1][y] +		mine[x - 1][y - 1] +		mine[x][y - 1] +		mine[x + 1][y - 1] +		mine[x + 1][y] +		mine[x + 1][y + 1] +		mine[x][y + 1] +		mine[x - 1][y + 1] - 8 * "0";}

接下来对这两段代码进行分析:

当我们输入需要排查的坐标的时候,我们所输入的坐标也必须合法,必须在1~row(col)之间的数字,如果在此之外,我们将会提醒玩家“输入坐标非法,无法排雷,请重新输入”字样。

当我们输入正确的坐标时候,我们需要对这个坐标下所对应的字符进行判断,如果是字符" 1 " ,说明踩中雷,说明游戏结束,这时候我们将完整棋盘打印出来,玩家也可以了解本局游戏的情况。

如果是字符 " 0 " ,说明玩家没有踩中雷,根据游戏规,我们需要显示这个格子周围8个格子中存在雷的个数,这时候我们调用了get_mine_count函数,我们先看一下统计周围雷的个数的代码:

	return mine[x - 1][y] +		mine[x - 1][y - 1] +		mine[x][y - 1] +		mine[x + 1][y - 1] +		mine[x + 1][y] +		mine[x + 1][y + 1] +		mine[x][y + 1] +		mine[x - 1][y + 1] - 8 * "0";

我们发现,此代码将周围8个格子的字符全部加了起来,我们知道如果是字符 " 0 " 和字符 " 1 "所对应的ASCII码值相差1,我们可以通过ASCII码值来进行判断,我们将周围8个字符相加,然后再减去8个字符" 0 " 的和,这样,我们就可以得到周围8个格子中有多少个字符 " 1 " 的格子,也就是雷的个数。

为了方便大家理解,我们假定有10个雷,我们将Mine棋盘和show棋盘都显示,我们根据棋盘制定输入,看是否可以得到我们想要的结果:

如果我们排除万难,最终将81个格子排完,我们将会获得胜利,具体判断代码如下:

if (win == row * col - EASY_COUNT)	{		printf("恭喜你,排雷成功/n");		DisplayBoard(mine, row,col);	}

我们这里假定有80个雷,我们显示一下:

 至此,我们扫雷小游戏也写完了,完整代码我也放在我的Gitee仓库,链接如下:

C语言: C语言代码学习-练习 - Gitee.com

其中这3个对应资源管理器3个文件



总结

本节内容主要用C语言实现了小游戏---> 扫雷,大家可以拷贝到编译器里面玩一玩,如果大家觉得还不错有收获的话,点赞收藏走一波呗~ 

由于我的个人技术水平有限,各位大佬发现错误及时指出哦~

这里是 用C语言实现《三子棋 》 小游戏的链接,大家有兴趣也可以看看哦:

[ C语言 ] 用C语言实现小游戏 ---- 三子棋 代码 + 解析_小白又菜的博客-CSDN博客

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

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

相关文章

  • 扫雷1.0(递归实现

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

    CoderDock 评论0 收藏0
  • C语言实现入门级小游戏——扫雷

    摘要:上一期咱们用语言实现了三子棋的小游戏语言实现三子棋今天我们再来写个扫雷的游戏,说起扫雷,相信大家都不陌生,可能许多朋友还是玩扫雷的高手。      上一期咱们用C语言实现了三子棋的小游戏  C语言实现三子棋       今天我们再来写个扫雷的游戏,说起扫雷,相信大家都不陌生,可能许多朋友还是...

    nevermind 评论0 收藏0
  • C语言初阶学习——扫雷小游戏(递归)

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

    zhonghanwen 评论0 收藏0
  • 扫雷C语言版)

    摘要:展示雷盘和初始化雷盘不一样,展示雷盘只需要用即可,并不需要将都展示出来,只是为了我们更好的计算扫雷的位置周围的雷的数量。 目录 1、需求分析 2、程序架构 3、代码实现(分函数呈现) (1)主函数代码实现 分析: 异常处理: (2)游戏主函数实现 分析: (3)初始化函数的实现 分析: (4...

    EscapedDog 评论0 收藏0
  • 扫雷连爆(望大佬也可以帮忙优化或提出意见)(C语言版)------上

    摘要:新人小白的第一篇博客,有什么不好之处望多提意见。这个扫雷小游戏主要是基于二维数组,循环与基本的函数知识等。请输入坐标提示玩家输入坐标。换行是为了看着好看,要不然打印出来的数组会变形的。用来接收判断输赢的函数的返回值。 ​​​​​​​新人小白的第一篇博客,有什么不好之处望多提意见。      ...

    incredible 评论0 收藏0

发表评论

0条评论

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