C++ 走迷宮


     想了一個尋路算法,用C++實現了一下,界面用MFC完成的很簡單。用20x20的方形區域作為迷宮,為了方便,隨機選取了大約1/3的格子作為路障,禁止通過。規則是在只能想前后左右四個方向移動的前提下找到從入口(默認左上角)到出口(默認右下角)的最短路徑。

     源代碼下載:http://files.cnblogs.com/GhostZCH/MFCMaze.rar(如果你下載了,希望你能留下只言片語,哪怕是“+1”也好,謝謝)

     說來這個算法也不算難,借鑒了路由器建立路由表的算法,更加簡化一些。熟悉TCP/IP協議的筒子們一定會記得路由表建立的原來,這個算法也一樣,把每一個單元看成一個路由器,在它上下左右的四個格子可以看做與它聯通的四個路由器。每個單元與相鄰的單元交換路由信息,直到穩定下來,這樣就獲得了每個單元到出口的路由信息。所謂的路由信息並不是一條完整地路徑,只保存了到達出口的跳數(距離)和下一跳(下一步)的位置。這樣如果存在從入口到出口的路徑就可以找出來。如果在與相鄰單位交換信息時,只保存最短的路徑,就可以得到最短路徑,同時最短路選擇也避免了繞圈形成死循環的問題。

      界面很簡單,進入程序或者點擊建立迷宮時生成一個隨機迷宮,點擊尋找路徑后電腦會執行尋路算法,通過提示框提示尋路是否成功及迭代次數,如果成功顯示路徑和每個格子到出口的距離。黑色為障礙,灰色為可通過區域,綠色為電腦找到的路徑,數字標明該格子到出口(右下角)的最短距離,沒有數字的灰色格子說明這個格子與出口不連通。如上圖中的左下區域。雖然結果只顯示了從左上到右下的最短路徑,事實上算法已經計算出每個格子(與出口聯通的)到達出口的最短路徑和距離。

下面的兩組圖片是生成的迷宮和找到的路徑,運行時間沒有計算,人工觀測都小於1秒。有興趣的筒子可以驗證一下是不是最短的路徑。

尋路的核心代碼如下:

    數據用的是“vector<Block *> _blocks”按照行優先的格式存下來的,在之前生成迷宮的時候就已經控制了入口和出口不是障礙,所以一開始先把出口的位置數據初始化了一下,剩下的就是迭代了。括號有十層,確實有點暈了,事實上不建議這樣寫代碼的,超過五層括號就讓人很迷惑了。但是考慮到程序本身比較小,既是不拆分函數也只有50行,不算變態(有一次需要讀懂一個700行的函數,淚奔啊!!),循環體內部的邏輯也比較簡單,沒有太復雜的,所以就一個函數搞定,當然還是不建議大家這么做的。

 1 int Grid::InitMap()
 2 {
 3     Block* target = _blocks.at(_height*_width-1);
 4     target->CanReach(true);
 5     target->JumpCount(0);
 6 
 7     int times = 0;
 8     bool ischanged = true;
 9     //迭代到收斂,每個格子有最短個路徑的長度和下一跳地址
10     while(ischanged)
11     {
12         times ++;
13         ischanged = false;
14 
15         // 逐格聞訊周圍格子路徑
16         for (int i=0;i<_height;i++)
17         {
18             for (int j =0;j<_width;j++)
19             { 
20                 //問詢鄰居,選擇最短的路徑更新自己的路由信息
21                 Block* block = Get(i,j);
22                 if (block->CanPass())
23                 {
24                     for (int ii=-1;ii<2;ii++)//-1到1
25                     {
26                         for (int jj=-1;jj<2;jj++)//-1到1
27                         {
28                             if(abs(ii)+abs(jj)==1)//只選四鄰域
29                             {
30                                 int x = i+ii;
31                                 int y = j+jj;
32                                 if (x>=0&&y>=0&&x<_height&&y<_width)//處於格子中的鄰域
33                                 {
34                                     // 鄰接格子中比自己路徑短的更新自己的路徑
35                                     Block *tmp = Get(x,y);//某個鄰接的格子
36                                     if (tmp->CanReach()&&(tmp->JumpCount()+1)<block->JumpCount())
37                                     {
38                                         block->CanReach(true);//設置可到達
39                                         block->JumpCount(tmp->JumpCount()+1);//設置跳數為鄰近格子的跳數+1
40                                         block->NextJump(x*_width+y);//下一跳地址是鄰接的格子
41                                         ischanged = true;
42                                     }
43                                 }//end if
44                             }//end if 
45                         }//end for jj
46                     }//end for ii
47                 }//end if
48             }//end for j
49         }//end for i
50     }// end while
51     return times;
52 }

 

順便多貼幾張結果圖,當然也有尋路失敗的:

 


免責聲明!

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



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