12

Click here to load reader

A* Algorithm

Embed Size (px)

Citation preview

Page 1: A* Algorithm

演算法演算法演算法演算法 Term Project

資工二乙資工二乙資工二乙資工二乙 494512102

張逸豪張逸豪張逸豪張逸豪

Page 2: A* Algorithm

一、 前言:

為何選擇 A* Algorithm 做為這次的 Term Project 題目?其實原本是想介紹有

關遊戲方面的演算法,想想覺得即時戰略的遊戲,為何遊戲角色會知道我要

怎走才是最短的路徑?(雖然有些還是在繞路…),是如何避開那些障礙物找

到正確的路徑?也因此在上網查了相關資訊後決定研究最小路徑的演算法

A* Algorithm。

二、 A* Algorithm 介紹:

1. A* Algorithm 一個重要的核心就是開啟列表開啟列表開啟列表開啟列表 (Open List)和關閉列表關閉列表關閉列表關閉列表

(Closed List)的使用。開啟列表存放著你目前節點可能接下來會經過的節

點,如:

ED

G H I

F

CBA

若以 E 做為起始點,把 A~I 都加入到開啟列表中(因為 A, B, C, D, F, G, H, I 為 E

的相鄰節點),並把 E 指定為父父父父節點節點節點節點。若相鄰節點中有不可通過的節點(例如:

樹林、牆壁、湖泊…等),則不將其存入開啟列表中。關閉列表則存放已經走

過的路徑,不需要再次的檢查。

2. A* Algorithm 其中一個最重要的核心部分就是在其路徑評估路徑評估路徑評估路徑評估的公式,其公

式為:F= G + H,G 代表從起點,沿著產生的路徑,移動到你所相鄰節點相鄰節點相鄰節點相鄰節點

的移動代價;H 為從所選擇的相鄰節點移動到所指定終點終點終點終點的移動代價,

又稱為錯誤嘗試錯誤嘗試錯誤嘗試錯誤嘗試(Heuristic)的方法,因為此路徑的做法為猜測的方法,在

移動的過程中會碰到不同的障礙物(例如:樹林、牆壁、湖泊…等),所以

我們對於路徑的長度只能猜測,但這大多都是錯誤的路徑長度;F 則為 G

和 H 的和。H 的計算方式有許多種,比較常用的方法有:

A. 曼哈頓曼哈頓曼哈頓曼哈頓法法法法 (Manhattan Method):此方法計算目前節點到終點節點之

間水瓶和垂直的方格總數和,並將其和 * 10 (對角線方格並不在此

討論中),並忽略所有的障礙物,因此此結果為一估計值,而非其實

際值。(這有點像是在城市間的街角行進,對角線將被視為建築物而

無法穿越)。

Page 3: A* Algorithm

B. Diagonal Shortcut Method:此方法會計算兩點 x 軸和 y 軸的實際距

離,若 x 軸的距離 > y 軸的距離,則將 H 計算為:H = 14 * y 軸距離

+ 10 * (x 軸距離 – y 軸距離);若 x 軸距離 < y 軸距離,則將 H 計算

為 H = 14 * x 軸距離 + 10 * (y 軸距離 – x 軸距離)。

其他還有不同的方法,不過在此我們就不多做討論。

有了以上的準備,接下來我們就可以介紹 A* Algorithm 是怎麼算出最短路徑

的。

A* Algorthm 的 Pseudo Code 如下:

Add START to OPEN list

while OPEN not empty

get node n from OPEN that has the lowest f(n)

if n is GOAL then return path

move n to CLOSED

for each n' = CanMove(n, direction)

g(n') = g(n) + 1

calculate h(n')

if n' in OPEN list and new n' is not better, continue

if n' in CLOSED list and new n' is not better, continue

remove any n' from OPEN and CLOSED

add n as n's parent

add n' to OPEN

end for

Page 4: A* Algorithm

end while

if we get to here, then there is No Solution

我們將舉個例子來實做 A* Algorithm:

靛色 --- 起始節點

藍色 --- 父節點

橘色 --- 障礙物

紅色 --- 終點

綠色 --- 列入開始列表中 (起始節點和終點不包含在內)

紫色 --- 列入關閉列表中 (起始節點和終點不包含在內)

Figure 1

考慮 Figure1,若將 A3 設為起始點,E7 設為終點,A6, B5, B6, C4, C5, C6, D3,

D4, D5, D6 設為牆壁(障礙物),G 值水平和垂直設為 10,對角線設為 14;H

值的算法我們使用曼哈頓法(Manhattan Method);F 為 G 和 H 的和,則利用

A* Algorithm 算出最小路徑的方法為:

1. 首先將 A3 加入開始列表中,並設為父節點,將其鄰近點 A2, A4, B2, B3, B4

一併加入到開始列表中,並計算出:

A2 的 G 為 10,H 為 90 => F = 100

A4 的 G 為 10,H 為 70 => F = 80

B2 的 G 為 14,H 為 80 => F = 94

B3 的 G 為 10,H 為 70 => F = 80

Page 5: A* Algorithm

B4 的 G 為 14,H 為 60=> F = 74

並將其各點指向父節點(如 Figure 2)

Figure 2

我們選擇 F 值為最低的做為下一點,因此我們選擇 B4。

將設為父節點(如 Figure 3),並將 A3 從開始列表中刪除,加入到關閉列表中。

B4 的相鄰節點 B3, A4 已在開始列表中;又因為在此我們不考慮可以直接由

對角線繞過牆腳的方法,所以 A5, C3 不做考慮。C4, B5 為牆壁,也不做考慮。

因此我們計算出:

A5 的 G 為 28,H 為 60 => F = 88

(注意:在此新的節點的 G 值為以父節點為起點,將父節點的 G 值再加上再加上再加上再加上對

父節點相鄰節點的路徑代價)

並將其各點指向父節點。

Page 6: A* Algorithm

Figure 3

我們選擇 F 值為最低的做為下一點,因此我們又選擇 B3(F = 80),為何選擇

B3 而非 A4(F 亦 = 80),其原因在於,我們從速度上考慮,選擇最後加入列

表的節點會較為快節。這種導致了路徑搜尋過程中,在靠近目標的時候,優

先使用新找到的格子的偏好。

將 B3 設為父節點(如 Figure 4),並將 B4 從開始列表中刪除,加入到關閉列

表中。B3 的相鄰節點 A2, B2, A4 已在開始列表中;C4 為牆壁,也不做考慮。

因此我們計算出:

C2 的 G 為 24,H 為 70 => F = 94

C3 的 G 為 20,H 為 60 => F = 80

並將其各點指向父節點。

Figure 4

我們選擇 F 值為最低的做為下一點,因此我們選擇 C3,而非 B2,因為 C3

較 B2 晚加入到列表中。

將 C3 設為父節點(如 Figure 5),並將 B3 從開始列表中刪除,加入到關閉列

表中。接著我們可以見到 D3 為牆壁,不列入考慮,又因為在此我們不考慮

可以直接由對角線繞過牆腳的方法,所以 D2 不做考慮。

Page 7: A* Algorithm

A1 A2

C3C2C1

B8B7B6B5B4B3B2B1

A8A7A6A4A3

E2

F1

E1

D1

C8C7C6C5C4

D5D4

E4

F4F3F2

E3

D3D2 D8D7D6

E7

F8F7

E6

F6

E5

F5

E8

A5

Figure 5

因此我們直接選擇 C2 為下一點。

將 C2 設為父節點(如 Figure 6),並將 C3 從開始列表中刪除,加入到關閉列

表中。因此我們計算出:

B1 的 G 為 38,H 為 90 => F = 128

C1 的 G 為 34,H 為 80 => F = 114

D1 的 G 為 38,H 為 70 => F = 108

D2 的 G 為 34,H 為 60 => F = 94

並將其各點指向父節點。

Figure 6

我們選擇 F 值為最低的做為下一點,因此我們選擇 D2。

Page 8: A* Algorithm

將 D2 設為父節點(如 Figure 7),並將 C2 從開始列表中刪除,加入到關閉列

表中。又因為在此我們不考慮可以直接由對角線繞過牆腳的方法,所以 E3

不做考慮。因此我們計算出:

E1 的 G 為 48,H 為 60 => F = 108

E2 的 G 為 44,H 為 50 => F = 94

並將其各點指向父節點。

Figure 7

我們選擇 F 值為最低的做為下一點,因此我們選擇 E2。

將 E2 設為父節點(如 Figure 8),並將 D2 從開始列表中刪除,加入到關閉列

表中。我們計算出:

E3 的 G 為 54,H 為 40 => F = 94

F1 的 G 為 58,H 為 70 => F = 128

F2 的 G 為 54,H 為 60 => F = 114

F3 的 G 為 58,H 為 50 => F = 108

並將其各點指向父節點。

Page 9: A* Algorithm

Figure 8

我們選擇 F 值為最低的做為下一點,因此我們選擇 E3。

將 E3 設為父節點(如 Figure 9),並將 E2 從開始列表中刪除,加入到關閉列

表中。我們計算出:

E4 的 G 為 64,H 為 30 => F = 94

F4 的 G 為 68,H 為 40 => F = 108

並將其各點指向父節點。

Figure 9

我們選擇 F 值為最低的做為下一點,因此我們選擇 E4。

Page 10: A* Algorithm

將 E4 設為父節點(如 Figure 10),並將 E3 從開始列表中刪除,加入到關閉列

表中。我們計算出:

E5 的 G 為 74,H 為 20 => F = 94

F5 的 G 為 78,H 為 30 => F = 108

並將其各點指向父節點。

Figure 10

我們選擇 F 值為最低的做為下一點,因此我們選擇 E5。

將 E5 設為父節點(如 Figure 11),並將 E4 從開始列表中刪除,加入到關閉列

表中。我們計算出:

E6 的 G 為 84,H 為 10 => F = 94

F6 的 G 為 88,H 為 20 => F = 108

並將其各點指向父節點。

Page 11: A* Algorithm

Figure 11

我們選擇 F 值為最低的做為下一點,因此我們選擇 E6。

將 E6 設為父節點(如 Figure 12),並將 E5 從開始列表中刪除,加入到關閉列

表中。我們計算出:

E7 的 G 為 94,H 為 0 => F = 94

F7 的 G 為 98,H 為 10 => F = 108

並將其各點指向父節點。

Figure 12

最後我們可以發現已經達到終點 E7,由 E7 反推回去至起始節點的路徑為:

E7→E6→E5→E4→E3→E2→D2→C2→B3→A3,因此由起始節點 A3 至終點 E7

Page 12: A* Algorithm

的最短路徑為:A3→B3→C2→D2→E2→E3→E4→E5→E6→E7。

三、 心得:A* Algorithm 的原理並不難,研究起來也非常的有趣,大概是因

為跟遊戲有關係吧?!只是實做時還會有更多額外的外在因素會影響到 A*

Algorithm 的結果。

例如:

1. 其他元素:如果碰到的障礙物並不是靜止的,而是移動的,那麼 A*

Algorithm 設計起來將會非常的複雜,網路上的資料就有提到:不妨只考

慮靜止或那些在計算路徑時臨近而來的元素,將其當前位置的標誌設為

可通過的,而對於鄰近的運動中的元素,則使用懲罰懲罰懲罰懲罰她們各自路徑上的

節點來鼓勵這些路徑搜尋程是找到不同的路徑。

2. 不同地形的耗損:在遊戲中,一定會有不同地形的路徑,如果將地形的

耗損也考慮進去,那麼有時候距離最短的路徑不一定是最快的,不過其

設計起來並不困難,只需在公式中一併計算地形耗損的值即可。

3. 其他因素:像是遊戲中可能會考慮到物種的相剋、敵人的多寡、任務目

標…等,進而影響最短路徑的計算,所以各個遊戲在使用 A* Algorithm 時

都需考慮到其自身影響的因素而加以改良。

其實原本還想將 A* Algorithm 和 Dijkstra Algorithm 拿來做比較的,因為兩者

均為尋找最短路徑的演算法(不過在查了資料後,發現 A* Algorithm 似乎比

Dijkstra Algorithm 要來的好點?!) 只可惜畫圖畫了太久,實在沒有其餘心力

再去將 A* Algorithm 和 Dijkstra Algorithm 做一番比較。不過還是希望下次有

機會可以將 A* Algorithm 研究的更為透徹。

四、 參考資料:

http://swf.com.tw/?p=67

http://www.policyalmanac.org/games/heuristics.htm

http://en.wikipedia.org/wiki/A%2A_algorithm

http://blog.minstrel.idv.tw/2004/12/star-algorithm.html

http://www.geocities.com/jheyesjones/astar.html

http://www.edenwaith.com/products/pige/tutorials/a-star.php