1. 程式人生 > >尋路演算法簡介

尋路演算法簡介

對一個物體來說,移動很容易,而尋路很複雜。

為什麼要尋找路徑?考慮以下情況:

一個單位最初位於地圖的底部,並希望到達頂部。

Movement - 它掃描的區域(肉色底)中沒有任何阻擋表示該裝置不應向上移動,因此它繼續前進。在頂部附近,它會檢測到障礙物並改變方向。然後它沿著(紅色)路徑繞過“U”形障礙物。

Pathfinding - 另一個想法是,探路者掃描更大的區域(淺藍底),發現較短的路徑(藍色),從而避免走進凹形障礙物。

 

另外,您可以擴充套件移動演算法以解決上面顯示的陷阱問題。可以避免生成凹陷障礙物,也可以將它們的凸包標記為危險(只有在目的地位於內部時才進入):

 

尋路的搜尋器希望能夠提前計劃,而不是等到最後一刻發現障礙。

我們需要在(Pathfinding)路徑規劃和(Movement)進行移動之間進行權衡。

規劃通常較慢,但能給出更好的路徑;運動通常更快,但可能會卡住。

如果遊戲世界經常變化,那麼提前規劃就不那麼有價值了。

我建議同時使用:在擁有大型、移動緩慢的障礙物,以及起點到目標之間有很長的路徑時用 Pathfinding;在區域性區域、有快速變化和較短路徑時用 Movement。

演算法

新頁面

計科的教科書中,尋路演算法,應用在圖論中

圖在數學意義上,是一組具有連線它們的邊緣的頂點。

 

平鋪的遊戲地圖可以視為一張圖。

每個平鋪塊都是頂點,彼此相鄰的圖塊之間有連線的邊:

 

現在,假設我們正在使用二維網格

如果您之前沒有使用圖表,參閱此入門手冊稍後,我將討論如何從遊戲世界中構建其他型別的圖形

來自AI或演算法研究的大多數尋路演算法,都是針對任意圖形,而不是基於網格的遊戲而設計的。

我們想找到一些可以利用遊戲地圖性質的東西。

我們認為有些事情是常識,但演算法並不理解。我們對距離有所瞭解:一般來說,當兩個東西相距較遠時,假設沒有蟲洞,則需要更長時間才能從一個移動到另一個。我們對方向有所瞭解:如果您的目的地位於東方,那麼走向東方的路徑比走向西方更容易找到最佳路徑。在網格上,我們知道關於對稱性的東西:大多數時候,向北移動然後向東移動與向東移動然後向北移動相同。這些附加資訊可以幫助我們更快地執行尋路演算法。

Dijkstra演算法和最佳優先搜尋

Dijkstra 演算法通過從物件的起點開始訪問圖中的頂點來工作。

然後,它重複檢查最近的尚未檢查的頂點,將其頂點新增到要檢查的頂點集

從起點向外擴充套件,直到達到目標。

Dijkstra 演算法保證找到一條從起點到目標的最短路徑,只要沒有邊緣具有負成本。(我寫的是“一條最短路徑”,因為通常存在多個等效短路徑。)

在下圖中,粉紅色方塊是起點,藍色方塊是目標,藍綠色區域顯示Dijkstra演算法掃描的區域。最輕的藍綠色區域距離起點最遠,因此形成了探索的“前沿”:

 

 

貪心演算法(Greedy Best-First-Search)以類似的方式工作,除了它有一些估計(稱為啟發式,任何頂點離目標有多遠。它不是選擇最接近起點的頂點,而是選擇最接近目標的頂點)。

貪心演算法不保證找到最短的路徑。

然而,它比 Dijkstra演算法執行得快得多,因為它用的啟發式函式非常快速地引導它朝向目標。例如,如果目標位於起始位置的南側,則貪心演算法將傾向於關注向南的路徑。

在下圖中,黃色表示具有高啟發式值(達到目標的高成本)的節點,黑色表示具有低啟發式值的節點(達到目標的低成本)。它表明,與Dijkstra的演算法相比,貪心演算法可以非常快速地找到路徑:

然而,這兩個例子都說明了最簡單的情況 - 當地圖沒有障礙物時,最短路徑確實是一條直線。

讓我們考慮上一節中描述的凹陷障礙。Dijkstra的演算法更加努力,但保證找到最短的路徑:

另一方面,貪心的Best-First-Search做的工作較少,但其路徑顯然不太好:

麻煩的是貪婪的Best-First-Search是“貪心的”,試圖朝著目標前進,即使它不是正確的道路。

因為它只考慮到達目標的成本忽略了到目前為止的路徑成本,所以即使它會繼續前進,即便所使用的路徑會變得非常長。

 

將兩者中最好的結合起來會不會很好?

A *是在1968年開發的,用於結合啟發式方法(如貪心演算法)和其他更莊重些的方法(如Dijsktra演算法)。

這有點不尋常,因為啟發式演算法通常會為您提供一種解決問題的近似方法,而無法保證最優解。

而 A* 建立在啟發式的基礎之上,雖然啟發式本身並不能保證,但 A* 可以保證最短的路徑。

 A* 演算法

我將專注於A* 演算法A* 是尋路尋找最受歡迎的選擇,因為它非常靈活,可以在各種環境中使用。

像 Dijkstra 演算法一樣,它可以用來找到最短的路徑。像貪心演算法一樣,它可以使用啟發式來指導自己。在簡單的情況下,它與貪心演算法一樣快:

在具有凹陷障礙物的示例中,A* 可以找到與Dijkstra演算法找到的路徑一樣好的路徑:

它成功的祕訣在於它結合了Dijkstra演算法使用的資訊(支援接近起點的頂點)和貪心演算法使用的資訊(支援接近目標的頂點)。

在談論A *時使用的標準術語,g(n)表示從起點到任何頂點的路徑確切成本 nh(n)表示從頂點到目標的啟發式估計成本 n

在上圖中,黃色點(h)表示遠離目標的頂點,藍綠色點(g)表示遠離起點的頂點。

A* 在從起點移動到目標時平衡兩者。每次通過主迴圈,它檢查 具有最低的頂點 f(n) = g(n) + h(n)

本文的其餘部分將探討啟發式設計實現地圖表示以及與在遊戲中使用尋路相關的各種其他主題。有些部分很充實,有些則相當不完整。