1. 程式人生 > >A* 尋路演算法

A* 尋路演算法

寫在前面

再來填一個坑。之前一直說要寫的A* 終於有空補上了,本篇部落格首先會介紹最基礎的A* 實現,在簡單A* 的基礎上,嘗試實現稍複雜的A* 演算法(帶有高度資訊的地形,允許對角線尋路等)。

A*演算法簡介

本部落格不準備探討A* 演算法的原理,這裡僅僅對A*演算法做一個簡單介紹,對具體原理感興趣的同學請查閱相關資料。

A* 演算法是一種啟發式搜尋演算法。本質上來講,可以算作是廣度優先搜尋演算法的改進。我們知道,廣度優先搜尋總能找到路徑最短的最優解,因為它每次新的一輪遍歷永遠是離起始點最近的位置,這樣,當掃描到目標點時,可以保證目標點的距離是離起點距離最近的,也就是找到了尋路的最優解。

A* 演算法的執行過程與廣度優先搜尋類似,不同的是,A* 除了考慮當前點離起始點的距離外,還考慮了當前點離目標點的距離,我們分別用g和h來表示這兩個距離,由此我們有代價函式f = g+h。A*演算法每次查詢代價最低的點作為搜尋點,並更新搜尋節點列表。最終搜尋到目標位置。可以看到,A* 演算法得到的路徑並不一定最優。

具體的演算法設計

對於每一次搜尋任務,我們維護兩個列表:openList和closeList。 這兩個列表分別存放待訪問的節點和已訪問過的節點。對於每一個迴圈,我們從openlist中取出f最小的點,並檢查它的四鄰域(上下左右四個點),若四鄰域的點中有已經處於openlist中的點,則做更新操作(如果該點新計算的f值比舊的f值更小),若有點處於closeList中,則不做任何操作,若不在以上列表,則計算他們的f值,並放入openList。以此類推,直至到達最終點或openList為空(不存在路徑)。

具體實現(C++11)

以下是用C++ 實現的A*尋路演算法,地圖上為1的點表示可達的點,-1則表示不可達。

#include <iostream>
#include <unordered_map>
#include<vector>
#include<limits.h> 
const int WIDTH = 100;
const int HEIGHT = 100;
using namespace std;
struct Node
{
    Node* parent;
    int _x;
    int _y;
    int f;
    int
g; int h; Node(int x, int y):_x(x),_y(y),parent(nullptr){ g = 0; h = 0; f = g+h; } }; int calculateH(Node* cur,Node* end); vector<Node*> find(Node* start,Node* end, unordered_map<int,unordered_map<int,int>>& mGraph); void check(int x,int y,Node* cur,unordered_map<int,unordered_map<int,Node*>>& openList, unordered_map<int,unordered_map<int,Node*>>& endList,Node* end, unordered_map<int,unordered_map<int,int>>& mGraph); Node* findMin(unordered_map<int,unordered_map<int,Node*>>& openList); int main(int argc, char const *argv[]) { unordered_map<int,unordered_map<int,int>> mGraph; for (int i = 0; i < WIDTH; ++i) { for (int j = 0; j < HEIGHT; ++j) { mGraph[i][j] = 1; } } for(int i = 0;i<25;++i) { mGraph[i][2] = -1; } Node * start = new Node(0,0); Node * end = new Node(10,10); start->h = calculateH(start,end); start->f = start->g+start->h; auto ret = find(start,end,mGraph); for(auto v:ret) { cout<<v->_x<<" "<<v->_y<<endl; } return 0; } vector<Node*> find(Node* start,Node* end, unordered_map<int,unordered_map<int,int>>& mGraph) { if(start->_x == end->_x && start->_y == end->_y) return {}; if(mGraph[start->_x][start->_y]==-1||mGraph[end->_x][end->_y] == -1) { // 起點不可達 return {}; } unordered_map<int,unordered_map<int,Node*>> openList; unordered_map<int,unordered_map<int,Node*>> endList; openList[start->_x][start->_y]=start; vector<pair<int,int>> dirs{{1,0},{-1,0},{0,1},{0,-1}}; bool isFind = false; while(!isFind) { // find min auto minNode = findMin(openList); // four directions if(minNode==nullptr) break; for(auto&val: dirs) { auto nx = val.first+minNode->_x; auto ny = val.second+minNode->_y; if(nx == end->_x&&ny == end->_y) { isFind = true; end->parent = minNode; break; } check(nx,ny,minNode,openList,endList,end,mGraph); } if(isFind) break; endList[minNode->_x][minNode->_y] = minNode; openList[minNode->_x].erase(openList[minNode->_x].find(minNode->_y)); } if(!isFind) return {}; vector<Node*> retVec; auto tmp = end; while(tmp) { retVec.push_back(tmp); tmp = tmp->parent; } reverse(retVec.begin(),retVec.end()); return retVec; } void check(int x,int y,Node* cur,unordered_map<int,unordered_map<int,Node*>>& openList, unordered_map<int,unordered_map<int,Node*>> &endList,Node* end, unordered_map<int,unordered_map<int,int>>& mGraph) { if (x<0||x>=HEIGHT||y<0||y>=WIDTH) { return; } if(mGraph[x][y]==-1) return; if (endList.find(x)!=endList.end()&&endList[x].find(y)!=endList[x].end()) { return; } if(openList.find(x)!=openList.end()&&openList[x].find(y)!=openList[x].end()) { auto t = openList[x][y]; if (cur->g+1+t->h<t->f) { t->g = cur->g+1; t->f = t->g+t->h; t->parent = cur; return; } } Node * newNode = new Node(x,y); newNode->g = cur->g+1; newNode->h = calculateH(newNode,end); newNode->f = newNode->g+newNode->h; openList[x][y] = newNode; newNode->parent = cur; } int calculateH(Node* cur,Node* end) { return (abs(cur->_x-end->_x)+abs(cur->_y-end->_y)); } Node* findMin(unordered_map<int,unordered_map<int,Node*>>& openList) { int minVal = INT_MAX; Node* n = nullptr; for(auto &v:openList) { for(auto&val:v.second) { if(val.second!=nullptr&&val.second->f<minVal) { minVal = val.second->f; n = val.second; } } } return n; }

相關推薦

理解A*演算法過程

   這兩天研究了下 A* 尋路演算法, 主要學習了這篇文章, 但這篇翻譯得不是很好, 我花了很久才看明白文章中的各種指代. 特寫此篇部落格用來總結, 並寫了尋路演算法的程式碼, 覺得有用的同學可以看看. 另外因為圖片製作起來比較麻煩, 所以我用的是原文裡的圖片. &n

淺談遊戲中的A*演算法

本文為銳亞教育原創文章,轉載請註明轉載自銳亞教育 A*尋路 A*演算法基本原理 A*(唸作A星)演算法對初學者來說的確有些難度。本文並不試圖對這個話題作權威性的陳述,取而代之的是描述演算法的原理,使你可以在進一步的閱讀中理解其他相關的資

A*演算法補充知識

A*演算法 輔助知識 unity視覺化輔助工具Gizmos Gizmos.color =Color.red;//設定畫筆的顏色 Gizmos.DrawWireCube(位置,Vector3(長寬高));//畫出一個範圍框: Gizmos.DrawCube(位置,三維屬性長寬高); /

A*演算法之解決目標點不可達問題

在遊戲世界的尋路中,通常會有這樣一種情況:在小地圖上點選目標點時,點選到了障礙物或者建築上,然後遊戲會提示我們目標地點無法到達。玩家必須非常小心的在小地圖上點選目標區域的空白部分,才能移動到目標地點。那麼,有沒有辦法來改進一下這種不友好的體驗呢? 下面給出兩種方法: 最近

A*演算法的優化與改進

提要通過對上一篇A*尋路演算法的學習,我們對A*尋路應該有一定的瞭解了,但實際應用中,需要對演算法進行一些改進和優化。 Iterative Deepening Depth-first search- 迭代深化深度優先搜尋在深度優先搜尋中一個比較坑爹情形就是在搜尋樹的一枝上沒有

第四章 Dijkstra和A*演算法

尋路 尋路希望ai中的角色能夠計算一條從當前位置到目標位置合適的路徑,並且這條路徑能夠儘可能的合理和短。 在我們的ai模型中,尋路在決策和移動之間。遊戲中大多數尋路的實現是基於a星演算法,但是它不能直接使用關卡資料工作,需要轉換成特別的資料結構:有向非負權重

RPG遊戲製作-03-人物行走及A*演算法

在遊戲中,可以控制人物的方法一般有:1.鍵盤 2.虛擬搖桿 3.滑鼠 4.手機觸碰。鍵盤一般是在PC端較為常用,如果在遊戲中使用wasd等操作人物的話,那麼在移植到安卓端時,就需要使用虛擬搖桿或虛擬按鈕來模擬鍵盤,以實現處理的統一性。滑鼠類似於手機的單點觸碰,而手機觸碰一般分

unity中的一個簡單易用的A*演算法

以前專案中用到了尋路,就寫了個A*尋路的演算法類,感覺還不錯,這裡分享出來。A*演算法的原理網上有很多,這裡只簡單說一下我這個演算法的邏輯:*我的這個演算法裡面沒有關閉列表,因為我會根據地圖資料建立一個對應的節點資料的陣列,每個節點資料記錄自己當前的狀態,是開啟還是關閉的。節

一個高效的a *演算法(八方向)

http://blog.csdn.net/onafioo/article/details/41089579 這種寫法比較垃圾,表現在每次搜尋一個點要遍歷整個地圖那麼大的陣列,如果地圖為256 * 256,每次搜尋都要執行65535次,如果遍歷多個點就是n * 65

A* 演算法

寫在前面 再來填一個坑。之前一直說要寫的A* 終於有空補上了,本篇部落格首先會介紹最基礎的A* 實現,在簡單A* 的基礎上,嘗試實現稍複雜的A* 演算法(帶有高度資訊的地形,允許對角線尋路等)。 A*演算法簡介 本部落格不準備探討A* 演算法的原理,這

A*演算法基於C#實現

 玩過即時戰略,RPG等型別的遊戲的朋友一定會知道,當我們用滑鼠選取某些單位並命令其到達地圖上確定的位置時,這些單位總是可以自動的選擇最短的路徑到達。這個時候我們就會聯想到大名鼎鼎的A*尋路演算法,下文簡略介紹演算法實現原理,並附上C#實現方法。using System; u

A*演算法的C++簡單實現

2007/8/13 17:26:59 #include <iostream> #include <ctime> #include <list> #include <algorithm> #include <cassert&

Unity A*演算法(人物移動AI

最近閒來無事,從網上看了一些大神的心得,再融合自己的體會,寫了一個簡單點的尋路演算法,廢話不多說,直接上程式碼 <Grid> usingUnityEngine; usingSystem.Collections; usingS

A*演算法與它的速度

如果你是一個遊戲開發者,或者開發過一些關於人工智慧的遊戲,你一定知道A*演算法,如果沒有接觸過此類的東東,那麼看了這一篇文章,你會對A*演算法從不知道變得了解,從瞭解變得理解。我不是一個純粹的遊戲開發者,我只是因為喜歡而研究,因為興趣而開發,從一些很小的遊戲開始,直到接觸到了

Unity3d利用A*演算法實現模擬

這裡我先引用一篇詳細文章來介紹A*演算法文章內容如下簡易地圖 如圖所示簡易地圖, 其中綠色方塊的是起點 (用 A 表示), 中間藍色的是障礙物, 紅色的方塊 (用 B 表示) 是目的地. 為了可以用一個二維陣列來表示地圖, 我們將地圖劃分成一個個的小方塊.二維陣列在遊戲中的應

js實現A*演算法

js使用canvas繪製介面。 定義兩個類:Node儲存點及A*演算法中的F=G+H值;Point。 /** * 節點 * p : 節點對應的座標 * pn : 節點的父節點 * g : A*-g * h : A*-h */ function Node(p,

A*演算法

#include <stdio.h>#include <stdlib.h>#define hello printf("hello\n");#define hi printf("hi\n");typedef struct NODE node;typede

Unity3D A* 演算法

筆者介紹:姜雪偉,IT公司技術合夥人,IT高階講師,CSDN社群專家,特邀編輯,暢銷書作者,國家專利發明人;已出版書籍:《手把手教你架構3D遊戲引擎》電子工業出版社和《Unity3D實戰核心技術詳解》電子工業出版社等。A*尋路演算法通常是應用於大型網路遊戲中,A*演算法通常應

Unity3d 實現 A * 演算法

原理A* 演算法是一種啟發式搜尋演算法,通過代價函式f = g+h,A*演算法每次查詢代價最低的點作為搜尋點,並更新搜尋節點列表。最終搜尋到目標位置。需要定義兩個列表 (Open和Closed列表):    private List<Tile> openList

A*演算法淺析

http://blog.csdn.net/yiyikela/article/details/46134339 最近剛接觸A*尋路演算法,聽說是一種比較高效的自動尋路的演算法,當然,事實也正是如此,這麼好的東西,自然是要收入囊中的,說不定什麼時候也能派上用場呢。為了學習這