扫雷详解(附代码)(保姆级教学)

前言

我们都知道扫雷的玩法,那怎么通过C语言来实现呢?希望通过阅读这篇文章可以给你带来帮助,我们从创建头文件,源文件开始,到最后实现整个游戏,全程一步一步手拿把掐的分享博主的经验,以下内容是详细过程及代码。话不多说,直接上货!

一·创建源文件 头文件

我们在vs2019中创建一个头文件,两个源文件,头文件用来声明函数,两个源文件一个用来写游戏实现的代码,一个用来写主函数。例如这样:

要想完成扫雷游戏的全部程序,我们要想通怎么设计这个游戏,首先我们要确定要设置几个炸弹,所以我们在头文件中定义一个炸弹变量,EASY_COUNT.,初始棋盘全是‘0’,当炸弹被布置的时候,此时设为‘1’,然后因为是扫雷游戏嘛,我们需要一个棋盘来进行埋雷和排查雷的过程,其次我们需要另外一个棋盘来显示当我们选择其中的的一个位置以后,这个位置不是雷,此时我们要显示在这个位置的周围雷的个数信息,我们把这个信息存储到另外一个棋盘当中,所以我们一共需要两个棋盘,想通这个我们就可以进行下一步的游戏设计了,像三子棋一样,我们需要先定义行和列,我们在这里设置变量名称为ROW和COL,因为扫雷棋盘一般都是9X9的形式,所以我们在这里设置为9X9。

但是想到这里是不是有一点小问题呢?问题就出现在当我们选择的点是边缘点时,它周围的点不足八个,此时我们就会出现溢出的情况:如下图展示

 如左图展示,当我们选择左下角的点时,它周围只有三个点的信息,但是我们要遍历八个点的信息,这时候就会出现溢出的情况,那我们怎么解决这个问题呢?再给棋盘大一圈不就好了嘛,我们在这里再设置两个变量ROWS,COLS,大小为11X11,解决完这个问题以后,我们再进行下一步的游戏设计,我们看右图的棋盘,我们先初始化棋盘,使这个棋盘所有的位置都显示‘*’,表示这个点未被选择,当这个点被选择时,此点显示周围雷的个数的信息。

当想到这里时,我们就快完成整个游戏的设计了,之后我们再声明提到的四个函数,分别是初始化棋盘 InitBoard,打印棋盘,DisplayBoard,布置雷,SetMine,排查雷,FindMine。

代码如下展示:

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

#define EASY_COUNT 10

#define ROW 9
#define COL 9

#define ROWS ROW+2
#define COLS COL+2

//初始化棋盘
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 board[ROWS][COLS], int row, int col);

//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

 

二.游戏的创建

第一步,我们要在主函数的源文件中写一个菜单代码,如下展示:

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

第二步,我们进入主函数, 因为此游戏涉及到随机布置雷,所以加入一个随机数。

再后,我们可以通过上面的游戏设计可以看到,当我们选择1的时候,进入游戏,选择0的时候,退出游戏,选择其他的数字,则不能识别到,这时候要提醒玩家输入错误,所以我们这时候用到了Switch-case语句,但我们不是只玩一次游戏,这时候我们可以就使用do-while语句来循环是否要继续进行扫雷,代码如下:

int main()
{
	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);
	return 0;
}

代码写到此步骤时,我们先来看看运行的结果吧,如下图所示:

 

 第三步,当我们选择1进入游戏的时候,我们写一个游戏的函数,game(),接下来博主要讲的是game()具体实现的步骤:

首先我们要设置两个数组mine,show,然后我们要初始化棋盘,使mine数组中一开始全部为‘0’,show数组中一开始全部为‘*’,这时候我们就需要把棋盘打印下来,一定要在这里注意!一定要把显示雷的数组打印下来,而不是把布置雷的数组打印下来,如果把布置雷的数组打印下来,那岂不是玩家一眼就能看到雷布置在哪里了嘛,所以我们在这里只能打印第二个数组。

第二步就是布置雷了,我们把雷布置到mine数组中,布置完以后我们可以打印看一下,但是不要给玩家看布置到哪里,之后我们要注销掉这行代码。

最后一步就是排查雷,我们要在mine数组中排查,并把排查到雷的个数信息展示在show中。

代码展示如下:

void game()
{
	char mine[ROWS][COLS];//存放布置好的雷
	char show[ROWS][COLS];//存放排查出的雷的信息
	//初始化棋盘
	//1.mine数组最开始全是' 0 '
	//2.show数组最开始全是' * '
	InitBoard(mine, ROWS, COLS, '0');
	InitBoard(show, ROWS, COLS, '*');
	//打印棋盘
	//DisplayBoard(mine, ROW, COL)
	DisplayBoard(show, ROW, COL);
	//1.布置雷
	SetMine(mine, ROW, COL);
	//DisplayBoard(mine, ROW, COL)
	//2.排查雷
	FindMine(mine, show, ROW, COL);
}

 看完这段代码,可能有些小伙伴就有疑问了,为什么你的行和列的变量一会儿是ROWS,一会儿是COLS,一会儿是ROW,一会儿是COL,这是因为一开始我们只是对11X11的棋盘进行初始化,我们并不对最外层的数据进行操作,我们操作的一直都是9X9的棋盘,所以我们在打印棋盘,布置雷,排查雷的时候,始终对9X9的棋盘进行就好啦。

三.游戏的实现

我们之前提到了五个函数,初始化棋盘函数,打印棋盘函数,布置雷函数,显示雷的个数信息的函数以及排查雷函数。

3.1初始化棋盘函数

首先我们要对两个棋盘进行初始化操作,把mine数组中全部初始化为‘0’,把show数组中全部初始化为‘*’,为了方便初始化为我们想要的内容,我们引入一个变量ret,然后使用for循环遍历两个数组中的每个位置。

代码如下展示:

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

3.2打印棋盘函数

首先,就像博主上面说的,我们是对棋盘中的9X9位置进行操作,所以我们只需要打印其中的9X9就好,为了便于观察游戏的状态,我们可以在打印棋盘前加上一句话***********扫雷游戏**********之后为了方便玩家观察第几行第几列,我们可以在棋盘的上边和左边加上数字,可以使玩家更快定位到想选择的位置,我们使用for循环打印列,然后换行,开始打印行数,使用for循环打印每一行的数字,然后再使用for循环遍历每一列,这样的话,我们就能完整的打印出整个9X9棋盘。

代码如下展示:

void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	printf("***********扫雷游戏**********\n");
	for (i = 0; i <= col; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);
		int j = 0;
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
}

3.3布置雷函数

我们要在棋盘上随机地生成10个雷,所以这个时候我们使用到随机数函数,我们设置一个变量来存放炸弹的个数,因为炸弹是一个一个的布置,所以这个时候我们使用while语句,当炸弹全部布置完时,跳出while语句,然后我们设置两个变量x和y,用来存放炸弹的坐标,当炸弹的坐标对应的是‘0’时,我们就把这个位置放置炸弹,使‘0’变为‘1’,每当放置一个炸弹时,总的炸弹数量就减一,总体思路就是这样的。

代码如下展示:

void SetMine(char board[ROWS][COLS], int row, int col)
{
	//布置10个雷
	//生成随机的坐标,布置雷
	int count = EASY_COUNT;
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
	}
}

3.4显示雷的个数信息函数

此信息展示在show数组中,当我们把在mine数组选择的点的坐标信息传递给show数组时,我们写一个遍历这个点周围八个点的函数GetMineCount,因为我们之前在mine数组中存放的都是‘0’‘1’,所以我们可以通过这个这条信息来设计返回此点周围雷的个数信息。

代码展示如下:

int GetMineCount(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');
}

3.5排查雷函数

既然是排查雷,那首先要输入你要排查的坐标,这里设置两个变量x和y,用来存放坐标的信息,因为是扫雷,游戏的设计者肯定不会只放入一个雷,所以我们这里用到了while循环,条件是 只要不踩雷就会一直排查下去,直到棋盘中只剩下雷的个数,此时我们设置一个变量win来记录循环的次数。

想清楚这一点,我们就继续往下进行,对于玩家输入的坐标,我们首先要对其进行判断到底合不合理,如果不合理则提示玩家重新输入,合理则进行下一步;

当玩家在mine数组中选择的点存放着‘1’,则该位置是炸弹,则排雷结束,并打印出mine数组给玩家看。当该位置不是雷的时候,那我们就统计该位置周围有几个雷,这时我们就用到了GetMineCount函数,我们此时设置一个变量count,用来存放此函数返回的值,然后在show数组对应的位置展示结果,并打印出show数组给玩家展示,之后win加一。

当循环次数等于行和列的乘积减去炸弹的个数时,打印排雷成功,并打印mine数组。

代码展示如下:

void FindMine(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 = GetMineCount(mine, x, y);
				show[x][y] = count + '0';
				DisplayBoard(show, ROW, COL);
				win++;
			}
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
	}
	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, ROW, COL);11
	}
}

四.游戏结果展示

 该结果展示的是棋盘中有80个雷的情况,玩家可自行设置炸弹的个数。

 

五.结束语

这就是扫雷有关的全部内容啦~希望这篇文章可以给你带来实质性的帮助,最后也祝你早日写出自己的扫雷代码哦~

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值