C++复现经典游戏?扫雷
作者:网络转载 发布时间:[ 2015/10/12 11:29:33 ] 推荐标签:测试开发技术 .NET
国庆小长假,当大家都去看人山人海的时候,我独自一人狂码代码。这两天想要实现的内容是Windows上的一个经典游戏——扫雷。相信90后和一些上班族对此并不陌生。然而,从win8开始,扫雷不再是Windows上的默认自带游戏了,但是可以通过微软的应用商店进行下载安装(界面更酷炫,游戏模式更丰富)。目前在win10上也暂时没有找到这款游戏。
这两天再次用Qt基本图形界面框架,来实现扫雷游戏的功能。本想做得酷炫酷炫再酷炫的,但是真正动手写起来的时候,才发现还是有很多技术关没有通过,因此界面写得丑了。这次扫雷程序实现了基本的游戏功能,包含随机布雷、空白块自动扩展、输赢判断等。
程序界面如下:
游戏界面
整个扫雷游戏,主要的一部分是当点击到空白块的时候,如何扩展开来。我在写程序前,也上网查了扫雷相关的东西,发现扫雷程序已经被写烂了,很多人都复现过,毕业设计、课程设计等等。说起来,扫雷程序确实适合用来练手,整个程序功能并不是特别的复杂。
下面说说我认为的点到空白块的自动扩展算法。
(1)点击到空白块
(2)计算该空白块周围一圈雷的个数。若为零,翻开该块并跳至(3)。若不为零,则翻开并显示雷的个数,跳至(4)。
(3)对周围八个块,重复第二步。
(4)结束
以上四步便是空白块自动扩展算法,是不是很简单。但是我刚开始的时候这个东西还是想了很长一段时间。当写程序实现该算法的时候,有一点需要注意的地方,是翻开的块需要做个标记。对于第三步中,已经翻开的块不需要再执行第(2)步,不然可能进入死循环。此外,该算法可以使用递归实现或非递归实现。
下面是我的具体实现代码:
1 /*
2 *统计(x,y)周围一圈雷的个数
3 */
4 int MainWindow::sumMine(int x, int y)
5 {
6 int mineNum=0;
7 if(x-1>=0&&y-1>=0&&map[x-1][y-1]==1) mineNum++;
8 if(x-1>=0&&map[x-1][y]==1) mineNum++;
9 if(x-1>=0&&y+1<mapCols&&map[x-1][y+1]==1) mineNum++;
10 if(y-1>=0&&map[x][y-1]==1) mineNum++;
11 if(y+1<mapCols&&map[x][y+1]==1) mineNum++;
12 if(x+1<mapRows&&y-1>=0&&map[x+1][y-1]==1) mineNum++;
13 if(x+1<mapRows&&map[x+1][y]==1) mineNum++;
14 if(x+1<mapRows&&y+1<mapCols&&map[x+1][y+1]==1) mineNum++;
15 return mineNum;
16
17 }
18
19 /*
20 *从(x,y)开始进行扩展
21 */
22 void MainWindow::expendBlock(int x, int y)
23 {
24 int mineAround=sumMine(x,y);
25 if(mineAround!=0){
26 //在(x,y)显示雷的个数,然后结束递归
27 QTableWidgetItem * temp=new QTableWidgetItem;
28 temp->setText(QString::number(mineAround,10));
29 temp->setTextAlignment(Qt::AlignCenter);
30 temp->setBackgroundColor(QColor(251,246,246));
31 mapUI->setItem(x,y,temp);
32 mapFlag[x][y]=1;
33 return ;
34 }
35 //翻开(x,y),并从周围八个方向递归,要判断越界
36
37 list<POINT> expendList;
38 POINT point;
39 point.x=x;
40 point.y=y;
41 expendList.push_back(point);
42 while (!expendList.empty()) {
43 point=expendList.front();
44 expendList.pop_front();
45 x=point.x;
46 y=point.y;
47 mineAround=sumMine(x,y);
48 if(mineAround!=0){
49 QTableWidgetItem * temp=new QTableWidgetItem;
50 temp->setText(QString::number(mineAround,10));
51 temp->setTextAlignment(Qt::AlignCenter);
52 temp->setBackgroundColor(QColor(251,246,246));
53 mapUI->setItem(x,y,temp);
54 mapFlag[x][y]=1;
55 continue;
56 }
57 QTableWidgetItem * temp1=new QTableWidgetItem;
58 temp1->setBackgroundColor(QColor(251,246,246));
59 temp1->setTextAlignment(Qt::AlignCenter);
60 mapUI->setItem(x,y,temp1);
61 mapFlag[x][y]=1;
62 if(x-1>=0&&y-1>=0&&mapFlag[x-1][y-1]==0){
63 point.x=x-1;
64 point.y=y-1;
65
66 expendList.push_back(point);
67 }
68 if(x-1>=0&&mapFlag[x-1][y]==0){
69 point.x=x-1;
70 point.y=y;
71
72 expendList.push_back(point);
73 }
74 if(x-1>=0&&y+1<mapCols&&mapFlag[x-1][y+1]==0){
75 point.x=x-1;
76 point.y=y+1;
77
78 expendList.push_back(point);
79 }
80 if(y-1>=0&&mapFlag[x][y-1]==0){
81 point.x=x;
82 point.y=y-1;
83
84 expendList.push_back(point);
85 }
86 if(y+1<mapCols&&mapFlag[x][y+1]==0){
87 point.x=x;
88 point.y=y+1;
89
90 expendList.push_back(point);
91 }
92 if(x+1<mapRows&&y-1>=0&&mapFlag[x+1][y-1]==0){
93 point.x=x+1;
94 point.y=y-1;
95
96 expendList.push_back(point);
97 }
98 if(x+1<mapRows&&mapFlag[x+1][y]==0){
99 point.x=x+1;
100 point.y=y;
101
102 expendList.push_back(point);
103 }
104 if(x+1<mapRows&&y+1<mapCols&&mapFlag[x+1][y+1]==0){
105 point.x=x+1;
106 point.y=y+1;
107 expendList.push_back(point);
108 }
109 }
110
111 }
其中map[][]保存着地图信息。mapFlag[][]是地图标志,当该块已经翻开是设置为1,否则为0。
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11