【CSDN转载】C/C++游戏项目详细教学:《扫雷》

扫雷最原始的版本可以追溯到1973年一款名为“方块”的游戏。

不久,“方块”被改写成了游戏“Rlogic”。在“Rlogic”里,玩家的任务是作为美国海军陆战队队员,为指挥中心探出一条没有地雷的安全路线,如果路全被地雷堵死就算输。两年后,汤姆·安德森在“Rlogic”的基础上又编写出了游戏“地雷”,由此奠定了现代扫雷游戏的雏形。

1981年,微软公司的罗伯特·杜尔和卡特·约翰逊两位工程师在Windows3.1系统上加载了该游戏,扫雷游戏才正式在全世界推广开来。

这款游戏的玩法是在一个9*9(初级),16*16(中级),16*30(高级),或自定义大小的方块矩阵中随机布置一定量的地雷(初级为10个,中级为40个,高级为99个)。由玩家逐个翻开方块,以找出所有地雷为最终游戏目标。如果玩家翻开的方块有地雷,则游戏结束。

我们今天就来自己写《扫雷》

这个项目并不是很难,今天就和大家从头到尾详细的讲一遍,大家一定要好好看好好学!

行吧,开始了

我们今天用的是Cpp来写,但不是用Windows来创建窗口,而是用他的远房表亲EasyX图形库来创建窗口,因为用图形库会简单很多,刚学C的也可以听懂,而且C/C++不分家,没有什么问题,OK,我们现在开始写代码,今天我就把头文件也分享出来了,主要是教大家如何去调用图形库。(注:没有EasyX图形库的可以去官网下载,也可以进群直接下载)

首先是我们的头文件以及一些宏定义

`

1.  #include<stdio.h>
    
2.  #include<graphics.h>//包含图形库头文件
    
3.  #define ROW 9 //行
    
4.  #define COL 9 //列  共81个格子
    
5.  #define MINE_NUM  18//雷的数量
    
6.  #define IMG_SIZE 40
    

`


初始化函数,也是我们的老朋友了

`

1.  void GameInit()
    
2.  {
    
3.  	//1,创建窗口 一行有九张图片每张图片40px,
    
4.  	initgraph(IMG_SIZE*ROW, IMG_SIZE*COL,SHOWCONSOLE);
    
5.  	//加载图片(赋值) load加载 第一个参数,存储图片的变量 错误:字符集问题
    
6.  	for (int i = 0; i < 12; i++)
    
7.  	{
    
8.  		char file[20] = "";
    
9.  		sprintf(file, "./image/%d.jpg", i);
    
10.  		loadimage(&img[i], file, IMG_SIZE, IMG_SIZE);
    
11.  	}
    
12.  	//布雷
    
13.  	for (int i = 0; i < MINE_NUM; )
    
14.  	{
    
15.  		//排除辅助区
    
16.  		int row = rand() % ROW+1;//0-8  1-9
    
17.  		int col = rand() % COL+1;
    
18.  		if (mine[row][col] == 0)
    
19.  		{
    
20.  			mine[row][col] = 9;
    
21.  			i++;
    
22.  		}
    
23.  	}
    
24.  	//雷所在的九宫格,要加1(雷除外)
    
25.  	for (int i = 1; i < ROW+1; i++)
    
26.  	{
    
27.  		for (int k = 1; k < COL+1; k++)
    
28.  		{
    
29.  			if (mine[i][k] == 9)
    
30.  			{
    
31.  				//遍历雷的九宫格 细心
    
32.  				for (int a = i - 1; a <= i + 1; a++)
    
33.  				{
    
34.  					for (int b = k - 1; b <= k + 1; b++)
    
35.  					{
    
36.  						//非雷的格子加1
    
37.  						if (mine[a][b] != 9)
    
38.  						{
    
39.  							mine[a][b]++;
    
40.  						}
    
41.  					}
    
42.  				}
    
43.  			}
    
44.  		}
    
45.  	}
    
46.  	//加密 开始时全部为掩码图
    
47.  	for (int i = 1; i < ROW + 1; i++)
    
48.  	{
    
49.  		for (int k = 1; k < COL + 1; k++)
    
50.  		{
    
51.  			mine[i][k] += 20;
    
52.  		}
    
53.  	}
    

55.  }
    

`


鼠标信息处理函数

`

1.  void MouseEvent()
    
2.  {
    
3.  	//检测是否有鼠标消息
    
4.  	if (MouseHit())
    
5.  	{
    
6.  		//获取鼠标消息,坐标,左键还是右键
    
7.  		MOUSEMSG msg = GetMouseMsg();
    
8.  		//把坐标转化成数组下标
    
9.  		openr = msg.y / IMG_SIZE+1;
    
10.  		openc = msg.x / IMG_SIZE+1;
    
11.  		//判断是左键还是右键
    
12.  		switch (msg.uMsg)
    
13.  		{
    
14.  		case WM_LBUTTONDOWN:
    
15.  			//如果格子没有打开,就打开格子,否则不做处理
    
16.  			if (mine[openr][openc] > 9)
    
17.  			{
    
18.  				mine[openr][openc] -= 20;
    
19.  				OpenNull(openr,openc);
    
20.  				num++;
    
21.  			}
    
22.  			break;
    
23.  		case WM_RBUTTONDOWN:
    
24.  			//标记
    
25.  			if (mine[openr][openc] > 9 && mine[openr][openc] <= 29)
    
26.  			{
    
27.  				mine[openr][openc] += 20;
    
28.  			}
    
29.  			else
    
30.  			{
    
31.  				mine[openr][openc] -= 20;
    
32.  			}
    
33.  			break;
    
34.  		}
    
35.  	}
    
36.  }
    

`

![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)


进行递归操作,判断鼠标点击的地方

`

1.  //递归打开所有空白,以及空白周围的数字
    
2.  void OpenNull(int row,int col)
    
3.  {
    
4.  	//点击的是空白才能打开
    
5.  	if (mine[row][col] == 0)
    
6.  	{
    
7.  		for (int i = row - 1; i <= row + 1; i++)
    
8.  		{
    
9.  			for (size_t k = col-1; k <= col+1; k++)
    
10.  			{
    
11.  				//如果为空或者不是雷就打开
    
12.  				if ((mine[i][k] == 20 || mine[i][k] != 29)&& mine[i][k]>9)
    
13.  				{
    
14.  					mine[i][k] -= 20;
    
15.  					num++;
    
16.  					OpenNull(i, k);
    
17.  				}
    
18.  			}
    
19.  		}
    
20.  	}
    
21.  }
    

`

![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)


游戏的输赢判断函数,注意理清逻辑

`

1.  void Jude()
    
2.  {
    
3.  	//判断输
    
4.  	if (mine[openr][openc] == 9)
    
5.  	{
    
6.  		int isok = MessageBox(GetHWnd(), "是否继续!", "点到雷了", MB_OKCANCEL);
    
7.  		if (isok == IDOK)
    
8.  		{
    
9.  			mine[openr][openc] += 20;
    
10.  		}
    
11.  		else
    
12.  		{
    
13.  			exit(666);
    
14.  		}
    
15.  	}
    
16.  	//判断赢
    
17.  	if (num == ROW*COL - MINE_NUM)
    
18.  	{
    
19.  		int isok = MessageBox(GetHWnd(), "是否继续!", "点到雷了", MB_OKCANCEL);
    
20.  		if (isok == IDOK)
    
21.  		{
    
22.  			num = 0;
    
23.  			GameInit();
    
24.  		}
    
25.  		else
    
26.  		{
    
27.  			exit(666);
    
28.  		}
    
29.  	}
    
30.  }
    

`


最后就是我们的主函数了

`

1.  int main()
    
2.  {
    
3.  	GameInit();
    
4.  	show();
    
5.  	//循环处理游戏逻辑
    
6.  	while (1)
    
7.  	{
    
8.  		MouseEvent();
    
9.  		GameDraw();
    
10.  		Jude();
    
11.  	}
    

13.  	getchar();
    
14.  	return 0;
    
15.  }
    

`


经典游戏《扫雷》完成,OK,简单总结一下,代码很简单,逻辑也不难,重要是大家一定要自己动手去做,这是毋庸置疑的,编程没有捷径,只有不断的学习熟练,加强自己的能力,有条件的话找个老师的话效果会更好,我也特意找了一个朋友叫他把一些关于《扫雷》的教学视频发给我,大家可以去我的主页上查看,我也希望下面的视频可以更好的帮助同学们掌握这个项目,好了,希望大家可以在这里得到自己想要的知识以及快乐吧,也希望大家可以给UP主一个关注,非常感谢大家了!!!

后续UP主还会发布更多的项目源码以及学习资料,希望大家可以持续关注,有什么问题可以回帖留言,我尽量回答。想要C/C++学习资料以及其他项目的源码的可以加群【765860056】了解。

点击下方链接观看详细视频讲解

【C/C++游戏开发系列教程】开发windows自带经典游戏“扫雷”!

原文链接: C/C++游戏项目详细教学:《扫雷》_扫雷c+±CSDN博客