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

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

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

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

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

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

通过C语言玩扫雷_#define

打开APP

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

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

李逢溪

关注

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

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

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

李逢溪 

码龄2年

关注

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


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

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

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

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

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

进一步解释

  图片参考:                      

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

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

                                         

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

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

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

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

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

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

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

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

打开APP

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

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

李逢溪

关注

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

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

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

李逢溪 

码龄2年

关注

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


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

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

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

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

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

进一步解释

  图片参考:                      

通过C语言玩扫雷_#define_11

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

                                         

通过C语言玩扫雷_初始化_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语言玩扫雷_while循环_13

打开APP

通过C语言玩扫雷_#define_14

通过C语言玩扫雷_#define_15

李逢溪

关注

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

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

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

李逢溪 

码龄2年

关注

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


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

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

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

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

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

进一步解释

  图片参考:                      

通过C语言玩扫雷_#define_17

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

                                         

通过C语言玩扫雷_初始化_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语言玩扫雷_while循环_19

通过C语言玩扫雷_#define_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语言玩扫雷_#define_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语言玩扫雷_while循环_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语言所有关键字的解析与应用,或者更多的游戏实现。这是我的第一篇真正意义上的博客,希望大家多多关照。

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