计算机软件实习项目三 —— 超级玛丽闯迷宫 (实验准备) 12-19(12-21更新)
實驗準備(超級瑪麗闖迷宮)
??經過了前面兩個項目的實踐,我對python和pyqt5已經有了一定的了解,除了能夠把實驗要求全部完成,還加入了自己的一些想法在游戲里,讓游戲更加有趣。
??第三個項目主要的需求是能隨機生成一個迷宮,并且能夠自動尋路來破解迷宮。迷宮的隨機生成主要采用Prim算法來生成迷宮,一方面是因為Prim算法生成的迷宮比較自然,另一方面是之前了解過Kurskal最小生成樹的思想,二者有共通性,故選用此算法。自動尋路則使用實驗要求里的A*算法來實現,它相比廣度優先搜索的效率更高,因為它有啟發函數,能夠在邊權為1的圖里面提供額外的啟發信息,能夠更快的收斂,搜索到目標結點。
目錄
- 實驗準備(超級瑪麗闖迷宮)
- 一、迷宮定義(Map類)
- 1. 成員變量
- 2. 成員方法
- 二、隨機生成迷宮(Prim算法)
- 1. 最小生成樹
- 2. Prim算法流程
- 3. prim算法和迷宮生成的關系
- 4. prim算法生成迷宮流程
- 三、迷宮自動尋路(A*算法)
- 1. 算法簡介
- 2. 路徑選擇
- 3. 定義結點
- 4. 子方法
- 5. 算法流程
- 四、游戲界面(PyQt5)
- 1. 成員變量
- 2. 構造函數
- 3. 子方法
一、迷宮定義(Map類)
??要實現隨機生成迷宮第一步當然是定義迷宮,定義迷宮的大小以及對迷宮進行獲取、設置、重置、判斷、打印等操作的方法。
1. 成員變量
(1)width,height:定義迷宮的行數和列數。
(2)map:二維列表用來存放迷宮地圖,坐標定義與數組索引相似,x為縱向,y為橫向(與一般坐標系不同)。
二維列表中每一個元素的值代表不同的含義,分別如下:
① map[i][j] == 0:當前格為空格。
② map[i][j] == 1:當前格為墻壁。
③ map[i][j] == 2:當前格為起點。
④ map[i][j] == 3:當前格為終點。
⑤ map[i][j] == 4:當前格為自動尋路路徑上的結點。
2. 成員方法
(1)getMap(self):返回當前對象的map[n][m]二位迷宮列表。
(2)resetNode(self, value):設置map[n][m]二位迷宮列表的每一個元素為value值。
(3)setNode(self, x, y, value):設置map[x][y] = value。
(4)isWall(self, x, y):判斷map[x][y] = 1 ?也就是判斷是否是墻壁。
(5)showMap(self):打印map[n][m]整個迷宮。
二、隨機生成迷宮(Prim算法)
??定義了迷宮后我們來實現Prim算法,用它來實現迷宮的隨機生成,Prim算法可在加權連通圖里搜索最小生成樹,那么首先我們來了解什么是最小生成樹。
1. 最小生成樹
??百度百科給出的定義是:一個有 n 個結點的連通圖的生成樹是原圖的極小連通子圖,且包含原圖中的所有 n 個結點,并且有保持圖連通的最少的邊。
??我的理解是:在一個帶權圖中,有n個結點,用n-1條邊使得這n個點相互之間可達,這也就是生成樹,所謂最小即為這n-1條邊的權值之和是最小的。所以最小生成樹其實就是在n個頂點的圖中選n-1條邊使得這個圖為聯通圖(強連通圖)并且這n-1條邊的權值之和最小。
??如下是我用3D畫圖畫的無向賦權圖
無向賦權圖它的生成樹:
生成樹1,邊權之和 = 13 生成樹2,邊權之和 = 13 即使生成樹不同,邊權可以相同。最小生成樹:
生成樹2,邊權之和 = 8 最小生成樹的邊權之和最小且為聯通圖。2. Prim算法流程
(1) 輸入:一個加權連通圖,其中頂點集合為V,邊集合為E;
(2) 初始化:Vnew = {x},其中x為集合V中的任一節點(起始點),Enew = {},為空;
(3) 重復下列操作,直到Vnew = V:
??① 在集合E中選取權值最小的邊<u, v>,其中u為集合Vnew中的元素,而v不在Vnew集合當中,并且v∈V(如果存在有多條滿足前述條件即具有相同權值的邊,則可任意選取其中之一);
??②將v加入集合Vnew中,將<u, v>邊加入集合Enew中;
(4) 輸出:使用集合Vnew和Enew來描述所得到的最小生成樹。
3. prim算法和迷宮生成的關系
??假設迷宮為7×7的正方形,9個白格子為初始空結點,黑色格子為墻壁。
??接著我們把整個迷宮看成一張無向圖,白色的格子看成結點,部分黑格子看成邊,如下圖: 圖中1~9標號代表結點,紅色的線代表邊。?? 接下來用Prim算法即可生成這個圖的一個最小生成樹,這個最小生成樹就是迷宮的連通的部分,也就是玩家可以走的部分。并且因為每一個邊權都是1,所以只要邊權之和一定是n-1也就是 9-1 = 8 。
圖中1~9標號代表結點,紅色的線代表邊。?? 最后生成如上圖,也就是我們所需要的迷宮,途中一共有8條邊,邊權之和也就是 8*1 = 8。
4. prim算法生成迷宮流程
預處理部分:
(1)定義一個檢查列表checklist存放為劃分頂點集。
(2)把初始起點加入checklist列表中。
主循環部分:
(3)重復下面幾個步驟直到檢查列表checklist為空:
??① 隨機取出checklist列表中的一個結點node1。
??② 檢查這個結點node1周圍有沒有墻wall。
????③ 有墻:從這個結點node1周圍的墻中隨機選一個,假設是wall_left,把這個墻置為空;并且把這個墻與node1之間的結點也置為空;最后把這個墻的位置坐標加入checklist中。
????④ 無墻:把node1從checklist中刪除。
(4)通過上述步驟后,迷宮即可隨機生成。
三、迷宮自動尋路(A*算法)
1. 算法簡介
?? A* 算法是一種靜態路網中求解最短路徑最有效的直接搜索方法,我認為A*算法與BFS廣度優先搜索算法有很多相似之處,不過它相比廣度優先搜索的效率更高,因為它有啟發函數,能夠在邊權為1的圖里面提供額外的啟發信息,能夠更快的收斂,搜索到目標結點。
2. 路徑選擇
?? 那么我們如何在若干條路徑中選出最優的一條呢?
這就需要定義路徑代價:F
它衡量了當前路徑的優劣程度,對是否繼續采用改路徑具有決定作用。
同時它滿足下列等式:
?? ?? ?? ?? ?? ?F = G + H
G是移動代價,即從起點沿當前路徑到當前結點的路徑的長度。
H是估算代價,我們這里使用曼哈頓距離,即當前結點到目標結點的最短路徑長度(忽略地形)。
3. 定義結點
??為什么要定義結點:因為最后輸出路徑的時候需要從最后一個目標結點不斷訪問父節點來進行路徑追溯,最后才能輸出從源節點到目標結點的一條完整路徑。
主要變量有:
- x、y坐標
- 沿當前路徑到map[x][y]的路徑長度(G值)
- 當前路徑的F值(F = G + H)
- 父節點(用于路徑回溯)
4. 子方法
(1)pathEvaluate(val, fx, fy, ex, ey) :
??計算當前路徑代價(F = G + H)。
(2)findMin(open) :
??返回open表中代價最小的結點。
(3)find_node(node, list):
??判斷某個結點在不在某個表中。
(4)AStar(map, row, col, sx, sy, ex, ey)方法:
??完成A* 算法的主邏輯,執行過程中調用前面三個子方法。
5. 算法流程
定義與預處理部分:
(1)定義一個open開放列表,這里面的結點可能更新可能移除。
(2)定義一個close封閉列表 ,這里面的結點不需要處理。
(3)往open表中加入起點。
主循環部分:
(4)重復下面幾個步驟直到檢查列表checklist為空:
??① 找到open表中代價最小的結點,把它從open表中取出并放入close表中。
??② 判斷這個結點是否是目標結點
??????③ 是:通過這個結點不斷回溯到源節點生成一條路徑,返回這個路徑并退出整個AStar函數。
??????④ 否:往相鄰結點nx拓展搜索。
??????????⑤ 如果相鄰結點nx:1.在close表里。2.是墻壁。3. 超出地圖邊界。就跳過這個相鄰結點nx,直到這個結點的4個相鄰結(n1、n2、n3、n4)點都判斷過。
??????????⑥ 如果相鄰結點nx在open表中(注意只要 (x,y) 坐標相同就算相同),比較相鄰結點nx和open表中結點的G移動代價,如果相鄰結點n的G值比open表中相同結點的G值小,則更新open表中的相同結點的G值和F值,并且把open表中的相同結點的父節點設置為當前結點。
??????????⑦ 如果相鄰結點nx不在open表中,直接把相鄰結點nx加入open表中。
(4)通過上述步驟后,從源結點到目標結點的路徑就生成了。
四、游戲界面(PyQt5)
1. 成員變量
??① 窗口變量:設置窗口大小
??② 地圖變量:設置地圖行列數、起點、終點、地圖列表
??③ 玩家變量:定義玩家坐標
??④ 游戲標志:定義各種游戲標志,如到第幾關、是否通關、人物左右。
??⑤ 音樂播放器:音樂播放器的初始化以及音樂的導入。
2. 構造函數
3. 子方法
??這次迷宮游戲學習了Prim算法以及A*算法收獲了很多,同時發掘經過前兩個項目的實踐,這次游戲編寫及調試的速度有了提升,整個游戲2天完成,第3天寫博客收尾。
———2020.12.21(1:25)(羅涵)
THE END
總結
以上是生活随笔為你收集整理的计算机软件实习项目三 —— 超级玛丽闯迷宫 (实验准备) 12-19(12-21更新)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 频率选择性衰落和时间选择性衰落详解
- 下一篇: 生活原则(1)