AStar 尋路算法

A*(A-Star)算法是一種靜態(tài)路網(wǎng)中求解最短路最有效的直接搜索方法煎娇。

注意是最有效的直接搜索算法。之后涌現(xiàn)了很多預(yù)處理算法(ALT,CH缸血,HL等等),在線查詢效率是A*算法的數(shù)千甚至上萬倍械筛。

公式表示為:f(n)=g(n)+h(n)

其中f(n)是從初始點經(jīng)由節(jié)點n到目標(biāo)點的估價函數(shù)属百,

g(n)是在狀態(tài)空間中從初始節(jié)點到n節(jié)點的實際代價,

h(n)是從n到目標(biāo)節(jié)點最佳路徑的估計代價变姨。

保證找到最短路徑(最優(yōu)解的)條件族扰,關(guān)鍵在于估價函數(shù)f(n)的選取:

估價值h(n)<= n到目標(biāo)節(jié)點的距離實際值,這種情況下渔呵,搜索的點數(shù)多怒竿,搜索范圍大,效率低扩氢。但能得到最優(yōu)解耕驰。并且如果h(n)=d(n),即距離估計h(n)等于最短距離录豺,那么搜索將嚴(yán)格沿著最短路徑進(jìn)行朦肘,此時的搜索效率是最高的。

如果估價值>實際值,搜索的點數(shù)少双饥,搜索范圍小媒抠,效率高,但不能保證得到最優(yōu)解咏花。

using System;

usingSystem.Collections;

using System.Collections.Generic;

usingUnityEngine;

public enumGridType

{

Normal,//正常

Obstacle,//障礙物

Start,//起點

End//終點

}

//為了格子排序需要繼承IComparable接口實現(xiàn)排序

public class

MapGrid : IComparable//排序接口

{

public int x;//記錄坐標(biāo)

public int y;

public int f;//總消耗

public int g;//當(dāng)前點到起點的消耗

public int h;//當(dāng)前點到終點的消耗

public GridType type;//格子類型

public MapGrid fatherNode;//父節(jié)點

//排序

public int CompareTo(object obj)//排序比較方法ICloneable的方法

{

//升序排序

MapGrid grid = (MapGrid)obj;

if (this.f < grid.f)

{

return -1;//升序

}

if (this.f > grid.f)

{

return 1;//降序

}

return 0;

}

}

public classAStar : MonoBehaviour

{

//格子大小

public int row = 5;

public int col = 10;

public int size = 70;//格子大小

public MapGrid[,] grids;//格子數(shù)組

public ArrayList openList;//開啟列表

public ArrayList closeList;//結(jié)束列表

//開始,結(jié)束點位置

private int xStart = 2;

private int yStart = 1;

private int xEnd = 2;

private int yEnd = 5;

private StackfatherNodeLocation;

void Init()

{

grids = new MapGrid[row, col];//初始化數(shù)組

for (int i = 0; i < row; i++)

{

for (int j = 0; j < col;j++)

{

grids[i, j] = newMapGrid();

grids[i, j].x = i;

grids[i, j].y = j;//初始化格子,記錄格子坐標(biāo)

}

}

grids[xStart, yStart].type =GridType.Start;

grids[xStart, yStart].h =Manhattan(xStart, yStart);//起點的h值

grids[xEnd, yEnd].type =GridType.End;//結(jié)束點

fatherNodeLocation = newStack();

//生成障礙物

for (int i = 1; i <= 3; i++)

{

grids[i, 3].type =GridType.Obstacle;

}

openList = new ArrayList();

openList.Add(grids[xStart,yStart]);

closeList = new ArrayList();

}

int Manhattan(int x, int y)//計算算法中的h

{

return (int)(Mathf.Abs(xEnd - x) +Mathf.Abs(yEnd - y)) * 10;

}

// Use this for initialization

void Start()

{

Init();

}

void DrawGrid()

{

for (int i = 0; i < row; i++)

{

for (int j = 0; j < col;j++)

{

Color color =Color.yellow;

if (grids[i, j].type== GridType.Start)

{

color =Color.green;

}

else if (grids[i, j].type== GridType.End)

{

color =Color.red;

}

else if (grids[i,j].type == GridType.Obstacle)//障礙顏色

{

color =Color.blue;

}

else if(closeList.Contains(grids[i, j]))//關(guān)閉列表顏色如果當(dāng)前點包含在closList里

{

color = Color.yellow;

}

else { color =Color.gray; }

GUI.backgroundColor= color;

GUI.Button(newRect(j * size, i * size, size, size), FGH(grids[i, j]));

}

}

}

//每個格子顯示的內(nèi)容

string FGH(MapGrid grid)

{

string str = "F" +grid.f + "\n";

str += "G" + grid.g +"\n";

str += "H" + grid.h +"\n";

str += "(" + grid.x +"," + grid.y + ")";

return str;

}

void OnGUI()

{

DrawGrid();

for (int i = 0; i

{

//生成一個空行,存放開啟數(shù)組

GUI.Button(new Rect(i *size, (row + 1) * size, size, size), FGH((MapGrid)openList[i]));

}

//生成一個空行,存放關(guān)閉數(shù)組

for (int j = 0; j

{

GUI.Button(new Rect(j *size, (row + 2) * size, size, size), FGH((MapGrid)closeList[j]));

}

if (GUI.Button(new Rect(col *size, size, size, size), "next"))

{

NextStep();//點擊到下一步

}

}

void NextStep()

{

if (openList.Count == 0)//沒有可走的點

{

print("Over !");

return;

}

MapGrid grid =(MapGrid)openList[0];//取出openList數(shù)組中的第一個點

if (grid.type == GridType.End)//找到終點

{

print("Find");

ShowFatherNode(grid);//找節(jié)點//打印路線

return;

}

for (int i = -1; i <= 1; i++)

{

for (int j = -1; j <= 1;j++)

{

if (!(i == 0&& j == 0))

{

int x =grid.x + i;

int y =grid.y + j;

//x,y不超過邊界,不是障礙物,不在closList里面

if (x >= 0&& x < row && y >= 0 && y < col &&grids[x, y].type != GridType.Obstacle && !closeList.Contains(grids[x,y]))

{

//到起點的消耗

int g= grid.g + (int)(Mathf.Sqrt((Mathf.Abs(i) + Mathf.Abs(j))) * 10);

if (grids[x, y].g == 0 || grids[x, y].g > g)

{

grids[x,y].g = g;

grids[x,y].fatherNode = grid;//更新父節(jié)點

}

//到終點的消耗

grids[x,y].h = Manhattan(x, y);

grids[x,y].f = grids[x, y].g + grids[x, y].h;

if (!openList.Contains(grids[x,y]))

{

openList.Add(grids[x,y]);//如果沒有則加入到openlist

}

openList.Sort();//排序

}

}

}

}

//添加到關(guān)閉數(shù)組

closeList.Add(grid);

//從open數(shù)組刪除

openList.Remove(grid);

}

//回溯法遞歸父節(jié)點

void ShowFatherNode(MapGrid grid)

{

if (grid.fatherNode != null)

{

//print(grid.fatherNode.x +"," + grid.fatherNode.y);

string str =grid.fatherNode.x + "," + grid.fatherNode.y;

fatherNodeLocation.Push(str);

ShowFatherNode(grid.fatherNode);

}

if (fatherNodeLocation.Count!=0)

{

print(fatherNodeLocation.Pop());

}

}

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末趴生,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子昏翰,更是在濱河造成了極大的恐慌苍匆,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件棚菊,死亡現(xiàn)場離奇詭異浸踩,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)统求,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進(jìn)店門民轴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人球订,你說我怎么就攤上這事后裸。” “怎么了冒滩?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵微驶,是天一觀的道長。 經(jīng)常有香客問我开睡,道長因苹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任篇恒,我火速辦了婚禮扶檐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘胁艰。我一直安慰自己款筑,他們只是感情好智蝠,可當(dāng)我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著奈梳,像睡著了一般杈湾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上攘须,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天漆撞,我揣著相機(jī)與錄音,去河邊找鬼于宙。 笑死浮驳,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的捞魁。 我是一名探鬼主播至会,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼署驻!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起健霹,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤旺上,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后糖埋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宣吱,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年瞳别,在試婚紗的時候發(fā)現(xiàn)自己被綠了征候。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡祟敛,死狀恐怖疤坝,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情馆铁,我是刑警寧澤跑揉,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站埠巨,受9級特大地震影響历谍,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜辣垒,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一望侈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧勋桶,春花似錦脱衙、人聲如沸侥猬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽陵究。三九已至,卻和暖如春奥帘,著一層夾襖步出監(jiān)牢的瞬間铜邮,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工寨蹋, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留松蒜,地道東北人。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓已旧,卻偏偏與公主長得像秸苗,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子运褪,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,969評論 2 355

推薦閱讀更多精彩內(nèi)容