扫雷游戏讲解

目录

一,游戏原理

二,扫雷游戏背后代码的创作与讲解

1、打印游戏目录

2、定义game函数

3、创建棋盘

​4、打印棋盘 

5、布置雷 

6、排查雷

三,总结

 


一,游戏原理

看到这幅图,相必大家都不会陌生,这正是陪伴我们整个童年的游戏--扫雷,那既然提到扫雷,我们都知道它的运作原理,就是简单的点一下图上的白方块,然后就会炸开,遇到雷时,就会停止炸裂,然后显示周围有几颗雷的数字(数字代表自己周围一圈雷的数量),让你猜雷的位置在哪 ,然后对有雷的位置插上小红旗,排除所有的雷就可以通关了。但是,一旦点到雷了,就会导致游戏结束。

二,扫雷游戏背后代码的创作与讲解

1、打印游戏目录

那既然我们已经知道了扫雷游戏的运行原理,那我们便可以通过c语言来将这款游戏进行还原。

首先,我们先创建1个项目,并再其添加2个源文件和1个头文件,就像这样:

首先test.c(源文件)是整个游戏的逻辑运行,game.h(头文件)是游戏相关的函数声明,game.c(源文件)是游戏相关的函数的实现。

那创作好我们的文件之后,我们就可以开始创建目录,这是每个游戏都必不可少的一个环节,图: 

 图中的#include "game.h",是我们待会要用到的头文件,所以在此引用,图中的game()函数的主体,我放入game.c中,待会就可以看见。好的,我们以这样的形式搭建好我们的游戏目录,其中do-while循环是至关重要的,它可是整个代码逻辑的主体,务必请大家熟练掌握。

2、定义game函数

在搭建好游戏目录之后,我们就开始思考下一个步骤,通过观察,我们不难发现,扫雷这款游戏跟我们所学的二维数组非常相似,可以说是一模一样,都是由行和列所组成,那既然这样,那我们便可以创造一个二维数组,但我们首先要想一个真的够吗?当我们用'0'和'1'来分别表示”没雷“和”有雷“,那我们有没有想过,当我们所猜的地方正好周围有一颗雷时,那这个数字“1”到底表示的是“有雷”还是“周围雷的数量了”。所以为了方便使用,我们可以创造两个二维数组,一个用于“专门存放布置好雷的信息”(这里我们就用数组mine代替),另一个“专门存放排查雷的信息”(这里我们就用数组show来表示),我们就可以把雷布置到mine数组,在数组mine中排查雷,将排查出的数据存放于show数组中,并打印show数组的信息给后期排查参考。

mine数组

show数组 

这两张图只是个例子,仅供参考,不必研究!!!

3、创建棋盘

通过对扫雷页面的观察,我们可知,在不同的的模式下,扫雷游戏的棋盘大小会发生变化,但其中最为基础的还是9*9的棋盘,于是我们便可以在game.h(头文件)中定义"row"和"cow",如图:

那就会有人问了,那个rows为啥后面跟着row+2(cols也是同理)了?这是因为当我们扫雷时,我们有时候点的位置可能会在边边角角的位置,但我们有没有想过?我们明明设置的是9*9的棋盘,但当我们统计所点地方周围雷的数量时,在9*9的范围内的好统计,但一旦超出这个范围,不就形成了越界访问这种现象嘛!所以为了防止这种现象,我们就在其周围扩大1圈(让纵行和横行各加一个2),所扩大的范围什么的不用加,就是为了防止越界访问这种现象出现,还有以后为了方便改变棋盘的大小,我们可以随时将row后面跟的9改成任意数字,但我们这里还是以最基本的棋盘来讲解。

搞清楚我们要创建的棋盘之后,我们就可以开始创建一个关于棋盘的函数“Initborad”,这里我们将show数组开始初始化为字符'*',为了保持两个数组的类型一致,可以使用同一套函数处理时,mine数组最开始也初始化为字符'0',布置雷改成'1'。

注意:这里需使用包含game.h的头文件,才能实现棋盘的初始化,这里用Rows和Cols是为了区分实参和形参,便于理解。

4、打印棋盘 

初始化棋盘之后就需打印出来,我们便可以创建DisplayBoard 函数实现,如图

这里打印行号和列号,是为了方便观察,填写相对应的坐标,就像这样:

5、布置雷 

我们棋盘创建好之后,我们便可以开始放置雷了,既然要放置雷,我们肯定希望雷的位置是完全随机的,所以我们可以创建一个SetMine函数来实现这一原理

注意: 在用rand函数时,需要用到srand函数、time.h和stdlib.h这两个头文件!!!

6、排查雷

布置完雷之后,我们就要开始排雷了,那该怎么排雷了?

首先,我们讲过在排雷的时候,我们所点的位置会显示周围有几颗雷,那根据这个原理,我们就可以统计它周围有多少个以'1'这样字符的雷,因为我们前面用这个'1'来表雷,用'0'表示“没有雷”,而且'1'的ASCLL对应的值为“49”,'0'对应的ASCLL对应的值为“48”,所以我们就可以得到用'1'-'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';
}

 这样我们的扫雷程序就基本完成了,以下便是完整代码:

test.c

#include<stdio.h>
#include "game.h"
 
void menu()
{
	printf("****************\n");
	printf("***  1.play  ***\n");
	printf("***  2.exit  ***\n");
	printf("****************\n");
}

//完成扫雷游戏的整个过程
void game()
{
	char mine[rows][cols] = { 0 };//存放布置好雷的信息
	char show[rows][cols] = { 0 };//存放排查出的雷的信息用于显示
	//初始化棋盘
	Initborad(mine, rows, cols,'0');//初始化"0"
	Initborad(show, rows, cols,'*');//初始化"*"

	DisplayBoard(show, row, col);
	/*DisplayBoard(mine, row, col);*/
	
	//布置雷
	SetMine(mine, row, col);
	/*DisplayBoard(mine, row, col);*/

	//排查雷
	FindMine(mine,show,row,col); 
}



int main()
{
	int a = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请输入数字:");
		scanf_s("%d", &a);
		switch (a)
		{
		case 1:
			game();
			break;
		case 2:
			printf("已退出游戏\n");
				break;
		default:
			printf("选择错误,请重新选择\n");
				break;
		}
	} while (a);
			return 0;
}

game.c 

#include "game.h"

void Initborad(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;
		}
	}
}

void DisplayBoard(char board[rows][cols], int Row, int Col)
{
	int i = 0;
	printf("----- 扫雷 -----\n");
	for (i = 0; i <= Row; i++)//打印列号
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i <= Row; i++)
	{
		int j = 0;
		printf("%d ", i);//打印行号, 
		for (j = 1; j <= Col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
}

//布置雷
void SetMine(char board[rows][cols], int Row, int Col)
{
	int count = EASY_COUNT;//用EASY_COUNT代表几个雷,方便以后随时更改雷的数量
	while (count)
	{
		int x = rand()%Row + 1;//生成的随机数范围为1~Row
		int y = rand()%Col + 1;//生成的随机数范围为1~Col
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
	}
}

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';
}
//排查雷
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_s("%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
			{
				if(show[x][y]!='*')
				{
					printf("该坐标已经排查过了,无需再排查\n");
				}
				else
				{
					//统计mine数组的x,y坐标周围8个坐标中有几个雷
					int count = GetMineCount(mine, x, y);
					show[x][y] = count + '0';
					DisplayBoard(show, row, col);
				}
			}
		}
		else
		{
			printf("输入的坐标非法,请重新输入\n");
		}
	}
	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, row, col);
	}
}

game.h 

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

#define EASY_COUNT 10

#define row 9
#define col 9

#define rows row+2
#define cols col+2


//棋盘的初始化
void Initborad(char board[rows][cols], int Rows, int Cols, char set);

//打印棋盘
void DisplayBoard(char board[rows][cols], int Rows, int Cols);

//布置雷
void SetMine(char board[rows][cols], int Row, int Col);

//排查雷
void FindMine(char mine[rows][cols], char show[rows][cols], int Row, int Col);

三,总结

 以上就是扫雷的全部过程了,小编我也是第一次编写这么多的程序,虽然可能在某些地方讲的不太好,但希望大家多多包容,有错误的地方,希望大家可以指出来,我们可以一起研究学习。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值