九折扫雷?我也就看一遍就会了!

如果你对其他的C++案例或知识感兴趣,请考虑阅读我的专栏:

C++学习【专栏】

须知

本文仅作学习笔记使用,仅在CSDN网站发布,如果在其他网站发现,均为侵权行为,请举报。作者:小王在努力。

说明

 本案例使用的是Easyx实现的,如果没有安装Easyx的朋友可能不能运行这个案例的源码(但是下方的exe文件还是可以运行的),Easyx的官网地址如下:
Easyx官网,官网中有详细的下载教程、安装过程、以及Easyx的帮助文档等。

一、游戏展示

 1.游戏界面说明

 游戏界面整体分成两部分:界面区和游戏区。
在这里插入图片描述

 2.游戏文件

 游戏的exe文件放到这里了:
扫雷游戏【百度网盘地址】 提取码:slyx
 大家有兴趣的可以下载试玩一下。

 如果大家被百度网盘的下载速度感动的话,可以私信我,我给大家在QQ上一对一传(目前实在想不到啥好办法上传文件)。

二、案例实现过程

 1.案例分析

扫雷游戏的核心内容分为两个大部分:1、背景部分 2、方块部分 。其次就是:界面部分。

  背景部分和方块部分的显示,都是用二维数组来实现的,也就是背景部分有一个二维数组,方块部分有一个二维数组。其中二维数组元素的值就是对应图片的序号。比如:数字1图片对应的序号是1,我们在背景部分,在想输出数字1的地方,将他的数组元素值设置为1。然后遍历整个数组,根据二维数组的元素值进行输出。

扫描二维码关注公众号,回复: 11445935 查看本文章

  输出图片的方法:

  1. 将图片放入到根目录下,将图片资源的名称和字符数组对应起来(也就是和序号对应起来)
	this->lps[0]="空.jpg";
	this->lps[1]="数字1.jpg";
	this->lps[2]="数字2.jpg";
	this->lps[3]="数字3.jpg";
	this->lps[4]="数字4.jpg";
	this->lps[5]="数字5.jpg";
	this->lps[6]="数字6.jpg";
	this->lps[7]="数字7.jpg";
	this->lps[8]="数字8.jpg";
	this->lps[9]="未选中.jpg";
	this->lps[10]="选中.jpg";
	this->lps[11]="空.jpg";
	this->lps[12]="炸弹(未炸).jpg";
	this->lps[13]="炸弹引爆.jpg";
	this->lps[14]="小红旗.jpg";
  1. 使用loadimage()函数 将图片加载到IMAGE对象数组中
//根据设置好的数组元素值将对应的图片载入到IMAG对象中,方便后续输出图片
	for(int i=1;i<=10;i++)
	{
		for(int j=1;j<=10;j++)
		{
			loadimage(&img[(i-1)*10+j],_T("IMAGE"),lps[this->b_m[i][j]]);
		}
	}
  1. 使用putimage()函数 将IMAGE对象数组中保存的图片输出到电脑的制定位置
	for(int i=1;i<=10;i++)
		for(int j=1;j<=10;j++)
			putimage(40*(i-1),40*(j-1)+200,&img[(i-1)*10+j]);//根据存储图片的对象数组元素值进行输出

  1.1 背景部分

    这里说的背景部分是在扫雷游戏一开始就生成的带有炸弹和数字还有空的一张图,我给大家展示一下我的背景部分:
在这里插入图片描述
    从这个背景部分,我们可以看出在游戏一开始我们需要做的事有这么几件:
    1.随机生成炸弹: Back类->void setM();
    2.根据炸弹生成周围的数字: Back类->void setM();
    3.将除了炸弹和周围的数字之外的所有部分填充为空: Back类->void setM();

  1.2 方块部分

    这里说的方块部分是覆盖在背景部分的上方的方块。也就是在背景部分上输出一层方块,将背景覆盖住:
在这里插入图片描述
    这部分只需要注意理解和背景部分的层级关系就可以了。由于我们每次消除的方块大多都是一个,所以我们这个方块部分就是由100(10×10)的方块组成的。在这部分,我们要做的事情就有这么几件:
    1.鼠标左键事件: Block类->void leftClick(int x,int y,intb_m[][11],int &flag,int &b_x,int &b_y)
    2.鼠标右键事件: Block类->rightClick(int x,int y)
    3.判断游戏是否通关: Block类->void isVoctory(int bomb_x[],int bomb_y[],int &flag)

  1.3 界面部分

    界面部分是位于背景部分和方块部分上方的的一部分,用来 说明游戏和重新进行游戏的区域:
在这里插入图片描述
    这部分我们需要做的事情就很简单了:
    1.鼠标左键事件: Surface类->void leftClick(int flag)
    2.设置图片更换: Surface类->void set(int flag)

  1.4 总结

    大体思路就是将上面三部分完成就可以实现这个游戏了,对于每个部分要处理的事件,在下方对应类的方法中都有明确的说明。

 2.类的设计

接下来就是关于类的设计了,我们根据上面的三部分,很容易就能联想到设计三个类:界面类(Surface)、方块类(Block)、背景类(Back)。

  在此处建议大家在做一些案例之前,要多想几遍整个游戏的流程,然后用思维导图的方式将类画出来,并将程序的流程图画出来,对整个案例有极大的帮助。
  这是博主在做这个游戏之前画的类的设计图,虽然最后改的和以前的简直不像一个版本,但是对梳理整个过程还是很有帮助的(流程图就不放了,博主手画的,博主的字体属实偏“狂草”(辨识度极低),就不丢人现眼了)。
在这里插入图片描述
  这是最后的样子:
在这里插入图片描述

  2.1 Back类

    头文件

#pragma once
#include<graphics.h>
class Back
{
private:
	IMAGE img[101];//存储图片的对象数组
	LPCTSTR lps[16];//字符数组
	
public:
	int b_m[11][11];//存储背景信息的二维数组
	int bomb_x[11];//存储随机生成的炸弹在数组中的列序号
	int bomb_y[11];//存储随机生成的炸弹在数组中的横序号

	Back(void);
	~Back(void);
	void setM();//设置存储北京信息的二维数组的初始值
	void showBack();//输出背景图片
	void setBomb(int x,int y);//设置目标炸弹为引爆
	
};


    源文件

#include "Back.h"
#include<cstdlib>
#include<graphics.h>
#include<ctime>

Back::Back(void)
{
	this->lps[0]="空.jpg";
	this->lps[1]="数字1.jpg";
	this->lps[2]="数字2.jpg";
	this->lps[3]="数字3.jpg";
	this->lps[4]="数字4.jpg";
	this->lps[5]="数字5.jpg";
	this->lps[6]="数字6.jpg";
	this->lps[7]="数字7.jpg";
	this->lps[8]="数字8.jpg";
	this->lps[9]="未选中.jpg";
	this->lps[10]="选中.jpg";
	this->lps[11]="空.jpg";
	this->lps[12]="炸弹(未炸).jpg";
	this->lps[13]="炸弹引爆.jpg";
	this->lps[14]="小红旗.jpg";
	setM();//初始化背景
}


Back::~Back(void)
{
}
//图片-序号对照表
//	lps[1]="数字1.jpg";
//	lps[2]="数字2.jpg";
//	lps[3]="数字3.jpg";
//	lps[4]="数字4.jpg";
//	lps[5]="数字5.jpg";
//	lps[6]="数字6.jpg";
//	lps[7]="数字7.jpg";
//	lps[8]="数字8.jpg";
//	lps[9]="未选中.jpg";
//	lps[10]="选中.jpg";
//	lps[11]="空.jpg";
//	lps[12]="炸弹(未炸).jpg";
//	lps[13]="炸弹引爆.jpg";
//	lps[14]="小红旗.jpg";

//输出背景函数:
//显示背景图片,包括:炸弹、数字、空。
void Back::showBack()
{
	for(int i=1;i<=10;i++)
		for(int j=1;j<=10;j++)
			putimage(40*(i-1),40*(j-1)+200,&img[(i-1)*10+j]);//格局存储图片的对象数组元素值进行输出
}

//设置数组函数:
//在数组中随机产生10个炸弹,可以通过分别产生i方向的10个数
//和j方向的10个数进行组合,形成10个炸弹
void Back::setM()
{
	for(int i=1;i<=10;i++)
		for(int j=1;j<=10;j++)
			this->b_m[i][j]=0;
	srand((int(time(0))));//设置随机数种子
	for(int i=1;i<=10;i++)
	{
		this->bomb_x[i] = (rand()%9)+1;//产生1-10之间的随机点的i
	}
	for(int i=1;i<=10;i++)
	{
		this->bomb_y[i] = (rand()%10)+1;//产生1-10之间的随机点的j
		while(this->b_m[this->bomb_x[i]][this->bomb_y[i]]==12)//为了产生不重合的10个炸弹(因为产生的随机数组合形成的点可能重合)
			this->bomb_y[i] = (rand()%10)+1;			  //原理:对已经产生的炸弹进行标记
		this->b_m[this->bomb_x[i]][this->bomb_y[i]]=12;//用炸弹图片对应的序号进行标记,一举两得,既方便后面设置图片,又能避免炸弹重合
		
	}	

	//生成炸弹旁边的数字,判断一个炸弹周围的8个数组元素是否为炸弹
	//如果不是的话,就让他的数组元素加1,是的话就不修改数组元素的值,
	//最后数组元素的值,就是炸弹周围的数字的值
	for(int i=1;i<=10;i++)
	{

			if(this->b_m[this->bomb_x[i]-1][this->bomb_y[i]-1]!=12) this->b_m[this->bomb_x[i]-1][this->bomb_y[i]-1]++;
			if(this->b_m[this->bomb_x[i]-1][this->bomb_y[i]]!=12) this->b_m[this->bomb_x[i]-1][this->bomb_y[i]]++;
			if(this->b_m[this->bomb_x[i]-1][this->bomb_y[i]+1]!=12) this->b_m[this->bomb_x[i]-1][this->bomb_y[i]+1]++;
			if(this->b_m[this->bomb_x[i]][this->bomb_y[i]-1]!=12) this->b_m[this->bomb_x[i]][this->bomb_y[i]-1]++;
			if(this->b_m[this->bomb_x[i]][this->bomb_y[i]+1]!=12) this->b_m[this->bomb_x[i]][this->bomb_y[i]+1]++;
			if(this->b_m[this->bomb_x[i]+1][this->bomb_y[i]-1]!=12) this->b_m[this->bomb_x[i]+1][this->bomb_y[i]-1]++;
			if(this->b_m[this->bomb_x[i]+1][this->bomb_y[i]]!=12) this->b_m[this->bomb_x[i]+1][this->bomb_y[i]]++;
			if(this->b_m[this->bomb_x[i]+1][this->bomb_y[i]+1]!=12) this->b_m[this->bomb_x[i]+1][this->bomb_y[i]+1]++;
	}
	//根据设置好的数组元素值将对应的图片载入到IMAG对象中,方便后续输出图片
	for(int i=1;i<=10;i++)
	{
		for(int j=1;j<=10;j++)
		{
			loadimage(&img[(i-1)*10+j],_T("IMAGE"),lps[this->b_m[i][j]]);
		}
	}
}

//设置目标炸弹引爆
//将目标炸弹的存储图片信息的数组进行更改,改为炸弹引爆.jpg
//在下次输出的时候即可显示为目标炸弹被引爆
void Back::setBomb(int x,int y)
{
	loadimage(&img[(x-1)*10+y],_T("IMAGE"),lps[13]);
}


  2.1 Block类

    头文件

#pragma once
#include<graphics.h>
class Block
{
private:
	IMAGE img[101];//存储图片的对象数组
	LPCTSTR lps[16];//字符数组
	
public:
	int bk_m[11][11];//存放方块信息的二维数组
	Block(void);
	~Block(void);
	void showBlock();//输出方块函数
	void initM();//初始化方块数组元素值函数
	//void moveChoice(MOUSEMSG m);
	void leftClick(int x,int y,int b_m[][11],int &flag,int &b_x,int &b_y);//鼠标左键消息处理函数
	void rightCLick(int x,int y);//鼠标右键消息处理函数
	void TraceBack(int b_m[][11],int i,int j);//递归函数
	void isVoctory(int bomb_x[],int bomb_y[],int &flag);//判断游戏是否结束函数
};


    源文件

#include "Block.h"
#include<graphics.h>

Block::Block(void)
{
	initM();
}


Block::~Block(void)
{
}

//初始化方块数组元素值函数
//首先将图片与字符数组对应起来
//然后将方块数组元素的值全部设置为9(也就是默认状态的下的方块为未选中状态)
//然后将图片全部加载到IMAGE对象数组中。
void Block::initM()
{
	this->lps[1]="数字1.jpg";
	this->lps[2]="数字2.jpg";
	this->lps[3]="数字3.jpg";
	this->lps[4]="数字4.jpg";
	this->lps[5]="数字5.jpg";
	this->lps[6]="数字6.jpg";
	this->lps[7]="数字7.jpg";
	this->lps[8]="数字8.jpg";
	this->lps[9]="未选中.jpg";
	this->lps[10]="选中.jpg";
	this->lps[11]="空.jpg";
	this->lps[12]="炸弹(未炸).jpg";
	this->lps[13]="炸弹引爆.jpg";
	this->lps[14]="小红旗.jpg";

	for(int i=1;i<=10;i++)
		for(int j=1;j<=10;j++)
			this->bk_m[i][j]=9;//初始化方块数组元素值为9,也就是默认状态下的方块为未选中状态

	for(int i=1;i<=10;i++)
	{
		for(int j=1;j<=10;j++)
		{
			if(this->bk_m[i][j]==-1) continue;
			loadimage(&img[(i-1)*10+j],_T("IMAGE"),lps[this->bk_m[i][j]]);//将方块数组元素对应的图片全部载入到IMAGE对象数组中,方便输出函数进行整体输出
		}
	}
}

//输出方块函数
//在初始化函数中已经将所有的图片全部载入到IAMGE对象数组中
//只需要判断一下方块数组元素值是否为-1(-1代表这个方块被敲开了,就不显示方块了)
//不是的话就正常输出未选中状态
void Block::showBlock()
{	
	for(int i=1;i<=10;i++)
		for(int j=1;j<=10;j++)
		{
			if(this->bk_m[i][j]==-1) continue;//判断方块数组元素值是否为-1
			putimage(40*(i-1),40*(j-1)+200,&img[(i-1)*10+j]);
		}
}

//void Block::moveChoice(MOUSEMSG m)
//{
//	IMAGE img;
//	LPCTSTR lps[16];
//	lps[1]="数字1.jpg";
//	lps[2]="数字2.jpg";
//	lps[3]="数字3.jpg";
//	lps[4]="数字4.jpg";
//	lps[5]="数字5.jpg";
//	lps[6]="数字6.jpg";
//	lps[7]="数字7.jpg";
//	lps[8]="数字8.jpg";
//	lps[9]="未选中.jpg";
//	lps[10]="选中.jpg";
//	lps[11]="空.jpg";
//	lps[12]="炸弹(未炸).jpg";
//	lps[13]="炸弹引爆.jpg";
//	lps[14]="小红旗.jpg";
//	if(m.x>=(m.x/40)*40&&m.x<=(m.x/40)*40+40&&m.y>=((m.y-200)/40)*40+200&&m.y<=((m.y-200)/40)*40+240)
//	{
//		loadimage(&img,lps[10]);
//		putimage((m.x/40)*40,((m.y-200)/40)*40+200,&img);
//	}
//}

//鼠标左击事件函数
//鼠标左击主要分为两大类:一个是空按钮,一个是小红旗按钮
//空按钮对应的背景分为三类:1、数字 2、炸弹 3、空 分别对这三种情况进行处理
void Block::leftClick(int x,int y,int b_m[][11],int &flag,int &b_x,int &b_y)
{
	if(this->bk_m[(x/40)+1][((y-200)/40)+1]!=14)//如果按钮是空按钮
	{
		if(b_m[(x/40)+1][((y-200)/40)+1]>=1&&b_m[(x/40)+1][((y-200)/40)+1]<=8)//当点击的为数字,为数字的话就仅显示数字这个方块
			this->bk_m[(x/40)+1][((y-200)/40)+1]=-1;
		else if(b_m[(x/40)+1][((y-200)/40)+1]==12)//当左击的是炸弹,让flag=1,提升游戏结束,并将所有的炸弹设置为引爆,输出背景
			{
				flag=1;
				b_x=(x/40)+1;
				b_y=((y-200)/40)+1;
				//设置背景的炸弹为引爆
				//输出背景
			}
		else//当点击的是空白,延伸出一片以数字为边界的空白区域(也就是将空白和数字形成的边界上方的方块去除掉)
		{
			TraceBack(b_m,(x/40)+1,((y-200)/40)+1);
		}
	}
	else//如果按钮是小红旗按钮
	{
		this->bk_m[(x/40)+1][((y-200)/40)+1]=9;
		loadimage(&img[(x/40)*10+((y-200)/40)+1],_T("IMAGE"),lps[this->bk_m[(x/40)+1][((y-200)/40)+1]]);
	}
	
}
//鼠标右键事件函数
//鼠标右键的事件目前只有一类:就用小红旗进行标记
//通过将鼠标的坐标信息进行与二维数组序号之间进行转换
//判断当前鼠标右击的方块,是否能进行标记(如果这个方块被左键消除了就不能进行标记了),能的话就进行标记。
void Block::rightCLick(int x,int y)
{
	if(bk_m[(x/40)+1][((y-200)/40)+1]!=-1)//将鼠标的坐标信息,转换为数组的序号(如果看不懂可以自己结合数据进行运算就知道了)
	{
		this->bk_m[(x/40)+1][((y-200)/40)+1]=14;
		loadimage(&img[(x/40)*10+((y-200)/40)+1],_T("IMAGE"),lps[this->bk_m[(x/40)+1][((y-200)/40)+1]]);
	}
}


//递归处理鼠标左键击中背景为空时候的处理函数
//当鼠标左键点击到背景为空的格子的时候,就要将以这个格子开始,以周围一圈数字为边界的
//方块全部敲开
//使用递归的算法,如果碰到数字,就将对应的数字上方的方块的数组元素值设置为-1(也就是将方块设置为敲开的状态)
//依次递归检测当前方块的:上方、左上方、左方、左下方、下方、右下方、右方、右上方
void Block::TraceBack(int b_m[][11],int i,int j)
{
	if(this->bk_m[i][j]!=-1)
		if(i>=1&&i<=10&&j<=10&&j>=1)
			if(b_m[i][j]>=1&&b_m[i][j]<=8)
			{
				this->bk_m[i][j]=-1;
			}else
			{
				this->bk_m[i][j]=-1;
				TraceBack(b_m,i,j-1);
				TraceBack(b_m,i-1,j-1);
				TraceBack(b_m,i-1,j);
				TraceBack(b_m,i-1,j+1);
				TraceBack(b_m,i,j+1);
				TraceBack(b_m,i+1,j+1);
				TraceBack(b_m,i+1,j);
				TraceBack(b_m,i+1,j-1);
			}
}

//判断游戏是否胜利函数
//游戏胜利,也就是除了炸弹上方的方块,其余的方块全部被敲开了
//也就是,其余方块的数组元素值全部为-1了,那么我们可以这么想:
//我们将炸弹上方的方块的数组元素值设置为1,然后只用判断整个
//方块数组元素值是否全部为-1,即可判断游戏是否通关。
void Block::isVoctory(int bomb_x[],int bomb_y[],int &flag)
{
	int temp[11][11];//设置一个临时二维数组,用来存放方块数组元素值
	for(int i=1;i<=10;i++)
		for(int j =1;j<=10;j++)
			temp[i][j]=this->bk_m[i][j];//数组值的复制
	for(int i=1;i<=10;i++)//将炸弹上方的方块数组元素值设为-1
	{
		temp[bomb_x[i]][bomb_y[i]]=-1;
	}
	int sum=0;
	for(int i=1;i<=10;i++)
		for(int j =1;j<=10;j++)
			if(temp[i][j]==-1)//判断此时的方块数组是否全为-1
				sum++;
	if(sum==100)//如果此时的方块数组全为-1,就代表游戏通关了,将全局游戏标志设置为2,代表游戏通关
		flag=2;

}

  2.1 Surface类

    头文件

#pragma once
#include<graphics.h>
//界面类
//用于输出界面框架、炸弹数目、重新游戏的按钮
class Surface
{
private:
	IMAGE img[7];//存储图片的对象数组
	LPCTSTR lps[7];//字符数组
public:
	Surface(void);
	~Surface(void);
	void showSurface();//输出界面函数
	void leftClick(int flag);//鼠标左键处理函数
	void set(int flag);//设置界面函数
};


    源文件

#include "Surface.h"


Surface::Surface(void)
{
	this->lps[1]="初始.jpg";
	this->lps[2]="初始(点击).jpg";
	this->lps[3]="成功.jpg";
	this->lps[4]="成功(点击).jpg";
	this->lps[5]="失败.jpg";
	this->lps[6]="失败(点击).jpg";
	for(int i=1;i<=6;i++)
		loadimage(&img[i],_T("IMAGE"),lps[i]);
}


Surface::~Surface(void)
{
}
//输出界面函数
void Surface::showSurface()
{
	putimage(0,0,&img[1]);
}
//鼠标左键处理函数
void Surface::leftClick(int flag)
{
	if(flag==1)
	{
		//哭脸变笑脸
		
		putimage(0,0,&img[1]);
	}
	else if(flag==2)
	{
		//酷脸变笑脸
		putimage(0,0,&img[1]);
	}
	else if(flag==3)
	{
		//笑脸变被选中
		putimage(0,0,&img[2]);
	}
	else if(flag ==4)
	{
		//笑脸选中变未选中
		putimage(0,0,&img[1]);
	}
}
//设置界面函数
void Surface::set(int flag)
{
	if(flag==1)
	{
		//哭脸
		putimage(0,0,&img[5]);
	}
	else if(flag==2)
	{
		//酷脸
		putimage(0,0,&img[3]);
	}
}

 3.问题解决

以下列举博主在案例中出现的问题,希望对大家有帮助:1、随机生成炸弹坐标时,出现炸弹重合 2、生成炸弹周围的数字 3、鼠标左键空白方块事件 4、将图片内嵌到exe文件中,实现一个exe文件就可以在别人的电脑上运行程序

  3.1 随机生成炸弹时,出现炸弹重合

    在此处随机产生炸弹时,我采用的是随机生成炸弹的行号和列号,这样就不可避免会产生相同的行号和列号(一开始我觉得这种可能比较小,想忽略这个问题,但是生成几次之后发现,产生重合的概率好大啊(;′⌒`) )。

    我采取的方法就是:1、先生成行号 2、在生成一个列号的时候,就对以这个行号和列号为维度的数组进行赋值,也就是让a[行号][列号]=12(a[][]这个数组初始化值全部为0)。在生成列号之前就判断生成的列号和当前的行号组合的数组元素值是否等于12,等于的话就说明在这个位置上已经生成炸弹了,就继续生成列号,直到行号和列号组合形成的元素值不是12。上代码:

for(int i=1;i<=10;i++)
		for(int j=1;j<=10;j++)
			this->b_m[i][j]=0;//首先对数组元素值进行初始化
	srand((int(time(0))));//设置随机数种子
	for(int i=1;i<=10;i++)
	{
		this->bomb_x[i] = (rand()%9)+1;//产生1-10之间的随机点的i
	}
	for(int i=1;i<=10;i++)
	{
		this->bomb_y[i] = (rand()%10)+1;//产生1-10之间的随机点的j
		while(this->b_m[this->bomb_x[i]][this->bomb_y[i]]==12)//为了产生不重合的10个炸弹(因为产生的随机数组合形成的点可能重合)
			this->bomb_y[i] = (rand()%10)+1;			  //原理:对已经产生的炸弹进行标记
		this->b_m[this->bomb_x[i]][this->bomb_y[i]]=12;//用炸弹图片对应的序号进行标记,一举两得,既方便后面设置图片,又能避免炸弹重合
		
	}	

  3.2 如何生成炸弹周围的数字

    生成炸弹周围的数字就很简单了,我们只需要依次将每个炸弹周围(以炸弹为中心的周围8个格子内)不是炸弹的数组元素值+1,那么最后数组中保留的值就是炸弹周围正确的数字。

    这步的关键是要注意炸弹周围还有可能生成炸弹这一种可能,有炸弹的话,就不管这个数组元素了,没有炸弹的地方,让数组元素值+1。上代码:

//生成炸弹旁边的数字,判断一个炸弹周围的8个数组元素是否为炸弹
	//如果不是的话,就让他的数组元素加1,是的话就不修改数组元素的值,
	//最后数组元素的值,就是炸弹周围的数字的值
	for(int i=1;i<=10;i++)
	{

			if(this->b_m[this->bomb_x[i]-1][this->bomb_y[i]-1]!=12) this->b_m[this->bomb_x[i]-1][this->bomb_y[i]-1]++;
			if(this->b_m[this->bomb_x[i]-1][this->bomb_y[i]]!=12) this->b_m[this->bomb_x[i]-1][this->bomb_y[i]]++;
			if(this->b_m[this->bomb_x[i]-1][this->bomb_y[i]+1]!=12) this->b_m[this->bomb_x[i]-1][this->bomb_y[i]+1]++;
			if(this->b_m[this->bomb_x[i]][this->bomb_y[i]-1]!=12) this->b_m[this->bomb_x[i]][this->bomb_y[i]-1]++;
			if(this->b_m[this->bomb_x[i]][this->bomb_y[i]+1]!=12) this->b_m[this->bomb_x[i]][this->bomb_y[i]+1]++;
			if(this->b_m[this->bomb_x[i]+1][this->bomb_y[i]-1]!=12) this->b_m[this->bomb_x[i]+1][this->bomb_y[i]-1]++;
			if(this->b_m[this->bomb_x[i]+1][this->bomb_y[i]]!=12) this->b_m[this->bomb_x[i]+1][this->bomb_y[i]]++;
			if(this->b_m[this->bomb_x[i]+1][this->bomb_y[i]+1]!=12) this->b_m[this->bomb_x[i]+1][this->bomb_y[i]+1]++;
	}

  3.3 鼠标左键空白方块事件

    在设计鼠标左键点击方块的时候,点击到数字上方的方块和空白上方的方块处理是不一样的。
    1、点击到数字上方的方块,就只敲开数字上方的方块即可
    2、点击到空白上方的方块,就要敲开他周围所有方块和数字形成的边界这么一个大的范围,举个例子:
在这里插入图片描述
    就会显示如下:
在这里插入图片描述
    那么这个功能是如何实现的呢?

    实现这个功能,我采用的方法是使用递归函数,按照:上方、左上方、左方、左下方、下方、右下方、右方、右上方这个顺序去遍历一个方块的四周,这样会有两种情况:1,遍历的方块为空白上方的方块,先敲开这个方块,然后继续从这个方块按顺序遍历 2、如果遍历的方块是数字上方的方块,就光敲开这个方块,函数结束。上代码:

//递归处理鼠标左键击中背景为空时候的处理函数
//当鼠标左键点击到背景为空的格子的时候,就要将以这个格子开始,以周围一圈数字为边界的
//方块全部敲开
//使用递归的算法,如果碰到数字,就将对应的数字上方的方块的数组元素值设置为-1(也就是将方块设置为敲开的状态)
//依次递归检测当前方块的:上方、左上方、左方、左下方、下方、右下方、右方、右上方
void Block::TraceBack(int b_m[][11],int i,int j)
{
	if(this->bk_m[i][j]!=-1)//判断方块是否被敲除,防止死循环
		if(i>=1&&i<=10&&j<=10&&j>=1)//判断数组是否越界
			if(b_m[i][j]>=1&&b_m[i][j]<=8)//判断是否数字边界
			{
				this->bk_m[i][j]=-1;
			}else
			{
				this->bk_m[i][j]=-1;
				TraceBack(b_m,i,j-1);
				TraceBack(b_m,i-1,j-1);
				TraceBack(b_m,i-1,j);
				TraceBack(b_m,i-1,j+1);
				TraceBack(b_m,i,j+1);
				TraceBack(b_m,i+1,j+1);
				TraceBack(b_m,i+1,j);
				TraceBack(b_m,i+1,j-1);
			}
}

  3.4 如何将图片内嵌到exe文件中,实现一个exe就可以运行程序

    这个问题的解决方法,是我的一个不使用easyx的朋友帮我找到的,正好也是我所在的easyx群 群主(慢羊羊)写的博客,属实惭愧(✿◡‿◡):博客地址

三、完整源码

如果大家对完整源码感兴趣的话,请在评论区留下邮箱,我会发送到大家的邮箱中的,希望大家多多点赞支持。

后话

  1. 首先给大家说一下,博主经常在线,如果有什么问题或者想法,可以在下方评论,我会积极反馈的。
  2. 其次还是要请大家能够多多指出问题,我也会在评论区等候大家!
    在这里插入图片描述 .

猜你喜欢

转载自blog.csdn.net/vangoudan/article/details/107389527