青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆 - 224  文章 - 41  trackbacks - 0
<2010年4月>
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

享受編程

常用鏈接

留言簿(11)

隨筆分類(159)

隨筆檔案(224)

文章分類(2)

文章檔案(4)

經(jīng)典c++博客

搜索

  •  

最新評(píng)論

閱讀排行榜

評(píng)論排行榜

原文地址:http://www.vckbase.com/document/viewdoc/?id=1422

原文出處:http://www.gamedev.net/reference/articles/article2003.asp


A*尋路初探

原文:Patrick Lester
翻譯:Panic
2005
318

 


譯者序
  很久以前就知道了A*算法,但是從未認(rèn)真讀過相關(guān)的文章,也沒有看過代碼,只是腦子里有個(gè)模糊的概念。這次決定從頭開始,研究一下這個(gè)被人推崇備至的簡單方法,作為學(xué)習(xí)人工智能的開始。
這篇文章非常知名,國內(nèi)應(yīng)該有不少人翻譯過它,我沒有查找,覺得翻譯本身也是對(duì)自身英文水平的鍛煉。經(jīng)過努力,終于完成了文檔,也明白的A*算法的原理。毫無疑問,作者用形象的描述,簡潔詼諧的語言由淺入深的講述了這一神奇的算法,相信每個(gè)讀過的人都會(huì)對(duì)此有所認(rèn)識(shí)(如果沒有,那就是偶的翻譯太差了--b)。
  以下是翻譯的正文。(由于本人使用ultraedit編輯,所以沒有對(duì)原文中的各種鏈接加以處理(除了圖表),也是為了避免未經(jīng)許可鏈接的嫌疑,有興趣的讀者可以參考原文。


會(huì)者不難,A*(念作A)算法對(duì)初學(xué)者來說的確有些難度。

這篇文章并不試圖對(duì)這個(gè)話題作權(quán)威的陳述。取而代之的是,它只是描述算法的原理,使你可以在進(jìn)一步的閱讀中理解其他相關(guān)的資料。

最后,這篇文章沒有程序細(xì)節(jié)。你盡可以用任意的計(jì)算機(jī)程序語言實(shí)現(xiàn)它。如你所愿,我在文章的末尾包含了一個(gè)指向例子程序的鏈接。 壓縮包包括C++Blitz Basic兩個(gè)語言的版本,如果你只是想看看它的運(yùn)行效果,里面還包含了可執(zhí)行文件。

我們正在提高自己。讓我們從頭開始......

序:搜索區(qū)域
   假設(shè)有人想從A點(diǎn)移動(dòng)到一墻之隔的B點(diǎn),如下圖,綠色的是起點(diǎn)A,紅色是終點(diǎn)B,藍(lán)色方塊是中間的墻。


[
1]

  你首先注意到,搜索區(qū)域被我們劃分成了方形網(wǎng)格。像這樣,簡化搜索區(qū)域,是尋路的第一步。這一方法把搜索區(qū)域簡化成了一個(gè)二維數(shù)組。數(shù)組的每一個(gè)元素是網(wǎng)格的一個(gè)方塊,方塊被標(biāo)記為可通過的和不可通過的。路徑被描述為從AB我們經(jīng)過的方塊的集合。一旦路徑被找到,我們的人就從一個(gè)方格的中心走向另一個(gè),直到到達(dá)目的地。

這些中點(diǎn)被稱為節(jié)點(diǎn)。當(dāng)你閱讀其他的尋路資料時(shí),你將經(jīng)常會(huì)看到人們討論節(jié)點(diǎn)。為什么不把他們描述為方格呢?因?yàn)橛锌赡苣愕穆窂奖环指畛善渌皇欠礁竦慕Y(jié)構(gòu)。他們完全可以是矩形,六角形,或者其他任意形狀。節(jié)點(diǎn)能夠被放置在形狀的任意位置-可以在中心,或者沿著邊界,或其他什么地方。我們使用這種系統(tǒng),無論如何,因?yàn)樗亲詈唵蔚摹?/span>

開始搜索

正如我們處理上圖網(wǎng)格的方法,一旦搜索區(qū)域被轉(zhuǎn)化為容易處理的節(jié)點(diǎn),下一步就是去引導(dǎo)一次找到最短路徑的搜索。在A*尋路算法中,我們通過從點(diǎn)A開始,檢查相鄰方格的方式,向外擴(kuò)展直到找到目標(biāo)。

我們做如下操作開始搜索:

  1. 從點(diǎn)A開始,并且把它作為待處理點(diǎn)存入一個(gè)開啟列表。開啟列表就像一張購物清單。盡管現(xiàn)在列表里只有一個(gè)元素,但以后就會(huì)多起來。你的路徑可能會(huì)通過它包含的方格,也可能不會(huì)。基本上,這是一個(gè)待檢查方格的列表。
  2. 尋找起點(diǎn)周圍所有可到達(dá)或者可通過的方格,跳過有墻,水,或其他無法通過地形的方格。也把他們加入開啟列表。為所有這些方格保存點(diǎn)A作為父方格。當(dāng)我們想描述路徑的時(shí)候,父方格的資料是十分重要的。后面會(huì)解釋它的具體用途。
  3. 從開啟列表中刪除點(diǎn)A,把它加入到一個(gè)關(guān)閉列表,列表中保存所有不需要再次檢查的方格。

在這一點(diǎn),你應(yīng)該形成如圖的結(jié)構(gòu)。在圖中,暗綠色方格是你起始方格的中心。它被用淺藍(lán)色描邊,以表示它被加入到關(guān)閉列表中了。所有的相鄰格現(xiàn)在都在開啟列表中,它們被用淺綠色描邊。每個(gè)方格都有一個(gè)灰色指針反指他們的父方格,也就是開始的方格。

[2]

接著,我們選擇開啟列表中的臨近方格,大致重復(fù)前面的過程,如下。但是,哪個(gè)方格是我們要選擇的呢?是那個(gè)F值最低的。

路徑評(píng)分

選擇路徑中經(jīng)過哪個(gè)方格的關(guān)鍵是下面這個(gè)等式:

F = G + H

這里:

  • G = 從起點(diǎn)A,沿著產(chǎn)生的路徑,移動(dòng)到網(wǎng)格上指定方格的移動(dòng)耗費(fèi)。
  • H = 從網(wǎng)格上那個(gè)方格移動(dòng)到終點(diǎn)B的預(yù)估移動(dòng)耗費(fèi)。這經(jīng)常被稱為啟發(fā)式的,可能會(huì)讓你有點(diǎn)迷惑。這樣叫的原因是因?yàn)樗皇莻€(gè)猜測(cè)。我們沒辦法事先知道路徑的長度,因?yàn)槁飞峡赡艽嬖诟鞣N障礙(墻,水,等等)。雖然本文只提供了一種計(jì)算H的方法,但是你可以在網(wǎng)上找到很多其他的方法。

我們的路徑是通過反復(fù)遍歷開啟列表并且選擇具有最低F值的方格來生成的。文章將對(duì)這個(gè)過程做更詳細(xì)的描述。首先,我們更深入的看看如何計(jì)算這個(gè)方程。

正如上面所說G表示沿路徑從起點(diǎn)到當(dāng)前點(diǎn)的移動(dòng)耗費(fèi)。在這個(gè)例子里,我們令水平或者垂直移動(dòng)的耗費(fèi)為10,對(duì)角線方向耗費(fèi)為14。我們?nèi)∵@些值是因?yàn)檠貙?duì)角線的距離是沿水平或垂直移動(dòng)耗費(fèi)的的根號(hào)2(別怕),或者約1.414倍。為了簡化,我們用1014近似。比例基本正確,同時(shí)我們避免了求根運(yùn)算和小數(shù)。這不是只因?yàn)槲覀兣侣闊┗蛘卟幌矚g數(shù)學(xué)。使用這樣的整數(shù)對(duì)計(jì)算機(jī)來說也更快捷。你不就就會(huì)發(fā)現(xiàn),如果你不使用這些簡化方法,尋路會(huì)變得很慢

既然我們?cè)谟?jì)算沿特定路徑通往某個(gè)方格的G值,求值的方法就是取它父節(jié)點(diǎn)的G值,然后依照它相對(duì)父節(jié)點(diǎn)是對(duì)角線方向或者直角方向(非對(duì)角線),分別增加1410。例子中這個(gè)方法的需求會(huì)變得更多,因?yàn)槲覀儚钠瘘c(diǎn)方格以外獲取了不止一個(gè)方格。

H可以用不同的方法估算。我們這里使用的方法被稱為曼哈頓方法,它計(jì)算從當(dāng)前格到目的格之間水平和垂直的方格的數(shù)量總和,忽略對(duì)角線方向。然后把結(jié)果乘以10。這被成為曼哈頓方法是因?yàn)樗雌饋硐裼?jì)算城市中從一個(gè)地方到另外一個(gè)地方的街區(qū)數(shù),在那里你不能沿對(duì)角線方向穿過街區(qū)。很重要的一點(diǎn),我們忽略了一切障礙物。這是對(duì)剩余距離的一個(gè)估算,而非實(shí)際值,這也是這一方法被稱為啟發(fā)式的原因。想知道更多?你可以在這里找到方程和額外的注解

F的值是GH的和。第一步搜索的結(jié)果可以在下面的圖表中看到。F,GH的評(píng)分被寫在每個(gè)方格里。正如在緊挨起始格右側(cè)的方格所表示的,F被打印在左上角,G在左下角,H則在右下角。


[
3]

現(xiàn)在我們來看看這些方格。寫字母的方格里,G = 10。這是因?yàn)樗辉谒椒较蚱x起始格一個(gè)格距。緊鄰起始格的上方,下方和左邊的方格的G值都等于10。對(duì)角線方向的G值是14
  H值通過求解到紅色目標(biāo)格的曼哈頓距離得到,其中只在水平和垂直方向移動(dòng),并且忽略中間的墻。用這種方法,起點(diǎn)右側(cè)緊鄰的方格離紅色方格有3格距離,H值就是30。這塊方格上方的方格有4格距離(記住,只能在水平和垂直方向移動(dòng))H值是40。你大致應(yīng)該知道如何計(jì)算其他方格的H值了~。每個(gè)格子的F值,還是簡單的由GH相加得到

繼續(xù)搜索

為了繼續(xù)搜索,我們簡單的從開啟列表中選擇F值最低的方格。然后,對(duì)選中的方格做如下處理:

4.把它從開啟列表中刪除,然后添加到關(guān)閉列表中。

5.檢查所有相鄰格子。跳過那些已經(jīng)在關(guān)閉列表中的或者不可通過的(有墻,水的地形,或者其他無法通過的地形),把他們添加進(jìn)開啟列表,如果他們還不在里面的話。把選中的方格作為新的方格的父節(jié)點(diǎn)。

6.如果某個(gè)相鄰格已經(jīng)在開啟列表里了,檢查現(xiàn)在的這條路徑是否更好。換句話說,檢查如果我們用新的路徑到達(dá)它的話,G值是否會(huì)更低一些。如果不是,那就什么都不做。

另一方面,如果新的G值更低,那就把相鄰方格的父節(jié)點(diǎn)改為目前選中的方格(在上面的圖表中,把箭頭的方向改為指向這個(gè)方格)。最后,重新計(jì)算FG的值。如果這看起來不夠清晰,你可以看下面的圖示。  

好了,讓我們看看它是怎么運(yùn)作的。我們最初的9格方格中,在起點(diǎn)被切換到關(guān)閉列表中后,還剩8格留在開啟列表中。這里面,F值最低的那個(gè)是起始格右側(cè)緊鄰的格子,它的F值是40。因此我們選擇這一格作為下一個(gè)要處理的方格。在緊隨的圖中,它被用藍(lán)色突出顯示。

[4]

 首先,我們把它從開啟列表中取出,放入關(guān)閉列表(這就是他被藍(lán)色突出顯示的原因)。然后我們檢查相鄰的格子。哦,右側(cè)的格子是墻,所以我們略過。左側(cè)的格子是起始格。它在關(guān)閉列表里,所以我們也跳過它。
  其他4格已經(jīng)在開啟列表里了,于是我們檢查G值來判定,如果通過這一格到達(dá)那里,路徑是否更好。我們來看選中格子下面的方格。它的G值是14。如果我們從當(dāng)前格移動(dòng)到那里,G值就會(huì)等于20(到達(dá)當(dāng)前格的G值是10,移動(dòng)到上面的格子將使得G值增加10)。因?yàn)?/span>G20大于14,所以這不是更好的路徑。如果你看圖,就能理解。與其通過先水平移動(dòng)一格,再垂直移動(dòng)一格,還不如直接沿對(duì)角線方向移動(dòng)一格來得簡單。

當(dāng)我們對(duì)已經(jīng)存在于開啟列表中的4個(gè)臨近格重復(fù)這一過程的時(shí)候,我們發(fā)現(xiàn)沒有一條路徑可以通過使用當(dāng)前格子得到改善,所以我們不做任何改變。既然我們已經(jīng)檢查過了所有鄰近格,那么就可以移動(dòng)到下一格了。

于是我們檢索開啟列表,現(xiàn)在里面只有7格了,我們?nèi)匀贿x擇其中F值最低的。有趣的是,這次,有兩個(gè)格子的數(shù)值都是54。我們?nèi)绾芜x擇?這并不麻煩。從速度上考慮,選擇最后添加進(jìn)列表的格子會(huì)更快捷。這種導(dǎo)致了尋路過程中,在靠近目標(biāo)的時(shí)候,優(yōu)先使用新找到的格子的偏好。但這無關(guān)緊要。(對(duì)相同數(shù)值的不同對(duì)待,導(dǎo)致不同版本的A*算法找到等長的不同路徑。)

那我們就選擇起始格右下方的格子,如圖。

[5]

這次,當(dāng)我們檢查相鄰格的時(shí)候,發(fā)現(xiàn)右側(cè)是墻,于是略過。上面一格也被略過。我們也略過了墻下面的格子。為什么呢?因?yàn)槟悴荒茉诓淮┰綁堑那闆r下直接到達(dá)那個(gè)格子。你的確需要先往下走然后到達(dá)那一格,按部就班的走過那個(gè)拐角。(注解:穿越拐角的規(guī)則是可選的。它取決于你的節(jié)點(diǎn)是如何放置的。)
  這樣一來,就剩下了其他5格。當(dāng)前格下面的另外兩個(gè)格子目前不在開啟列表中,于是我們添加他們,并且把當(dāng)前格指定為他們的父節(jié)點(diǎn)。其余3格,兩個(gè)已經(jīng)在關(guān)閉列表中(起始格,和當(dāng)前格上方的格子,在表格中藍(lán)色高亮顯示),于是我們略過它們。最后一格,在當(dāng)前格的左側(cè),將被檢查通過這條路徑,G值是否更低。不必?fù)?dān)心,我們已經(jīng)準(zhǔn)備好檢查開啟列表中的下一格了。

我們重復(fù)這個(gè)過程,知道目標(biāo)格被添加進(jìn)開啟列表,就如在下面的圖中所看到的。


[
6]

注意,起始格下方格子的父節(jié)點(diǎn)已經(jīng)和前面不同的。之前它的G值是28,并且指向右上方的格子。現(xiàn)在它的G值是20,指向它上方的格子。這在尋路過程中的某處發(fā)生,當(dāng)應(yīng)用新路徑時(shí),G值經(jīng)過檢查變得低了-于是父節(jié)點(diǎn)被重新指定,GF值被重新計(jì)算。盡管這一變化在這個(gè)例子中并不重要,在很多場(chǎng)合,這種變化會(huì)導(dǎo)致尋路結(jié)果的巨大變化。

那么,我們?cè)趺创_定這條路徑呢?很簡單,從紅色的目標(biāo)格開始,按箭頭的方向朝父節(jié)點(diǎn)移動(dòng)。這最終會(huì)引導(dǎo)你回到起始格,這就是你的路徑!看起來應(yīng)該像圖中那樣。從起始格A移動(dòng)到目標(biāo)格B只是簡單的從每個(gè)格子(節(jié)點(diǎn))的中點(diǎn)沿路徑移動(dòng)到下一個(gè),直到你到達(dá)目標(biāo)點(diǎn)。就這么簡單。


[
7]

A*方法總結(jié)

好,現(xiàn)在你已經(jīng)看完了整個(gè)說明,讓我們把每一步的操作寫在一起:把起始格添加到開啟列表。

  1. 重復(fù)如下的工作:

 a) 尋找開啟列表中F值最低的格子。我們稱它為當(dāng)前格。

 b) 把它切換到關(guān)閉列表。

c) 對(duì)相鄰的8格中的每一個(gè)?

如果它不可通過或者已經(jīng)在關(guān)閉列表中,略過它。反之如下。

    • 如果它不在開啟列表中,把它添加進(jìn)去。把當(dāng)前格作為這一格的父節(jié)點(diǎn)。記錄這一格的F,G,H值。
    • 如果它已經(jīng)在開啟列表中,用G值為參考檢查新的路徑是否更好。更低的G值意味著更好的路徑。如果是這樣,就把這一格的父節(jié)點(diǎn)改成當(dāng)前格,并且重新計(jì)算這一格的GF值。如果你保持你的開啟列表按F值排序,改變之后你可能需要重新對(duì)開啟列表排序。

d) 停止,當(dāng)你

    • 把目標(biāo)格添加進(jìn)了開啟列表,這時(shí)候路徑被找到,或者
    • 沒有找到目標(biāo)格,開啟列表已經(jīng)空了。這時(shí)候,路徑不存在。
  1. 保存路徑。從目標(biāo)格開始,沿著每一格的父節(jié)點(diǎn)移動(dòng)直到回到起始格。這就是你的路徑。

題外話

離題一下,見諒,值得一提的是,當(dāng)你在網(wǎng)上或者相關(guān)論壇看到關(guān)于A*的不同的探討,你有時(shí)會(huì)看到一些被當(dāng)作A*算法的代碼而實(shí)際上他們不是。要使用A*,你必須包含上面討論的所有元素--特定的開啟和關(guān)閉列表,用F,GH作路徑評(píng)價(jià)。有很多其他的尋路算法,但他們并不是A*A*被認(rèn)為是他們當(dāng)中最好的。Bryan Stout在這篇文章后面的參考文檔中論述了一部分,包括他們的一些優(yōu)點(diǎn)和缺點(diǎn)。有時(shí)候特定的場(chǎng)合其他算法會(huì)更好,但你必須很明確你在作什么。好了,夠多的了。回到文章。

實(shí)現(xiàn)的注解

  現(xiàn)在你已經(jīng)明白了基本原理,寫你的程序的時(shí)候還得考慮一些額外的東西。下面這些材料中的一些引用了我用C++Blitz Basic寫的程序,但對(duì)其他語言寫的代碼同樣有效。

  1. 維護(hù)開啟列表:這是A*尋路算法最重要的組成部分。每次你訪問開啟列表,你都需要尋找F值最低的方格。有幾種不同的方法實(shí)現(xiàn)這一點(diǎn)。你可以把路徑元素隨意保存,當(dāng)需要尋找F值最低的元素的時(shí)候,遍歷開啟列表。這很簡單,但是太慢了,尤其是對(duì)長路徑來說。這可以通過維護(hù)一格排好序的列表來改善,每次尋找F值最低的方格只需要選取列表的首元素。當(dāng)我自己實(shí)現(xiàn)的時(shí)候,這種方法是我的首選。

在小地圖。這種方法工作的很好,但它并不是最快的解決方案。更苛求速度的A*程序員使用叫做“binary heap”的方法,這也是我在代碼中使用的方法。憑我的經(jīng)驗(yàn),這種方法在大多數(shù)場(chǎng)合會(huì)快23倍,并且在長路經(jīng)上速度呈幾何級(jí)數(shù)提升(10倍以上速度)。如果你想了解更多關(guān)于binary heap的內(nèi)容,查閱我的文章:Using Binary Heaps in A* Pathfinding

  1. 其他單位:如果你恰好看了我的例子代碼,你會(huì)發(fā)現(xiàn)它完全忽略了其他單位。我的尋路者事實(shí)上可以相互穿越。取決于具體的游戲,這也許可以,也許不行。如果你打算考慮其他單位,希望他們能互相繞過,我建議在尋路算法中忽略其他單位,寫一些新的代碼作碰撞檢測(cè)。當(dāng)碰撞發(fā)生,你可以生成一條新路徑或者使用一些標(biāo)準(zhǔn)的移動(dòng)規(guī)則(比如總是向右,等等)直到路上沒有了障礙,然后再生成新路徑。為什么在最初的路徑計(jì)算中不考慮其他單位呢?那是因?yàn)槠渌麊挝粫?huì)移動(dòng),當(dāng)你到達(dá)他們?cè)瓉淼奈恢玫臅r(shí)候,他們可能已經(jīng)離開了。這有可能會(huì)導(dǎo)致奇怪的結(jié)果,一個(gè)單位突然轉(zhuǎn)向,躲避一個(gè)已經(jīng)不在那里的單位,并且會(huì)撞到計(jì)算完路徑后,沖進(jìn)它的路徑中的單位。
      然而,在尋路算法中忽略其他對(duì)象,意味著你必須編寫單獨(dú)的碰撞檢測(cè)代碼。這因游戲而異,所以我把這個(gè)決定權(quán)留給你。參考文獻(xiàn)列表中,Bryan Stout的文章值得研究,里面有一些可能的解決方案(像魯棒追蹤,等等)
  2. 一些速度方面的提示:當(dāng)你開發(fā)你自己的A*程序,或者改寫我的,你會(huì)發(fā)現(xiàn)尋路占據(jù)了大量的CPU時(shí)間,尤其是在大地圖上有大量對(duì)象在尋路的時(shí)候。如果你閱讀過網(wǎng)上的其他材料,你會(huì)明白,即使是開發(fā)了星際爭霸或帝國時(shí)代的專家,這也無可奈何。如果你覺得尋路太過緩慢,這里有一些建議也許有效:
    • 使用更小的地圖或者更少的尋路者。
    • 不要同時(shí)給多個(gè)對(duì)象尋路。取而代之的是把他們加入一個(gè)隊(duì)列,把尋路過程分散在幾個(gè)游戲周期中。如果你的游戲以40周期每秒的速度運(yùn)行,沒人能察覺。但是他們會(huì)發(fā)覺游戲速度突然變慢,當(dāng)大量尋路者計(jì)算自己路徑的時(shí)候。
    • 盡量使用更大的地圖網(wǎng)格。這降低了尋路中搜索的總網(wǎng)格數(shù)。如果你有志氣,你可以設(shè)計(jì)兩個(gè)或者更多尋路系統(tǒng)以便使用在不同場(chǎng)合,取決于路徑的長度。這也正是專業(yè)人士的做法,用大的區(qū)域計(jì)算長的路徑,然后在接近目標(biāo)的時(shí)候切換到使用小格子/區(qū)域的精細(xì)尋路。如果你對(duì)這個(gè)觀點(diǎn)感興趣,查閱我的文章 Two-Tiered A* Pathfinding
    • 使用路徑點(diǎn)系統(tǒng)計(jì)算長路徑,或者預(yù)先計(jì)算好路徑并加入到游戲中。
    • 預(yù)處理你的地圖,表明地圖中哪些區(qū)域是不可到達(dá)的。我把這些區(qū)域稱作孤島。事實(shí)上,他們可以是島嶼或其他被墻壁包圍等無法到達(dá)的任意區(qū)域。A*的下限是,當(dāng)你告訴它要尋找通往那些區(qū)域的路徑時(shí),它會(huì)搜索整個(gè)地圖,直到所有可到達(dá)的方格/節(jié)點(diǎn)都被通過開啟列表和關(guān)閉列表的計(jì)算。這會(huì)浪費(fèi)大量的CPU時(shí)間。可以通過預(yù)先確定這些區(qū)域(比如通過flood-fill或類似的方法)來避免這種情況的發(fā)生,用某些種類的數(shù)組記錄這些信息,在開始尋路前檢查它。在我Blitz版本的代碼中,我建立了一個(gè)地圖預(yù)處理器來作這個(gè)工作。它也標(biāo)明了尋路算法可以忽略的死端,這進(jìn)一步提高了尋路速度。
  3. 不同的地形損耗:在這個(gè)教程和我附帶的程序中,地形只有兩種-可通過的和不可通過的。但是你可能會(huì)需要一些可通過的地形,但是移動(dòng)耗費(fèi)更高-沼澤,小山,地牢的樓梯,等等。這些都是可通過但是比平坦的開闊地移動(dòng)耗費(fèi)更高的地形。類似的,道路應(yīng)該比自然地形移動(dòng)耗費(fèi)更低。

  這個(gè)問題很容易解決,只要在計(jì)算任何地形的G值的時(shí)候增加地形損耗就可以了。簡單的給它增加一些額外的損耗就可以了。由于A*算法已經(jīng)按照尋找最低耗費(fèi)的路徑來設(shè)計(jì),所以很容易處理這種情況。在我提供的這個(gè)簡單的例子里,地形只有可通過和不可通過兩種,A*會(huì)找到最短,最直接的路徑。但是在地形耗費(fèi)不同的場(chǎng)合,耗費(fèi)最低的路徑也許會(huì)包含很長的移動(dòng)距離-就像沿著路繞過沼澤而不是直接穿過它。
  一種需額外考慮的情況是被專家稱之為“influence mapping”的東西(暫譯為影響映射圖)。就像上面描述的不同地形耗費(fèi)一樣,你可以創(chuàng)建一格額外的分?jǐn)?shù)系統(tǒng),并把它應(yīng)用到尋路的AI中。假設(shè)你有一張有大批尋路者的地圖,他們都要通過某個(gè)山區(qū)。每次電腦生成一條通過那個(gè)關(guān)口的路徑,它就會(huì)變得更擁擠。如果你愿意,你可以創(chuàng)建一個(gè)影響映射圖對(duì)有大量屠殺事件的格子施以不利影響。這會(huì)讓計(jì)算機(jī)更傾向安全些的路徑,并且?guī)椭苊饪偸莾H僅因?yàn)槁窂蕉?/span>(但可能更危險(xiǎn))而持續(xù)把隊(duì)伍和尋路者送到某一特定路徑。

  1. 處理未知區(qū)域:你是否玩過這樣的PC游戲,電腦總是知道哪條路是正確的,即使它還沒有偵察過地圖?對(duì)于游戲,尋路太好會(huì)顯得不真實(shí)。幸運(yùn)的是,這是一格可以輕易解決的問題。

  答案就是為每個(gè)不同的玩家和電腦(每個(gè)玩家,而不是每個(gè)單位--那樣的話會(huì)耗費(fèi)大量的內(nèi)存)創(chuàng)建一個(gè)獨(dú)立的“knownWalkability”數(shù)組,每個(gè)數(shù)組包含玩家已經(jīng)探索過的區(qū)域,以及被當(dāng)作可通過區(qū)域的其他區(qū)域,直到被證實(shí)。用這種方法,單位會(huì)在路的死端徘徊并且導(dǎo)致錯(cuò)誤的選擇直到他們?cè)谥車业铰贰R坏┑貓D被探索了,尋路就像往常那樣進(jìn)行。

  1. 平滑路徑:盡管A*提供了最短,最低代價(jià)的路徑,它無法自動(dòng)提供看起來平滑的路徑。看一下我們的例子最終形成的路徑(在圖7)。最初的一步是起始格的右下方,如果這一步是直接往下的話,路徑不是會(huì)更平滑一些嗎?

  有幾種方法來解決這個(gè)問題。當(dāng)計(jì)算路徑的時(shí)候可以對(duì)改變方向的格子施加不利影響,對(duì)G值增加額外的數(shù)值。也可以換種方法,你可以在路徑計(jì)算完之后沿著它跑一遍,找那些用相鄰格替換會(huì)讓路徑看起來更平滑的地方。想知道完整的結(jié)果,查看 Marco Pinter 發(fā)表在 Gamasutra.com 一篇文章:Toward More Realistic Pathfinding (免費(fèi),但是需要注冊(cè))

  1. 非方形搜索區(qū)域:在我們的例子里,我們使用簡單的2D方形圖。你可以不使用這種方式。你可以使用不規(guī)則形狀的區(qū)域。想想冒險(xiǎn)棋的游戲,和游戲中那些國家。你可以設(shè)計(jì)一個(gè)像那樣的尋路關(guān)卡。為此,你可能需要建立一個(gè)國家相鄰關(guān)系的表格,和從一個(gè)國家移動(dòng)到另一個(gè)的G值。你也需要估算H值的方法。其他的事情就和例子中完全一樣了。當(dāng)你需要向開啟列表中添加新元素的時(shí)候,不需使用相鄰的格子,取而代之的是從表格中尋找相鄰的國家。

  類似的,你可以為一張確定的地形圖創(chuàng)建路徑點(diǎn)系統(tǒng),路徑點(diǎn)一般是路上,或者地牢通道的轉(zhuǎn)折點(diǎn)。作為游戲設(shè)計(jì)者,你可以預(yù)設(shè)這些路徑點(diǎn)。兩個(gè)路徑點(diǎn)被認(rèn)為是相鄰的如果他們之間的直線上沒有障礙的話。在冒險(xiǎn)棋的例子里,你可以保存這些相鄰信息在某個(gè)表格里,當(dāng)需要在開啟列表中添加元素的時(shí)候使用它。然后你就可以記錄關(guān)聯(lián)的G值(可能使用兩點(diǎn)間的直線距離),H值(可以使用到目標(biāo)點(diǎn)的直線距離),其他都按原先的做就可以了。

另一個(gè)在非方形區(qū)域搜索RPG地圖的例子,查看我的文章:Two-Tiered A* Pathfinding

進(jìn)一步的閱讀

  好,現(xiàn)在你對(duì)一些進(jìn)一步的觀點(diǎn)有了初步認(rèn)識(shí)。這時(shí),我建議你研究我的源代碼。包里面包含兩個(gè)版本,一個(gè)是用C++寫的,另一個(gè)用Blitz Basic。順便說一句,兩個(gè)版本都注釋詳盡,容易閱讀,這里是鏈接。

例子代碼:A* Pathfinder (2D) Version 1.71

  如果你既不用C++也不用Blitz Basic,C++版本里有兩個(gè)小的可執(zhí)行文件。Blitz Basic可以在從Blitz Basic網(wǎng)站免費(fèi)下載的 litz Basic 3D(不是Blitz Plus)演示版上運(yùn)行。Ben O''Neill提供一個(gè)聯(lián)機(jī)演示可以在這里找到。

你也該看看以下的網(wǎng)頁。讀了這篇教程后,他們應(yīng)該變得容易理解多了。

  • Amit A* 頁面:這是由Amit Patel制作,被廣泛引用的頁面,如果你沒有事先讀這篇文章,可能會(huì)有點(diǎn)難以理解。值得一看。尤其要看Amit關(guān)于這個(gè)問題的自己的看法。
  • Smart Moves:智能尋路Bryan Stout發(fā)表在Gamasutra.com的這篇文章需要注冊(cè)才能閱讀。注冊(cè)是免費(fèi)的而且比起這篇文章和網(wǎng)站的其他資源,是非常物有所值的。BryanDelphi寫的程序幫助我學(xué)習(xí)A*,也是我的A*代碼的靈感之源。它還描述了A*的幾種變化。
  • 地形分析:這是一格高階,但是有趣的話題,Dave Pottinge撰寫,Ensemble Studios的專家。這家伙參與了帝國時(shí)代和君王時(shí)代的開發(fā)。別指望看懂這里所有的東西,但是這是篇有趣的文章也許會(huì)讓你產(chǎn)生自己的想法。它包含一些對(duì)mip-mappinginfluence mapping以及其他一些高級(jí)AI/尋路觀點(diǎn)。對(duì)"flood filling"的討論使我有了我自己的死端孤島的代碼的靈感,這些包含在我Blitz版本的代碼中。

其它一些值得一看的網(wǎng)站:

其它參考文章:

好了,這就是全部。如果你剛好寫一個(gè)運(yùn)用這些觀點(diǎn)的程序,我想見識(shí)見識(shí)。你可以這樣聯(lián)系我:

現(xiàn)在,好運(yùn)!

 

這是更新版本的:

原文地址: http://zone.emsky.net/?uid-2-action-viewspace-itemid-118

 

題外話

離題一下,見諒,值得一提的是,當(dāng)你在網(wǎng)上或者相關(guān)論壇看到關(guān)于A*的不同的探討,你有時(shí)會(huì)看到一些被當(dāng)作A*算法的代碼而實(shí)際上他們不是。要使用A*,你必須包含上面討論的所有元素--特定的開啟和關(guān)閉列表,用F,GH作路徑評(píng)價(jià)。有很多其他的尋路算法,但他們并不是A*A*被認(rèn)為是他們當(dāng)中最好的。Bryan Stout在這篇文章后面的參考文檔中論述了一部分,包括他們的一些優(yōu)點(diǎn)和缺點(diǎn)。有時(shí)候特定的場(chǎng)合其他算法會(huì)更好,但你必須很明確你在作什么。好了,夠多的了。回到文章。

實(shí)現(xiàn)的注解

現(xiàn)在你已經(jīng)明白了基本原理,寫你的程序的時(shí)候還得考慮一些額外的東西。下面這些材料中的一些引用了我用C++Blitz Basic寫的程序,但對(duì)其他語言寫的代碼同樣有效。

 

1.其他單位(避免碰撞)如果你恰好看了我的例子代碼,你會(huì)發(fā)現(xiàn)它完全忽略了其他單位。我的尋路者事實(shí)上可以相互穿越。取決于具體的游戲,這也許可以,也許不行。如果你打算考慮其他單位,希望他們能互相繞過,我建議你只考慮靜止或那些在計(jì)算路徑時(shí)臨近當(dāng)前單位的單位,把它們當(dāng)前的位置標(biāo)志為可通過的。對(duì)于臨近的運(yùn)動(dòng)著的單位,你可以通過懲罰它們各自路徑上的節(jié)點(diǎn),來鼓勵(lì)這些尋路者找到不同的路徑(更多的描述見#2).

如果你選擇了把其他正在移動(dòng)并且遠(yuǎn)離當(dāng)前尋路單位的那些單位考慮在內(nèi),你將需要實(shí)現(xiàn)一種方法及時(shí)預(yù)測(cè)在何時(shí)何地碰撞可能會(huì)發(fā)生,以便恰當(dāng)?shù)谋苊狻7駝t你極有可能得到一條怪異的路徑,單位突然轉(zhuǎn)彎試圖避免和一個(gè)已經(jīng)不存在的單位發(fā)生碰撞。

當(dāng)然,你也需要寫一些碰撞檢測(cè)的代碼,因?yàn)闊o論計(jì)算的時(shí)候路徑有多完美,它也會(huì)因時(shí)間而改變。當(dāng)碰撞發(fā)生時(shí),一個(gè)單位必須尋找一條新路徑,或者,如果另一個(gè)單位正在移動(dòng)并且不是正面碰撞,在繼續(xù)沿當(dāng)前路徑移動(dòng)之前,等待那個(gè)單位離開。
這些提示大概可以讓你開始了。如果你想了解更多,這里有些你可能會(huì)覺得有用的鏈接:
    *自治角色的指導(dǎo)行為
Craig Reynold在指導(dǎo)能力上的工作和尋路有些不同,但是它可以和尋路整合從而形成更完整的移動(dòng)和碰撞檢測(cè)系統(tǒng)。
    *電腦游戲中的長短距指導(dǎo)
:指導(dǎo)和尋路方面著作的一個(gè)有趣的考察。這是一個(gè)pdf文件。
    *協(xié)同單位移動(dòng)
:一個(gè)兩部分系列文章的第一篇,內(nèi)容是關(guān)于編隊(duì)和基于分組的移動(dòng),作者是帝國時(shí)代(Age of Empires)的設(shè)計(jì)者Dave Pottinger.
    *實(shí)現(xiàn)協(xié)同移動(dòng)
Dave Pottinger文章系列的第二篇。
2.
不同的地形損耗:在這個(gè)教程和我附帶的程序中,地形只能是二者之-可通過的和不可通過的。但是你可能會(huì)需要一些可通過的地形,但是移動(dòng)耗費(fèi)更高-沼澤,小山,地牢的樓梯,等等。這些都是可通過但是比平坦的開闊地移動(dòng)耗費(fèi)更高的地形。類似的,道路應(yīng)該比自然地形移動(dòng)耗費(fèi)更低。

這個(gè)問題很容易解決,只要在計(jì)算任何地形的G值的時(shí)候增加地形損耗就可以了。簡單的給它增加一些額外的損耗就可以了。由于A*算法已經(jīng)按照尋找最低耗費(fèi)的路徑來設(shè)計(jì),所以很容易處理這種情況。在我提供的這個(gè)簡單的例子里,地形只有可通過和不可通過兩種,A*會(huì)找到最短,最直接的路徑。但是在地形耗費(fèi)不同的場(chǎng)合,耗費(fèi)最低的路徑也許會(huì)包含很長的移動(dòng)距離-就像沿著路繞過沼澤而不是直接穿過它。

一種需額外考慮的情況是被專家稱之為“influence mapping”的東西(暫譯為影響映射圖)。就像上面描述的不同地形耗費(fèi)一樣,你可以創(chuàng)建一格額外的分?jǐn)?shù)系統(tǒng),并把它應(yīng)用到尋路的AI中。假設(shè)你有一張有大批尋路者的地圖,他們都要通過某個(gè)山區(qū)。每次電腦生成一條通過那個(gè)關(guān)口的路徑,它就會(huì)變得更擁擠。如果你愿意,你可以創(chuàng)建一個(gè)影響映射圖對(duì)有大量屠殺事件的格子施以不利影響。這會(huì)讓計(jì)算機(jī)更傾向安全些的路徑,并且?guī)椭苊饪偸莾H僅因?yàn)槁窂蕉?/span>(但可能更危險(xiǎn))而持續(xù)把隊(duì)伍和尋路者送到某一特定路徑。

另一個(gè)可能得應(yīng)用是懲罰周圍移動(dòng)單位路徑上得節(jié)點(diǎn)。A*的一個(gè)底限是,當(dāng)一群單位同時(shí)試圖尋路到接近的地點(diǎn),這通常會(huì)導(dǎo)致路徑交疊。以為一個(gè)或者多個(gè)單位都試圖走相同或者近似的路徑到達(dá)目的地。對(duì)其他單位已經(jīng)認(rèn)領(lǐng)了的節(jié)點(diǎn)增加一些懲罰會(huì)有助于你在一定程度上分離路徑,降低碰撞的可能性。然而,如果有必要,不要把那些節(jié)點(diǎn)看成不可通過的,因?yàn)槟闳匀幌M鄠€(gè)單位能夠一字縱隊(duì)通過擁擠的出口。同時(shí),你只能懲罰那些臨近單位的路徑,而不是所有路徑,否則你就會(huì)得到奇怪的躲避行為例如單位躲避路徑上其他已經(jīng)不在那里的單位。 還有,你應(yīng)該只懲罰路徑當(dāng)前節(jié)點(diǎn)和隨后的節(jié)點(diǎn),而不應(yīng)處理已經(jīng)走過并甩在身后的節(jié)點(diǎn)。

3處理未知區(qū)域:你是否玩過這樣的PC游戲,電腦總是知道哪條路是正確的,即使它還沒有偵察過地圖?對(duì)于游戲,尋路太好會(huì)顯得不真實(shí)。幸運(yùn)的是,這是一格可以輕易解決的問題。

答案就是為每個(gè)不同的玩家和電腦(每個(gè)玩家,而不是每個(gè)單位--那樣的話會(huì)耗費(fèi)大量的內(nèi)存)創(chuàng)建一個(gè)獨(dú)立的“knownWalkability”數(shù)組,每個(gè)數(shù)組包含玩家已經(jīng)探索過的區(qū)域,以及被當(dāng)作可通過區(qū)域的其他區(qū)域,直到被證實(shí)。用這種方法,單位會(huì)在路的死端徘徊并且導(dǎo)致錯(cuò)誤的選擇直到他們?cè)谥車业铰贰R坏┑貓D被探索了,尋路就像往常那樣進(jìn)行。

4. 平滑路徑:盡管A*提供了最短,最低代價(jià)的路徑,它無法自動(dòng)提供看起來平滑的路徑。看一下我們的例子最終形成的路徑(在圖7)。最初的一步是起始格的右下方,如果這一步是直接往下的話,路徑不是會(huì)更平滑一些嗎?

有幾種方法來解決這個(gè)問題。當(dāng)計(jì)算路徑的時(shí)候可以對(duì)改變方向的格子施加不利影響,對(duì)G值增加額外的數(shù)值。也可以換種方法,你可以在路徑計(jì)算完之后沿著它跑一遍,找那些用相鄰格替換會(huì)讓路徑看起來更平滑的地方。想知道完整的結(jié)果,查看Toward More Realistic Pathfinding,一篇(免費(fèi),但是需要注冊(cè))Marco Pinter發(fā)表在Gamasutra.com的文章
5.
非方形搜索區(qū)域:在我們的例子里,我們使用簡單的2D方形圖。你可以不使用這種方式。你可以使用不規(guī)則形狀的區(qū)域。想想冒險(xiǎn)棋的游戲,和游戲中那些國家。你可以設(shè)計(jì)一個(gè)像那樣的尋路關(guān)卡。為此,你可能需要建立一個(gè)國家相鄰關(guān)系的表格,和從一個(gè)國家移動(dòng)到另一個(gè)的G值。你也需要估算H值的方法。其他的事情就和例子中完全一樣了。當(dāng)你需要向開啟列表中添加新元素的時(shí)候,不需使用相鄰的格子,取而代之的是從表格中尋找相鄰的國家。

類似的,你可以為一張確定的地形圖創(chuàng)建路徑點(diǎn)系統(tǒng),路徑點(diǎn)一般是路上,或者地牢通道的轉(zhuǎn)折點(diǎn)。作為游戲設(shè)計(jì)者,你可以預(yù)設(shè)這些路徑點(diǎn)。兩個(gè)路徑點(diǎn)被認(rèn)為是相鄰的如果他們之間的直線上沒有障礙的話。在冒險(xiǎn)棋的例子里,你可以保存這些相鄰信息在某個(gè)表格里,當(dāng)需要在開啟列表中添加元素的時(shí)候使用它。然后你就可以記錄關(guān)聯(lián)的G值(可能使用兩點(diǎn)間的直線距離),H值(可以使用到目標(biāo)點(diǎn)的直線距離),其他都按原先的做就可以了。
Amit Patel
寫了其他方法的摘要。另一個(gè)在非方形區(qū)域搜索RPG地圖的例子,查看我的文章Two-Tiered A* Pathfinding(譯者注:譯文:  A*分層尋路)
6.
一些速度方面的提示:當(dāng)你開發(fā)你自己的A*程序,或者改寫我的,你會(huì)發(fā)現(xiàn)尋路占據(jù)了大量的CPU時(shí)間,尤其是在大地圖上有大量對(duì)象在尋路的時(shí)候。如果你閱讀過網(wǎng)上的其他材料,你會(huì)明白,即使是開發(fā)了星際爭霸或帝國時(shí)代的專家,這也無可奈何。如果你覺得尋路太過緩慢,這里有一些建議也許有效:

    * 使用更小的地圖或者更少的尋路者。

    * 不要同時(shí)給多個(gè)對(duì)象尋路。取而代之的是把他們加入一個(gè)隊(duì)列,把尋路過程分散在幾個(gè)游戲周期中。如果你的游戲以40周期每秒的速度運(yùn)行,沒人能察覺。但是當(dāng)大量尋路者計(jì)算自己路徑的時(shí)候,他們會(huì)發(fā)覺游戲速度突然變慢。

盡量使用更大的地圖網(wǎng)格。這降低了尋路中搜索的總網(wǎng)格數(shù)。如果你有志氣,你可以設(shè)計(jì)兩個(gè)或者更多尋路系統(tǒng)以便使用在不同場(chǎng)合,取決于路徑的長度。這也正是專業(yè)人士的做法,用大的區(qū)域計(jì)算長的路徑,然后在接近目標(biāo)的時(shí)候切換到使用小格子/區(qū)域的精細(xì)尋路。如果你對(duì)這個(gè)觀點(diǎn)感興趣,查閱我的文章Two-Tiered A* Pathfinding(譯者注:譯文 :A*分層尋路)

* 使用路徑點(diǎn)系統(tǒng)計(jì)算長路徑,或者預(yù)先計(jì)算好路徑并加入到游戲中。

* 預(yù)處理你的地圖,表明地圖中哪些區(qū)域是不可到達(dá)的。我把這些區(qū)域稱作孤島。事實(shí)上,他們可以是島嶼或其他被墻壁包圍等無法到達(dá)的任意區(qū)域。A*的下限是,當(dāng)你告訴它要尋找通往那些區(qū)域的路徑時(shí),它會(huì)搜索整個(gè)地圖,直到所有可到達(dá)的方格/節(jié)點(diǎn)都被通過開啟列表和關(guān)閉列表的計(jì)算。這會(huì)浪費(fèi)大量的CPU時(shí)間。可以通過預(yù)先確定這些區(qū)域(比如通過flood-fill或類似的方法)來避免這種情況的發(fā)生,用某些種類的數(shù)組記錄這些信息,在開始尋路前檢查它。

    * 在一個(gè)擁擠的類似迷宮的場(chǎng)合,把不能連通的節(jié)點(diǎn)看作死端。這些區(qū)域可以在地圖編輯器中預(yù)先手動(dòng)指定,或者如果你有雄心壯志,開發(fā)一個(gè)自動(dòng)識(shí)別這些區(qū)域的算法。給定死端的所有節(jié)點(diǎn)可以被賦予一個(gè)唯一的標(biāo)志數(shù)字。然后你就可以在尋路過程中安全的忽略所有死端,只有當(dāng)起點(diǎn)或者終點(diǎn)恰好在死端的某個(gè)節(jié)點(diǎn)的時(shí)候才需要考慮它們。

7. 維護(hù)開啟列表:這是A*尋路算法最重要的組成部分。每次你訪問開啟列表,你都需要尋找F值最低的方格。有幾種不同的方法實(shí)現(xiàn)這一點(diǎn)。你可以把路徑元素隨意保存,當(dāng)需要尋找F值最低的元素的時(shí)候,遍歷開啟列表。這很簡單,但是太慢了,尤其是對(duì)長路徑來說。這可以通過維護(hù)一格排好序的列表來改善,每次尋找F值最低的方格只需要選取列表的首元素。當(dāng)我自己實(shí)現(xiàn)的時(shí)候,這種方法是我的首選。

在小地圖。這種方法工作的很好,但它并不是最快的解決方案。更苛求速度的A*程序員使用叫做二叉堆的方法,這也是我在代碼中使用的方法。憑我的經(jīng)驗(yàn),這種方法在大多數(shù)場(chǎng)合會(huì)快23倍,并且在長路經(jīng)上速度呈幾何級(jí)數(shù)提升(10倍以上速度)。如果你想了解更多關(guān)于二叉堆的內(nèi)容,查閱我的文章,Using Binary Heaps in A* Pathfinding(譯者注:譯文:A*尋路中使用二叉堆)

另一個(gè)可能的瓶頸是你在多次尋路之間清除和保存你的數(shù)據(jù)結(jié)構(gòu)的方法。我個(gè)人更傾向把所有東西都存儲(chǔ)在數(shù)組里面。雖然節(jié)點(diǎn)可以以面向?qū)ο蟮娘L(fēng)格被動(dòng)態(tài)的產(chǎn)生,記錄和保存,我發(fā)現(xiàn)創(chuàng)建和刪除對(duì)象所增加的大量時(shí)間,以及多余的管理層次減慢的整個(gè)過程的速度。但是,如果你使用數(shù)組,你需要在調(diào)用之間清理數(shù)據(jù)。這中情形你想做的最后一件事就是在尋路調(diào)用之后花點(diǎn)時(shí)間把一切歸零,尤其是你的地圖很大的時(shí)候。

我通過使用一個(gè)叫做whichList(x,y)的二維數(shù)組避免這種開銷,數(shù)組的每個(gè)元素表明了節(jié)點(diǎn)在開啟列表還是在關(guān)閉列表中。嘗試尋路之后,我沒有清零這個(gè)數(shù)組。取而代之的是,我在新的尋路中重置onClosedListonOpenList的數(shù)值,每次尋路兩個(gè)都+5或者類似其他數(shù)值。這種方法,算法可以安全的跳過前面尋路留下的臟數(shù)據(jù)。我還在數(shù)組中儲(chǔ)存了諸如F,GH的值。這樣一來,我只需簡單的重寫任何已經(jīng)存在的值而無需被清除數(shù)組的操作干擾。將數(shù)據(jù)存儲(chǔ)在多維數(shù)組中需要更多內(nèi)存,所以這里需要權(quán)衡利弊。最后,你應(yīng)該使用你最得心應(yīng)手的方法。

8. Dijkstra的算法:盡管A*被認(rèn)為是通常最好的尋路算法(看前面的題外話”),還是有一種另外的算法有它的可取之處-Dijkstra算法。Dijkstra算法和A*本質(zhì)是相同的,只有一點(diǎn)不同,就是Dijkstra算法沒有啟發(fā)式(H值總是0)。由于沒有啟發(fā)式,它在各個(gè)方向上平均搜索。正如你所預(yù)料,由于Dijkstra算法在找到目標(biāo)前通常會(huì)探索更大的區(qū)域,所以一般會(huì)比A*更慢一些。

那么為什么要使用這種算法呢?因?yàn)橛袝r(shí)候我們并不知道目標(biāo)的位置。比如說你有一個(gè)資源采集單位,需要獲取某種類型的資源若干。它可能知道幾個(gè)資源區(qū)域,但是它想去最近的那個(gè)。這種情況,Dijkstra算法就比A*更適合,因?yàn)槲覀儾恢滥膫€(gè)更近。用A*,我們唯一的選擇是依次對(duì)每個(gè)目標(biāo)許路并計(jì)算距離,然后選擇最近的路徑。我們尋找的目標(biāo)可能會(huì)有不計(jì)其數(shù)的位置,我們只想找其中最近的,而我們并不知道它在哪里,或者不知道哪個(gè)是最近的。

進(jìn)一步的閱讀

好,現(xiàn)在你對(duì)一些進(jìn)一步的觀點(diǎn)有了初步認(rèn)識(shí)。這時(shí),我建議你研究我的源代碼。包里面包含兩個(gè)版本,一個(gè)是用C++寫的,另一個(gè)用Blitz Basic。順便說一句,兩個(gè)版本都注釋詳盡,容易閱讀,這里是鏈接。

* 例子代碼:A* Pathfinder (2D) Version 1.9
如果你既不用C++也不用Blitz Basic,C++版本里有兩個(gè)小的可執(zhí)行文件。Blitz Basic可以在從Blitz Basic網(wǎng)站免費(fèi)下載的Blitz Basic 3D(不是Blitz Plus)演示版上運(yùn)行。Ben O'Neill提供一個(gè)聯(lián)機(jī)演示可以在這里找到。

你也該看看以下的網(wǎng)頁。讀了這篇教程后,他們應(yīng)該變得容易理解多了。

*Amit A* 頁面:這是由Amit Patel制作,被廣泛引用的頁面,如果你沒有事先讀這篇文章,可能會(huì)有點(diǎn)難以理解。值得一看。尤其要看Amit關(guān)于這個(gè)問題的自己的看法

*Smart Moves:智能尋路Bryan Stout發(fā)表在Gamasutra.com的這篇文章需要注冊(cè)才能閱讀。注冊(cè)是免費(fèi)的而且比起這篇文章和網(wǎng)站的其他資源,是非常物有所值的。BryanDelphi寫的程序幫助我學(xué)習(xí)A*,也是我的A*代碼的靈感之源。它還描述了A*的幾種變化。

*地形分析:這是一格高階,但是有趣的話題,Dave Pottinge撰寫,Ensemble Studios的專家。這家伙參與了帝國時(shí)代和君王時(shí)代的開發(fā)。別指望看懂這里所有的東西,但是這是篇有趣的文章也許會(huì)讓你產(chǎn)生自己的想法。它包含一些對(duì)mip-mappinginfluence mapping以及其他一些高級(jí)AI/尋路觀點(diǎn)。對(duì)"flood filling"的討論使我有了我自己的死端孤島的代碼的靈感,這些包含在我Blitz版本的代碼中。

其他一些值得一看的網(wǎng)站:

*aiGuru: Pathfinding

*Game AI Resource: Pathfinding

*GameDev.net: Pathfinding

我同樣高度推薦下面這幾本書, 里面有很多關(guān)于尋路和其他AI話題的文章。 它們也附帶了實(shí)例代碼的CD。這些書我都買了。另外,如果你通過下面的鏈接購買了它們,我會(huì)從Amazon得到幾個(gè)美分。

好了,這就是全部。如果你剛好寫一個(gè)運(yùn)用這些觀點(diǎn)的程序,我想拜讀一下。你可以這樣聯(lián)系我:

現(xiàn)在,好運(yùn)!

posted on 2008-12-01 16:39 漂漂 閱讀(669) 評(píng)論(0)  編輯 收藏 引用 所屬分類: 算法
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美777四色影视在线| 久久久精品日韩欧美| 国产精品青草综合久久久久99| 欧美成黄导航| 欧美日韩午夜视频在线观看| 欧美午夜在线一二页| 国产欧美另类| 亚洲电影免费观看高清完整版在线| 在线观看成人小视频| 亚洲三级网站| 亚洲欧美经典视频| 久久先锋资源| 亚洲精品在线免费观看视频| 久久成人18免费网站| 在线综合视频| 久久精品91久久久久久再现| 美女视频黄 久久| 欧美日韩一区三区| 韩日成人在线| 一区二区欧美激情| 久久精品国产久精国产爱| 欧美激情亚洲国产| 亚洲一区二区三区在线| 久久久久综合网| 欧美午夜宅男影院在线观看| 国内揄拍国内精品久久| 一区二区不卡在线视频 午夜欧美不卡在 | 久久国产福利| 亚洲成人中文| 一区二区三区高清| 久久嫩草精品久久久精品一| 欧美四级在线观看| 亚洲高清久久| 欧美亚洲在线| 日韩天堂av| 男男成人高潮片免费网站| 国产精品午夜在线| 一本不卡影院| 亚洲电影一级黄| 欧美在线视频不卡| 国产精品xxxxx| 日韩午夜激情av| 欧美成人国产| 欧美在线播放| 国产一区二区久久| 久久福利影视| 亚洲欧美激情一区二区| 国产精品成人播放| 99国产精品视频免费观看一公开| 久久精品国产99精品国产亚洲性色 | 久久久久久久精| 亚洲一区欧美一区| 欧美日韩色婷婷| 99精品免费网| 91久久精品美女| 欧美不卡视频一区| 亚洲精品护士| 亚洲黄色免费电影| 另类综合日韩欧美亚洲| 国产免费观看久久黄| 亚洲人成久久| 久久中文久久字幕| 亚洲欧美另类久久久精品2019| 欧美午夜久久久| 一区二区三区四区五区在线| 亚洲精品久久久久久下一站| 免费在线欧美视频| 亚洲精品视频免费| 亚洲精品视频免费观看| 欧美性猛交xxxx乱大交蜜桃| 性8sex亚洲区入口| 欧美一区二区三区四区在线观看| 国产毛片一区二区| 久久亚洲午夜电影| 女女同性女同一区二区三区91| 在线精品国产欧美| 亚洲激情一区二区| 欧美性猛交xxxx乱大交退制版| 欧美亚洲一级片| 久久综合999| 亚洲视频在线免费观看| 亚洲欧美激情视频| 最新中文字幕亚洲| 亚洲香蕉伊综合在人在线视看| 国产欧美丝祙| 亚洲国产mv| 国产精品一二三视频| 久久久www免费人成黑人精品 | 欧美日韩亚洲精品内裤| 亚洲欧美欧美一区二区三区| 性做久久久久久| 亚洲国产精品成人一区二区| 日韩亚洲综合在线| 国产视频观看一区| 亚洲韩国日本中文字幕| 国产欧美日韩精品丝袜高跟鞋| 美女亚洲精品| 国产精品毛片大码女人| 欧美国产精品人人做人人爱| 国产精品高潮粉嫩av| 久久亚洲一区| 欧美午夜一区二区| 欧美黄色网络| 国产欧美日韩另类一区| 亚洲三级免费观看| 狠狠综合久久av一区二区小说| 亚洲欧洲中文日韩久久av乱码| 国产日韩欧美中文在线播放| 91久久国产综合久久91精品网站| 国产一级久久| 亚洲一区二区视频在线| 99热在线精品观看| 另类av一区二区| 久久激情五月婷婷| 欧美特黄一级大片| 亚洲日本欧美在线| 亚洲国产三级| 久久国产66| 欧美在线短视频| 久久久久久日产精品| av成人天堂| 久久久久久午夜| 久久国产精品第一页| 欧美日韩系列| 亚洲人成人一区二区三区| 在线免费观看日韩欧美| 欧美一区二区在线免费观看| 校园春色国产精品| 国产精品天天看| 亚洲一区二区三区乱码aⅴ| 一本高清dvd不卡在线观看| 欧美高清视频一区| 欧美国产第一页| 亚洲欧洲一区二区三区久久| 美女精品在线观看| 欧美黄色影院| 亚洲精品日韩精品| 麻豆freexxxx性91精品| 欧美国产高清| 日韩一级片网址| 欧美日韩免费高清一区色橹橹| 亚洲激情一区二区三区| 亚洲视频精选| 国产欧美一区二区精品秋霞影院| 亚洲视频在线看| 午夜精品久久久久久99热软件 | 国产精品老牛| 小黄鸭视频精品导航| 久久综合精品国产一区二区三区| 国语自产精品视频在线看一大j8| 欧美在线二区| 免费在线视频一区| 日韩视频专区| 国产精品夜夜夜| 久久九九免费| 亚洲国产女人aaa毛片在线| 亚洲午夜未删减在线观看| 国产精品无码永久免费888| 欧美在线观看视频在线| 欧美国产成人精品| 亚洲一区网站| 国内一区二区三区| 欧美理论在线播放| 亚洲在线播放| 欧美激情精品久久久久久免费印度| 亚洲乱码一区二区| 国产精品视频久久一区| 久久天天躁狠狠躁夜夜爽蜜月| 亚洲国产欧美在线| 欧美亚洲免费电影| 最新中文字幕亚洲| 国产日韩一区二区| 欧美理论电影网| 欧美在线首页| 99国产精品一区| 久久伊人精品天天| 亚洲性色视频| 亚洲国产精品免费| 国产精品久久久久久久浪潮网站| 久久国产精品久久久久久久久久| 亚洲国产三级在线| 久久国产精品免费一区| 99精品欧美| 亚洲福利免费| 国产情侣一区| 国产精品国产馆在线真实露脸| 久久久99精品免费观看不卡| 99国产精品久久久| 亚洲国产精品一区二区www| 亚洲欧美视频一区二区三区| 国产伦精品一区二区三区免费迷 | 一区二区三区四区蜜桃| 欧美承认网站| 久久久国产精品一区| 亚洲一区二区三区视频播放| 在线看欧美日韩| 国产亚洲一区二区精品| 国产精品爽黄69| 欧美午夜视频网站| 欧美日韩一区二|