首页 > 其他分享 >通过C语言玩扫雷

通过C语言玩扫雷

时间:2023-05-12 17:31:53浏览次数:46  
标签:COLS int 通过 mine C语言 char 扫雷 棋盘 我们

直接进入主题:先思考后敲代码!!

首先,我将扫雷分为两个棋盘,一个放雷,另一个为玩家猜测盘。

这就有同学问了,设置一个棋盘不就完了,这样不就搞复杂了吗?

先简短的回答这位同学的问题:

因为我的考虑是这样的,我用‘1’代表有雷,‘0’代表没有雷,如果放在一个盘中,出现多个1的时候,无法确定这是雷还是代表周围8个格子中有一个雷。

Copyright © 1999-2020, CSDN.NET, All Rights Reserved

通过C语言玩扫雷_初始化

打开APP

通过C语言玩扫雷_while循环_02

通过C语言玩扫雷_while循环_03

李逢溪

关注

C语言实现扫雷(含展开,附源码) 原创

 2021-11-13 23:03:01 52点赞

通过C语言玩扫雷_#define_04

李逢溪 

码龄2年

关注

我相信在做的各位都是玩过扫雷的,游戏玩法就不赘述了。


直接进入主题:先思考后敲代码!!

首先,我将扫雷分为两个棋盘,一个放雷,另一个为玩家猜测盘。

这就有同学问了,设置一个棋盘不就完了,这样不就搞复杂了吗?

先简短的回答这位同学的问题:

因为我的考虑是这样的,我用‘1’代表有雷,‘0’代表没有雷,如果放在一个盘中,出现多个1的时候,无法确定这是雷还是代表周围8个格子中有一个雷。

进一步解释

  图片参考:                      

通过C语言玩扫雷_初始化_05

当雷是1,还有记录数字也为1时,以下黄色标记位置为例:         

                                         

通过C语言玩扫雷_while循环_06

此时点击黄色位置,那么它显示的数字是2而不是1,我们会发现雷‘’变多了‘’。

但又有同学要问了,为啥非要用1代表雷,0代表没有雷呢,我用¥代表雷,@代表非雷就不会出现这种情况了。

其实这样安排是没问题的,我也鼓励大家去尝试一下,但分双棋盘带来的好处,经过后面的代码分析会体现出来。(之后可以出一个棋盘的版本)

需要注意的是我们采用‘1’和‘0’,即字符1和字符0代表有雷和没有雷。为什么要这样安排呢?这利于我们后续设计数组和函数,现在暂时解释到这,后面会让大家有一个更清楚,更系统的认知。

初步设计思路到此结束!现在开始发车了,请大家系好安全带

Copyright © 1999-2020, CSDN.NET, All Rights Reserved

通过C语言玩扫雷_#define_07

打开APP

通过C语言玩扫雷_初始化_08

通过C语言玩扫雷_while循环_09

李逢溪

关注

C语言实现扫雷(含展开,附源码) 原创

 2021-11-13 23:03:01 52点赞

通过C语言玩扫雷_初始化_10

李逢溪 

码龄2年

关注

我相信在做的各位都是玩过扫雷的,游戏玩法就不赘述了。


直接进入主题:先思考后敲代码!!

首先,我将扫雷分为两个棋盘,一个放雷,另一个为玩家猜测盘。

这就有同学问了,设置一个棋盘不就完了,这样不就搞复杂了吗?

先简短的回答这位同学的问题:

因为我的考虑是这样的,我用‘1’代表有雷,‘0’代表没有雷,如果放在一个盘中,出现多个1的时候,无法确定这是雷还是代表周围8个格子中有一个雷。

进一步解释

  图片参考:                      

通过C语言玩扫雷_初始化_11

当雷是1,还有记录数字也为1时,以下黄色标记位置为例:         

                                         

通过C语言玩扫雷_while循环_12

此时点击黄色位置,那么它显示的数字是2而不是1,我们会发现雷‘’变多了‘’。

但又有同学要问了,为啥非要用1代表雷,0代表没有雷呢,我用¥代表雷,@代表非雷就不会出现这种情况了。

其实这样安排是没问题的,我也鼓励大家去尝试一下,但分双棋盘带来的好处,经过后面的代码分析会体现出来。(之后可以出一个棋盘的版本)

需要注意的是我们采用‘1’和‘0’,即字符1和字符0代表有雷和没有雷。为什么要这样安排呢?这利于我们后续设计数组和函数,现在暂时解释到这,后面会让大家有一个更清楚,更系统的认知。

初步设计思路到此结束!现在开始发车了,请关好门窗,系好安全带!!


首先我们分文件设计游戏,分一个test.c来管理游戏的执行流程,一个game.c来实现游戏需要的自定义函数,一个game.h来封装函数声明,常数的定义,头文件的包含等。

test.c的初步游戏执行流程设计,参考以下代码:

void menu()
 {
     printf("******************\n");
 	printf("***   1.play   ***\n");
 	printf("***   0.exit   ***\n");
 	printf("******************\n");
 }
  
 int main()
 {
 	int input = 0;
 	do
 	{
 		menu();
 		printf("请选择:>");
 		scanf("%d", &input);
 		switch (input)
 		{
 		case 1:
 			game();
 			break;
 		case 0:
 			printf("已退出\n");
 			break;
 		default:
 			printf("输入错误,请重新输入\n");
 			break;
 		}
 	} while (input);
 	return 0;
 }

因为游戏可能需要玩很多次,为了不重新打开游戏,此处采用循环的形式,又因为游戏至少需要执行 一次,此处采用do while循环,用while循环其实问题也不大。好了,do while循环首先执行的是打印菜单,然后我们根据菜单来选择接下来要执行的分支,当我们选1的时候代表我们接下来要玩游戏,而选择0的时候我们要退出游戏,在这里我们选择用整形变量input来接受我们的选择,用switch来执行我们的选择。同时我们会发现安排退出数字为0时有一个好处,当input为0的时候直接可以退出循环,而非0可以继续循环,这完美符合我们的选择设计!!!

接下来就是函数game()的实现了。

我们刚刚讨论了,我们需要两个棋盘,一个雷盘,另一个为玩家猜测盘。

因此我们创建两个二维数组来代表这两个盘。

即(雷盘) char mine [ ] [ ] = { 0 }; (玩家界面盘)char show [ ] [ ] = { 0 };但这两个盘的大小分别为多大呢?这是我们要考虑的问题,根据初级扫雷难度,我们暂且安排为9X9的棋盘。为了更长远的考虑,我们不可能直接这样写char mine [ 9 ] [ 9 ] = { 0 };  char show [ 9 ] [ 9 ] = { 0 };为了以后的维护和花小代价的控制难度,我们用#define分别定义ROW为9,COL为9.但是我们真的想的够全面了吗?如果要统计处于边界位置周围的8个雷怎么算呢?这样无疑会造成数组越界。因此我们需要将棋盘扩展成11X11的棋盘。因此我们这样创建两个棋盘char mine [ ROWS ] [ COLS ] = { 0 };  char mine [ ROWS ] [ COLS ] = { 0 };

这里需要简单说一下:

#define ROWS ROW+2

#define COLS COL+2.

好了,我们终于有了可操作的对象了,现在我们需要给它们初始化。

先按照传统取个函数名吧,initboard(),就是它了。上代码!!!

在这里,我们用0初始化雷盘,代表所有位置都没有雷,用 * 来保持对该位置的神秘感,用来玩家猜测。

即         initboard(mine, ROWS, COLS, '0');
            initboard(show, ROWS, COLS, '*');

虽然没暂时没完成打印函数,但并不妨碍我们欣赏初始化结果

其实这里就可以体现为什么用字符‘1’和字符‘0’代表有雷和没有雷了,而不是数字1和0了,因为我们只要一个函数就可以两个盘都进行初始化。而如果一个棋盘是整数数组,另一个是字符数组,你就需要两个初始化函数了。


 初始化棋盘完了之后,我们需要完成剩下的打印函数,因为我们要检查我们的初始化函数是否按照我们的想法实现了对棋盘的初始化

此处EASY_COUNT是#define EASY_COUNT 9定义的常函数,意思是雷的简单数量。此处用rand()库函数对坐标X和Y分别设计随机数,%row+1和%col+1确保X和Y在 1~row 范围内,需要注意的是在给mine[ x ] [ y ]赋值的时候,要确保mine[ x ] [ y ]的位置没有埋雷,如果缺少上图if条件判断,这设置的雷可能变少,因为重复赋值,会覆盖上次的值。


哈哈哈,终于来激动人心的排雷环节了,此处应有掌声!!!

通过C语言玩扫雷_初始化_13

打开APP

通过C语言玩扫雷_初始化_14

通过C语言玩扫雷_#define_15

李逢溪

关注

C语言实现扫雷(含展开,附源码) 原创

 2021-11-13 23:03:01 52点赞

通过C语言玩扫雷_初始化_16

李逢溪 

码龄2年

关注

我相信在做的各位都是玩过扫雷的,游戏玩法就不赘述了。


直接进入主题:先思考后敲代码!!

首先,我将扫雷分为两个棋盘,一个放雷,另一个为玩家猜测盘。

这就有同学问了,设置一个棋盘不就完了,这样不就搞复杂了吗?

先简短的回答这位同学的问题:

因为我的考虑是这样的,我用‘1’代表有雷,‘0’代表没有雷,如果放在一个盘中,出现多个1的时候,无法确定这是雷还是代表周围8个格子中有一个雷。

进一步解释

  图片参考:                      

通过C语言玩扫雷_#define_17

当雷是1,还有记录数字也为1时,以下黄色标记位置为例:         

                                         

通过C语言玩扫雷_#define_18

此时点击黄色位置,那么它显示的数字是2而不是1,我们会发现雷‘’变多了‘’。

但又有同学要问了,为啥非要用1代表雷,0代表没有雷呢,我用¥代表雷,@代表非雷就不会出现这种情况了。

其实这样安排是没问题的,我也鼓励大家去尝试一下,但分双棋盘带来的好处,经过后面的代码分析会体现出来。(之后可以出一个棋盘的版本)

需要注意的是我们采用‘1’和‘0’,即字符1和字符0代表有雷和没有雷。为什么要这样安排呢?这利于我们后续设计数组和函数,现在暂时解释到这,后面会让大家有一个更清楚,更系统的认知。

初步设计思路到此结束!现在开始发车了,请关好门窗,系好安全带!!


首先我们分文件设计游戏,分一个test.c来管理游戏的执行流程,一个game.c来实现游戏需要的自定义函数,一个game.h来封装函数声明,常数的定义,头文件的包含等。

test.c的初步游戏执行流程设计,参考以下代码:

void menu()
 {
     printf("******************\n");
 	printf("***   1.play   ***\n");
 	printf("***   0.exit   ***\n");
 	printf("******************\n");
 }
  
 int main()
 {
 	int input = 0;
 	do
 	{
 		menu();
 		printf("请选择:>");
 		scanf("%d", &input);
 		switch (input)
 		{
 		case 1:
 			game();
 			break;
 		case 0:
 			printf("已退出\n");
 			break;
 		default:
 			printf("输入错误,请重新输入\n");
 			break;
 		}
 	} while (input);
 	return 0;
 }

因为游戏可能需要玩很多次,为了不重新打开游戏,此处采用循环的形式,又因为游戏至少需要执行 一次,此处采用do while循环,用while循环其实问题也不大。好了,do while循环首先执行的是打印菜单,然后我们根据菜单来选择接下来要执行的分支,当我们选1的时候代表我们接下来要玩游戏,而选择0的时候我们要退出游戏,在这里我们选择用整形变量input来接受我们的选择,用switch来执行我们的选择。同时我们会发现安排退出数字为0时有一个好处,当input为0的时候直接可以退出循环,而非0可以继续循环,这完美符合我们的选择设计!!!


接下来就是函数game()的实现了。

我们刚刚讨论了,我们需要两个棋盘,一个雷盘,另一个为玩家猜测盘。

因此我们创建两个二维数组来代表这两个盘。

即(雷盘) char mine [ ] [ ] = { 0 }; (玩家界面盘)char show [ ] [ ] = { 0 };但这两个盘的大小分别为多大呢?这是我们要考虑的问题,根据初级扫雷难度,我们暂且安排为9X9的棋盘。为了更长远的考虑,我们不可能直接这样写char mine [ 9 ] [ 9 ] = { 0 };  char show [ 9 ] [ 9 ] = { 0 };为了以后的维护和花小代价的控制难度,我们用#define分别定义ROW为9,COL为9.但是我们真的想的够全面了吗?如果要统计处于边界位置周围的8个雷怎么算呢?这样无疑会造成数组越界。因此我们需要将棋盘扩展成11X11的棋盘。因此我们这样创建两个棋盘char mine [ ROWS ] [ COLS ] = { 0 };  char mine [ ROWS ] [ COLS ] = { 0 };

这里需要简单说一下:

#define ROWS ROW+2

#define COLS COL+2.

好了,我们终于有了可操作的对象了,现在我们需要给它们初始化。

先按照传统取个函数名吧,initboard(),就是它了。上代码!!!

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

在这里,我们用0初始化雷盘,代表所有位置都没有雷,用 * 来保持对该位置的神秘感,用来玩家猜测。

即         initboard(mine, ROWS, COLS, '0');
            initboard(show, ROWS, COLS, '*');

虽然没暂时没完成打印函数,但并不妨碍我们欣赏初始化结果(参考下图)

    

通过C语言玩扫雷_#define_19

通过C语言玩扫雷_初始化_20

其实这里就可以体现为什么用字符‘1’和字符‘0’代表有雷和没有雷了,而不是数字1和0了,因为我们只要一个函数就可以两个盘都进行初始化。而如果一个棋盘是整数数组,另一个是字符数组,你就需要两个初始化函数了。


 初始化棋盘完了之后,我们需要完成剩下的打印函数,因为我们要检查我们的初始化函数是否按照我们的想法实现了对棋盘的初始化。代码如下:

void displayboard(char board[ROWS][COLS], int row, int col)
 {
 	int i = 0;
 	int j = 0;
 	for (i = 0; i <= col; i++)
 	{
 		if (i == 0)
 		{
 			printf("  %d     ", i);
 		}
 		else
 		{
 			printf("%d     ", i);
 		}
 	}
 	printf("\n------------------------------------------------------------\n");
 	for (i = 1; i <= row; i++)
 	{
 		printf("  %d  |", i);
 		for (j = 1; j <= col; j++)
 		{
 			printf("  %c  |", board[i][j]);
 		}
 		printf("\n------------------------------------------------------------\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--;
 		}
 	}
 }

此处EASY_COUNT是#define EASY_COUNT 9定义的常函数,意思是雷的简单数量。此处用rand()库函数对坐标X和Y分别设计随机数,%row+1和%col+1确保X和Y在 1~row 范围内,需要注意的是在给mine[ x ] [ y ]赋值的时候,要确保mine[ x ] [ y ]的位置没有埋雷,如果缺少上图if条件判断,这设置的雷可能变少,因为重复赋值,会覆盖上次的值。


哈哈哈,终于来激动人心的排雷环节了,此处应有掌声!!!先看图

通过C语言玩扫雷_#define_21

首先我们需要输入排查雷的坐标,因此我们创建两个整形变量X和Y,在我们输入X和Y的值时候,可能输入的X和Y并不符合要求,此时该 if 语句登场了。当我们输入的值符合要求的适合,我们先要判断是否mine [ X ] [ Y ] == '1',如果条件成立,则可以宣布游戏结束了,如果mine [ X ] [ Y ] == '1',不成立,则我们需要对坐标(X,Y)位置赋值,要统计它周围8个位置有多少个雷。统计坐标(X,Y)位置周围8个位置雷的个数我们用 int get_mine_count();代码如下:

void foundmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
 {
 	int x = 0;
 	int y = 0;
 	int iswin = 0;
 	while (iswin < 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
 			{
 				iswin++;
 				expand(mine, show, row, col, x, y);
 				displayboard(show, row, col);
 			}
 		}
 		else
 		{
 			printf("输入坐标不合法,请重新输入\n");
 		}
 	}
 	if (iswin == row * col - EASY_COUNT)
 	{
 		printf("恭喜你,排雷成功\n");
 	}
 }

排雷过程是整个游戏的核心,需要玩家排查出所有的雷的位置或者踩到雷,然后游戏才能结束,所以排雷函数一定是一个循环过程,这样才能取到多次排雷的效果。如何判断胜利?我们采取这样的一种设计思想:排查出所有非雷的位置,其他位置自然是雷,这样达到一个扫雷的效果。此处我采用整形变量 iswin 来当计数器,当输入一个非雷的坐标位置的时候,iswin+=1,当 iswin等于ROW*COL-EASY_COUNT的时候,即可判断游戏胜利。

通过C语言玩扫雷_#define_22

打开APP

通过C语言玩扫雷_初始化_23

通过C语言玩扫雷_while循环_24

李逢溪

关注

C语言实现扫雷(含展开,附源码) 原创

 2021-11-13 23:03:01 52点赞

通过C语言玩扫雷_while循环_25

李逢溪 

码龄2年

关注

我相信在做的各位都是玩过扫雷的,游戏玩法就不赘述了。


直接进入主题:先思考后敲代码!!

首先,我将扫雷分为两个棋盘,一个放雷,另一个为玩家猜测盘。

这就有同学问了,设置一个棋盘不就完了,这样不就搞复杂了吗?

先简短的回答这位同学的问题:

因为我的考虑是这样的,我用‘1’代表有雷,‘0’代表没有雷,如果放在一个盘中,出现多个1的时候,无法确定这是雷还是代表周围8个格子中有一个雷。

进一步解释

  图片参考:                      

通过C语言玩扫雷_初始化_26

当雷是1,还有记录数字也为1时,以下黄色标记位置为例:         

                                         

通过C语言玩扫雷_初始化_27

此时点击黄色位置,那么它显示的数字是2而不是1,我们会发现雷‘’变多了‘’。

但又有同学要问了,为啥非要用1代表雷,0代表没有雷呢,我用¥代表雷,@代表非雷就不会出现这种情况了。

其实这样安排是没问题的,我也鼓励大家去尝试一下,但分双棋盘带来的好处,经过后面的代码分析会体现出来。(之后可以出一个棋盘的版本)

需要注意的是我们采用‘1’和‘0’,即字符1和字符0代表有雷和没有雷。为什么要这样安排呢?这利于我们后续设计数组和函数,现在暂时解释到这,后面会让大家有一个更清楚,更系统的认知。

初步设计思路到此结束!现在开始发车了,请关好门窗,系好安全带!!


首先我们分文件设计游戏,分一个test.c来管理游戏的执行流程,一个game.c来实现游戏需要的自定义函数,一个game.h来封装函数声明,常数的定义,头文件的包含等。

test.c的初步游戏执行流程设计,参考以下代码:

void menu()
 {
     printf("******************\n");
 	printf("***   1.play   ***\n");
 	printf("***   0.exit   ***\n");
 	printf("******************\n");
 }
  
 int main()
 {
 	int input = 0;
 	do
 	{
 		menu();
 		printf("请选择:>");
 		scanf("%d", &input);
 		switch (input)
 		{
 		case 1:
 			game();
 			break;
 		case 0:
 			printf("已退出\n");
 			break;
 		default:
 			printf("输入错误,请重新输入\n");
 			break;
 		}
 	} while (input);
 	return 0;
 }

因为游戏可能需要玩很多次,为了不重新打开游戏,此处采用循环的形式,又因为游戏至少需要执行 一次,此处采用do while循环,用while循环其实问题也不大。好了,do while循环首先执行的是打印菜单,然后我们根据菜单来选择接下来要执行的分支,当我们选1的时候代表我们接下来要玩游戏,而选择0的时候我们要退出游戏,在这里我们选择用整形变量input来接受我们的选择,用switch来执行我们的选择。同时我们会发现安排退出数字为0时有一个好处,当input为0的时候直接可以退出循环,而非0可以继续循环,这完美符合我们的选择设计!!!


接下来就是函数game()的实现了。

我们刚刚讨论了,我们需要两个棋盘,一个雷盘,另一个为玩家猜测盘。

因此我们创建两个二维数组来代表这两个盘。

即(雷盘) char mine [ ] [ ] = { 0 }; (玩家界面盘)char show [ ] [ ] = { 0 };但这两个盘的大小分别为多大呢?这是我们要考虑的问题,根据初级扫雷难度,我们暂且安排为9X9的棋盘。为了更长远的考虑,我们不可能直接这样写char mine [ 9 ] [ 9 ] = { 0 };  char show [ 9 ] [ 9 ] = { 0 };为了以后的维护和花小代价的控制难度,我们用#define分别定义ROW为9,COL为9.但是我们真的想的够全面了吗?如果要统计处于边界位置周围的8个雷怎么算呢?这样无疑会造成数组越界。因此我们需要将棋盘扩展成11X11的棋盘。因此我们这样创建两个棋盘char mine [ ROWS ] [ COLS ] = { 0 };  char mine [ ROWS ] [ COLS ] = { 0 };

这里需要简单说一下:

#define ROWS ROW+2

#define COLS COL+2.

好了,我们终于有了可操作的对象了,现在我们需要给它们初始化。

先按照传统取个函数名吧,initboard(),就是它了。上代码!!!

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

在这里,我们用0初始化雷盘,代表所有位置都没有雷,用 * 来保持对该位置的神秘感,用来玩家猜测。

即         initboard(mine, ROWS, COLS, '0');
            initboard(show, ROWS, COLS, '*');

虽然没暂时没完成打印函数,但并不妨碍我们欣赏初始化结果(参考下图)

    

通过C语言玩扫雷_初始化_28

通过C语言玩扫雷_#define_29

其实这里就可以体现为什么用字符‘1’和字符‘0’代表有雷和没有雷了,而不是数字1和0了,因为我们只要一个函数就可以两个盘都进行初始化。而如果一个棋盘是整数数组,另一个是字符数组,你就需要两个初始化函数了。


 初始化棋盘完了之后,我们需要完成剩下的打印函数,因为我们要检查我们的初始化函数是否按照我们的想法实现了对棋盘的初始化。代码如下:

void displayboard(char board[ROWS][COLS], int row, int col)
 {
 	int i = 0;
 	int j = 0;
 	for (i = 0; i <= col; i++)
 	{
 		if (i == 0)
 		{
 			printf("  %d     ", i);
 		}
 		else
 		{
 			printf("%d     ", i);
 		}
 	}
 	printf("\n------------------------------------------------------------\n");
 	for (i = 1; i <= row; i++)
 	{
 		printf("  %d  |", i);
 		for (j = 1; j <= col; j++)
 		{
 			printf("  %c  |", board[i][j]);
 		}
 		printf("\n------------------------------------------------------------\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--;
 		}
 	}
 }

此处EASY_COUNT是#define EASY_COUNT 9定义的常函数,意思是雷的简单数量。此处用rand()库函数对坐标X和Y分别设计随机数,%row+1和%col+1确保X和Y在 1~row 范围内,需要注意的是在给mine[ x ] [ y ]赋值的时候,要确保mine[ x ] [ y ]的位置没有埋雷,如果缺少上图if条件判断,这设置的雷可能变少,因为重复赋值,会覆盖上次的值。


哈哈哈,终于来激动人心的排雷环节了,此处应有掌声!!!先看图

通过C语言玩扫雷_初始化_30

首先我们需要输入排查雷的坐标,因此我们创建两个整形变量X和Y,在我们输入X和Y的值时候,可能输入的X和Y并不符合要求,此时该 if 语句登场了。当我们输入的值符合要求的适合,我们先要判断是否mine [ X ] [ Y ] == '1',如果条件成立,则可以宣布游戏结束了,如果mine [ X ] [ Y ] == '1',不成立,则我们需要对坐标(X,Y)位置赋值,要统计它周围8个位置有多少个雷。统计坐标(X,Y)位置周围8个位置雷的个数我们用 int get_mine_count();代码如下:

void foundmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
 {
 	int x = 0;
 	int y = 0;
 	int iswin = 0;
 	while (iswin < 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
 			{
 				iswin++;
 				expand(mine, show, row, col, x, y);
 				displayboard(show, row, col);
 			}
 		}
 		else
 		{
 			printf("输入坐标不合法,请重新输入\n");
 		}
 	}
 	if (iswin == row * col - EASY_COUNT)
 	{
 		printf("恭喜你,排雷成功\n");
 	}
 }

排雷过程是整个游戏的核心,需要玩家排查出所有的雷的位置或者踩到雷,然后游戏才能结束,所以排雷函数一定是一个循环过程,这样才能取到多次排雷的效果。如何判断胜利?我们采取这样的一种设计思想:排查出所有非雷的位置,其他位置自然是雷,这样达到一个扫雷的效果。此处我采用整形变量 iswin 来当计数器,当输入一个非雷的坐标位置的时候,iswin+=1,当 iswin等于ROW*COL-EASY_COUNT的时候,即可判断游戏胜利。


重点来了,expand()函数的详细解析

这里重申以下get_mine_count()函数的功能:计算输入坐标(X,Y)位置周围8个位置有多少个雷。

expand()是一个扩展函数,功能是:

当排查的坐标位置get_mine_count()!=  0时候,将该位置的值改为get_mine_count()的返回值。

当排查的坐标位置周围为0个雷的时候,把该位置置为空,并检查周围8个位置是否它的周围也是0个雷,如果周围坐标位置有满足条件get_mine_count == 0 ,这将这个位置也置为空,如果周围周围的位置也满足条件get_mine_count == 0,这也将该位置置为0,如果周围的周围的周围也满足条件et_mine_count == 0.........。

说人话就是:以你输入的位置为起点,只要该位置get_mine_count == 0,就把它置空,同时把周围满足get_mine_count == 0也置空,同时也把周围这个位置也看做起点。显然满足递归思想,用递归能够很舒服的解决。

好了,以上就是扫雷的简单实现了,看到这里还不点个赞吗,哈哈。以后会出更多的系列,比如C语言所有关键字的解析与应用,或者更多的游戏实现。这是我的第一篇真正意义上的博客,希望大家多多关照。

上述如有错误,还请各位看官不吝赐教,在下感激不尽。

标签:COLS,int,通过,mine,C语言,char,扫雷,棋盘,我们
From: https://blog.51cto.com/u_16110604/6271496

相关文章

  • C语言程序设计(第四版)谭浩强版 课后答案 第四章
    4、#include<stdio.h>intmain(){inta,b,c;scanf("%d%d%d",&a,&b,&c);if(a>b){if(a>c){printf("maxnumis:%d\n",a);}......
  • 对于生下来只通过短视频学习的小孩来说,他还需要识字么?
    春节虽然已经过完,不过儿子的寒假还有最后一周,所以这周基本还是慢慢启动工作的状态,闲聊一个话题。从信息内容的供需看,最近几十年,产能明显越来越大,于是,从供不应求逐渐到供过于求,消费者(需求方)地位提升,供给方更需努力促进供需匹配,这个努力体现在两个方面,一是触达通路,二是内容形式。触达......
  • stm32 AES256加密 串口IAP升级 bootloader程序 通过上位机将keil生成的
    stm32AES256加密串口IAP升级bootloader程序通过上位机将keil生成的BIN文件进行AES加密,得到新的加密文件,加密需要自己设置秘钥,加密升级包直接烧录不能运行。通过串口升级上位机将加密包发送到单片机,单片机接收到数据后,会根据你事先设置好的秘钥,对数据进行还原,再写入。解密完成,程......
  • 单片机ADC,十大C语言滤波算法
    一、限幅滤波法1、方法:根据经验判断两次采样允许的最大偏差值(设为A) 每次检测到新值时判断: a.如果本次值与上次值之差<=A,则本次值有效b.如果本次值与上次值之差>A,则本次值无效,放弃本次值,用上次值代替本次值2、优点:能有效克服因偶然因素引起的脉冲干扰3、缺点......
  • django通过celery定时任务
    settings.py #Broker配置,使用Redis作为消息中间件BROKER_URL='redis://127.0.0.1:6379/0'#BACKEND配置,这里使用redisCELERY_RESULT_BACKEND='redis://127.0.0.1:6379/0'#结果序列化方案CELERY_RESULT_SERIALIZER='json'#任务结果过期时间,秒CELERY_TASK......
  • django通过channels实现websocket
     WebSocket协议是基于TCP的一种新的协议。WebSocket最初在HTML5规范中被引用为TCP连接,作为基于TCP的套接字API的占位符。它实现了浏览器与服务器全双工(full-duplex)通信。其本质是保持TCP连接,在浏览器和服务端通过Socket进行通信。当客户端向服务端发送连接请求时,不仅连接还会......
  • 通过 UE的反射机制来查找类里面的所有UPROPERTY,UFUCTION
    Property涵盖了UE中所有的原生类型Property是以链表的形式存储的,UE中提供了两种遍历方式:TFieldIteratorFPropertyValueIterator示例: UObject*Content;for(TFieldIterator<FProperty>PropertyIter(Content->GetClass());PropertyIter;++PropertyIter) { FPro......
  • Qt编写视频监控系统72-通过onvif增删改查OSD
    一、前言之前监控系统中原创的onvif协议解析机制,已经能够满足绝大部分用户的需要,比如搜索设备、获取视频流地址并播放、云台控制、预置位管理、图片亮度色彩饱和度等参数设置等,近期又多了一个需求,那就是通过onvif国际标准协议来对摄像头的OSD进行增删改查,可以通过协议添加OSD、删......
  • C语言之环形队列
    . 一、环形队列的优势环形队列是一种特殊的队列,它可以解决普通队列在使用时空间利用不充分的问题。在环形队列中,当队列满时,队列的尾指针指向队列的起始位置,而不是指向队列的最后一个元素。这样可以在不浪费空间的情况下存储更多的元素。      下面我们来详细讲解一下环形......
  • FreeCodeCamp-通过建立城市轮廓学习 CSS 变量
    index.html<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>CitySkyline</title><linkhref="styles.css"rel="stylesheet"/><......