zoukankan      html  css  js  c++  java
  • C++复现经典游戏——扫雷

      国庆小长假,当大家都去看人山人海的时候,我独自一人狂码代码。这两天想要实现的内容是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。

      

    ——来自 熊猫 [http://www.cnblogs.com/xiongmao-cpp/]
  • 相关阅读:
    22、栈的应用-中缀表达式转后缀表达式
    21、栈的应用-就近匹配
    20、双向链表
    19、链式栈
    Eclipse 重新加载插件
    Asp.net web form 使用IOC(Unity) 构造函数注入Page,.net Framework 4.7.2
    asp.net webform 多语言
    sql server 生成数字辅助表
    查询指定数据库的慢语句
    2008 sql 揭秘 第4章的数据库脚本
  • 原文地址:https://www.cnblogs.com/xiongmao-cpp/p/4853344.html
Copyright © 2011-2022 走看看