前言
提示:本文是基于easyX图形库实现的,还有部分功能可以添加,仅适合新手参考。
一、扫雷游戏模式
在确定大小的矩形雷区中随机布置一定数量的地雷,玩家需要尽快找出雷区中的所有不是地雷的方块,而不许踩到地雷。
游戏的基本操作包括左键单击和右键单击。其中左键用于打开安全的格子,推进游戏进度;右键用于标记地雷,以辅助判断。
左键单击:在判断出不是雷的方块上按下左键,可以打开该方块。如果方块上出现数字,则该数字表示其周围3×3区域中的地雷数(一般为8个格子,对于边块为5个格子,对于角块为3个格子。所以扫雷中最大的数字为8);如果方块上为空(相当于0),则可以递归地打开与空相邻的方块;如果不幸触雷,则游戏结束。
右键单击:在判断为地雷的方块上按下右键,可以标记地雷(显示为小红旗)。重复一次或两次操作可取消标记。
二、代码实现
1.绘制地图场景
根据每一块地区的数据进行图形输出。
代码如下(示例):
1 void drawmap(int map[][12],IMAGE *img)
2 {
3 int i, j;
4 for (i = 1; i <= 10; i++)
5 {
6 for (j = 0; j <= 10; j++)
7 {
8 int x = 50 * (i - 1);//得到位置
9 int y = 50 * (j - 1);
10 if (map[i][j]>25)
11 {
12 putimage(x, y, &img[9]);//标记flag
13 }
14 else
15 {
16 switch (map[i][j])
17 {
18 case 9:
19 putimage(x, y, &img[11]);//输出图片雷
20 break;
21 case 10:
22 putimage(x, y, &img[0]);//0
23 break;
24 case 11:
25 putimage(x, y, &img[1]);//1
26 break;
27 case 12:
28 putimage(x, y, &img[2]);//2
29 break;
30 case 13:
31 putimage(x, y, &img[3]);//3
32 break;
33 case 14:
34 putimage(x, y, &img[4]);//4
35 break;
36 case 15:
37 putimage(x, y, &img[5]);//5
38 break;
39 case 16:
40 putimage(x, y, &img[6]);//6
41 break;
42 case 17:
43 putimage(x, y, &img[7]);//7
44 break;
45 case 18:
46 putimage(x, y, &img[8]);//8
47 break;
48 default:
49 putimage(x, y, &img[10]);//地图
50 break;
51 }
52 }
53 }
54 }
55 }
2.鼠标点击
鼠标左键点击翻开格子,右键点击标记flag,再次点击可以进行取消。
sum记录翻开格子的数量,点击后对每个位置的数据进行加减操作。
代码如下(示例):
1 int mousedown(int map[][12])
2 {
3 MOUSEMSG m; //定义鼠标消息变量
4 while (1)
5 {
6 //获取鼠标消息
7 m = GetMouseMsg();
8 int mi = m.x / 50 + 1;
9 int mj = m.y / 50 + 1;
10
11 //判断鼠标消息
12 switch (m.uMsg)
13 {
14 case WM_LBUTTONDOWN:
15 if (map[mi][mj] > 9) //已翻开的情况
16 {
17 continue;
18 }
19 if (map[mi][mj] == 0) //如果点击为0,则翻开一片。
20 {
21 //使用递归函数
22 swap(map, mi, mj);
23 }
24 else
25 {
26 map[mi][mj] += 10;
27 sum += 1;
28 }
29 return map[mi][mj];
30 break;
31 case WM_RBUTTONDOWN:
32 if (map[mi][mj] > 9&& map[mi][mj] < 25) //已翻开的情况
33 {
34 continue;
35 }
36 if (map[mi][mj] > 25) //再次点击取消flag
37 {
38 map[mi][mj] -= 30;
39 }
40 else
41 {
42 map[mi][mj] += 30;
43 }
44 return map[mi][mj];
45 break;
46 }
47 }
48 }
3.递归
当我们点到为0的地区时,将会打开周围的部分地区,外围为非0数或到达边界,内部为0.
如图:
代码如下(示例):
1 void swap(int map[][12],int mi,int mj)
2 {
3 map[mi][mj] = 10;
4 sum += 1;
5 for (int i = mi - 1; i <= mi + 1; i++)
6 {
7 for (int j = mj - 1; j <= mj + 1; j++)
8 {
9 //数组下标不能越界
10 if (i >= 1 && i <= 10 && j >= 1 && j <= 10)
11 {
12 //翻开的只能是数字
13 if (map[i][j] < 9)
14 {
15 //如果为0,则进行递归。
16 if (map[i][j] == 0)
17 {
18 swap(map, i, j);
19 }
20 else
21 {
22 map[i][j] += 10;
23 sum += 1;
24 }
25 }
26 }
27 }
28 }
29 }
4.初始化游戏
代码如下(示例):
1 void startgame()
2 {
3 initgraph(500, 500); //初始化地图500x500
4 int map[12][12] = { 0 };
5 int i,j,m,n;
6 //随机函数种子
7 srand((unsigned int)time(NULL));
8 //随机生成10个雷
9 for (n = 0; n < 10;)
10 {
11 i = rand() % 10 + 1; //[1,10]
12 j = rand() % 10 + 1;
13 if (map[i][j] == 0) //排除本来就有雷的情况
14 {
15 map[i][j] = -1; //-1表示有雷
16 n++;
17 }
18 }
19 //产生数字
20 for (i = 1; i <= 10; i++)
21 {
22 for (j = 1; j <= 10; j++)
23 {
24 //排除是雷的情况
25 if (map[i][j] != -1)
26 {
27 for (m = i - 1; m <= i + 1; m++) //判断周围是否有雷
28 {
29 for (n = j - 1; n <= j + 1; n++)
30 {
31 if (map[m][n] == -1)
32 {
33 map[i][j]++;
34 }
35 }
36 }
37 }
38 }
39 }
40 IMAGE img[12]; //定义图片变量
41 loadimage(&img[0], "E:\\C++ project\\minesweeping\\0.jpg", 50, 50);
42 loadimage(&img[1], "E:\\C++ project\\minesweeping\\1.gif", 50, 50);//加载图片
43 loadimage(&img[2], "E:\\C++ project\\minesweeping\\2.gif", 50, 50);
44 loadimage(&img[3], "E:\\C++ project\\minesweeping\\3.gif", 50, 50);
45 loadimage(&img[4], "E:\\C++ project\\minesweeping\\4.gif", 50, 50);
46 loadimage(&img[5], "E:\\C++ project\\minesweeping\\5.gif", 50, 50);
47 loadimage(&img[6], "E:\\C++ project\\minesweeping\\6.gif", 50, 50);
48 loadimage(&img[7], "E:\\C++ project\\minesweeping\\7.gif", 50, 50);
49 loadimage(&img[8], "E:\\C++ project\\minesweeping\\8.gif", 50, 50);
50 loadimage(&img[9], "E:\\C++ project\\minesweeping\\flag.gif", 50, 50);
51 loadimage(&img[10], "E:\\C++ project\\minesweeping\\地图.gif", 50, 50);
52 loadimage(&img[11], "E:\\C++ project\\minesweeping\\雷.gif", 50, 50);
53 while (1)
54 {
55 drawmap(map, img);
56 //点到地雷
57 if (mousedown(map)==9)
58 {
59 sum = 0; //重置判断变量
60 drawmap(map, img);
61 MessageBox(hwnd,"你踩到雷了!","Game Over",MB_OK);
62 return;
63 }
64 //成功完成游戏
65 if (sum == 90)
66 {
67 sum = 0; //重置判断变量
68 drawmap(map, img);
69 MessageBox(hwnd, "你成功完成了游戏!", "Game Over", MB_OK);
70 return;
71 }
72 }
73 }
5.main
代码如下(示例):
1 #include<iostream>
2 #include<time.h>
3 #include<graphics.h> //图形库头文件 easyx
4 #include <conio.h> //调用_getch函数
5 using namespace std;
6 HWND hwnd;
7 int sum = 0;//用于表示目前已经点开的格子数
8 //声明函数
9 void drawmap(int map[][12], IMAGE* img);
10 int mousedown(int map[][12]);
11 void swap(int map[][12], int mi, int mj);
12 //初始化游戏
13
14 //绘制地图
15
16 //鼠标点击
17
18 //递归函数
19
20 int main()
21 {
22 while (1)
23 {
24 startgame();
25 if (MessageBox(hwnd, "再来一次", "结束游戏", MB_YESNO)==IDNO)
26 break;
27 }
28 //_getch(); //防止闪屏
29 closegraph();
30 return 0;
31 }