A*搜索算法--游戏寻路
文章目錄
- 1. 算法解析
- 2. 總結
仙劍奇俠傳這類MMRPG游戲中,有人物角色 自動尋路功能。當人物處于游戲地圖中某位置時,點擊另一個相對較遠的位置,人物就會自動地繞過障礙物走過去。這個功能是怎么實現的呢?
1. 算法解析
這是一個非常典型的搜索問題。起點是當下位置,終點是鼠標點擊位置。找一條路徑。路徑要繞過地圖中所有障礙,并且走的路不能太繞。最短路徑顯然是最聰明的走法,是最優解。
但是如果圖非常大,那Dijkstra最短路徑算法的執行耗時會很多。在真實的軟件開發中,面對的是超級大的地圖和海量的尋路請求,算法的執行效率太低,是無法接受的。
一般情況下,我們都不需要非得求最優解(最短路徑)。在權衡路線規劃質量和執行效率的情況下,只需要尋求一個次優解就足夠了。
- A* 算法是對Dijkstra算法的優化和改造。
Dijkstra 算法有點類似BFS算法,它每次找到跟起點最近的頂點,往外擴展。這種往外擴展有些盲目。舉一個例子。下圖對應一個真實地圖,每個點在地圖中的位置,用一個坐標(x,y)來表示,x橫坐標,y縱坐標。
在Dijkstra算法中,用一個優先隊列,記錄已經遍歷的頂點以及這個頂點與起點的路徑長度。頂點與起點路徑長度越小,優先從優先級隊列中取出來擴展,從圖中舉例可以看出,盡管找的是從s到t的路線,但是最先被搜索到的頂點依次是1,2,3。這個搜索方向明顯“跑偏"了。
之所以“跑偏”,是因為沒有考慮這個頂點到終點的距離,盡管1,2,3三個頂點離起始頂點最近,但離終點卻越來越遠。
如果綜合更多因素,把這個頂點到終點可能還要走多遠,考慮進去,綜合判斷哪個頂點先出隊列,是不是就可以避免“跑偏”呢?
當遍歷到某個頂點時,從起點走到這個頂點的路徑長度是確定的,我們記作g(i)。通過這個頂點跟終點之間的直線距離,也就是歐幾里得距離,來近似估計這個頂點跟終點的路徑長度。我們把這個距離記作h(i),專業叫法是啟發函數(heuristic function)。因為歐幾里得距離公式,會涉及比較耗時的開根號計算,所以一般計算曼哈頓距離(Manhattan distance)。曼哈頓距離是兩點之間橫縱坐標的距離之和。只涉及加減法、符號位反轉,所以更加高效。
int hManhattan(Vertex v1, Vertex v2) { // Vertex 表示頂點return Math.abs(v1.x - v2.x) + Math.abs(v1.y - v2.y); }通過兩者之和 f(i)= g(i)+ h(i),來判斷哪個頂點最先出隊。能有效避免“跑偏"。這里f(i)的專業叫法是估價函數(evaluation function)。
A* 算法就是對Djkstra算法的簡單改造。在A*算法的代碼實現中,頂點Vertex類的定義,多了x,y坐標,f(i)值。
A* 算法跟Djkstra 算法主要有3點區別:
- 優先級隊列構建的方式不同。A*算法是根據 f 值 f(i)=g(i)+h(i)來構建優先級隊列,而Dijkstra 算法是根據dist值 g(i)來構建優先級隊列;
- A*算法在更新頂點dist值的時候,同步更新 f 值;
- 循環結束的條件不一樣。Dijkstra 算法是在終點出隊列的時候才結束,A*算法是一旦遍歷到終點就結束。
盡管A* 算法可以快速找到從起點到終點的路線,但是它并不能像Dijkstra算法那樣,找到最短路線。
Dijkstra 算法在回溯基礎上,利用動態規劃思想,對回溯進行剪枝,只保留起點到某個頂點的最短路徑,繼續往外擴展搜索。動態規劃相較于回溯搜索,只是換了一個實現思路,但它實際上也考察到了所有從起點到終點的路線,所以能得到最優解。
A* 算法之所以不能像Dijkstra 算法那樣,找到最短路徑,主要原因是兩者的while 循環結束條件不一樣。
- Dijkstra 算法是在終點出隊列的時候才結束
- A*算法是一旦遍歷到終點就結束。
對于Dijkstra 算法來說,當終點出隊列的時候,終點的 dist 值是優先級隊列中所有頂點的最小值,即便再運行下去,終點的dist值也不會再被更新了。
對于A* 算法來說,一旦遍歷到終點,我們就結束 while循環,這個時候,終點的dist值未必是最小值。
A* 算法利用貪心算法的思路,每次都找 f 值最小的頂點出隊列,一旦搜到終點就不繼續考察其他頂點和路線。所以,它沒有考察所有路線,也就不能找出最短路徑。
如何借助A* 算法解決游戲尋路?
游戲地圖并不像現實生活中那樣,存在規劃非常清晰的道路,更多的是寬闊的荒野、草坪等。換一種抽象的思路,把地圖分割成一個一個的小方塊。在某個方塊上的人物,只能往上下左右四個方向移動。把每個方塊看作一個頂點。方塊相鄰,它們之間連兩條有向邊,權值都是1。套用A* 算法。
2. 總結
A* 算法屬于一種啟發式搜索算法(Heuristically Search Algorithm)。啟發式搜索算法還有很多其他算法,比如 IDA* 算法、蟻群算法、遺傳算法、模擬退火算法等。
- 啟發式搜索算法利用估價函數,避免“跑偏”,貪心地朝著最有可能到達終點的方向前進。
- 算法找出的路線,并不是最短路線。
- 實際軟件開發中的路線規劃問題,并不需要非得找最短路線。鑒于啟發式搜索算法能很好地平衡路線質量和執行效率,它應用更加廣泛。
總結
以上是生活随笔為你收集整理的A*搜索算法--游戏寻路的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: idea中git如何切换到master_
- 下一篇: 分治应用--万里挑一 找假硬币