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。

  

 

打賞

免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號  © 2018-2021 CODEPRJ.COM