偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

淺談A*算法的一個(gè)C#實(shí)現(xiàn)

開(kāi)發(fā) 后端 算法
最近正在讀云風(fēng)的《游戲之旅》,看著看著就讀到了A*尋路算法,雖然以前沒(méi)有接觸過(guò),但總覺(jué)得好奇。于是從網(wǎng)上找了一些C#實(shí)現(xiàn)資料便開(kāi)始研究。

當(dāng)然,主要參考的算法文檔是“http://www.vckbase.com/document/viewdoc/?id=1422”不過(guò)這里并沒(méi)有給出實(shí)際的源代碼。而搜了一下A*算法的代碼,大都是ActionScript的源碼。畢竟用Flash做一個(gè)Demo會(huì)方便很多。不過(guò)既然都打開(kāi)了VisualStudio,那么就用寫(xiě)一個(gè)C#實(shí)現(xiàn)吧。

A*算法最主要的是對(duì)路徑的評(píng)分函數(shù)。而實(shí)際應(yīng)用時(shí),這個(gè)函數(shù)的設(shè)計(jì)會(huì)產(chǎn)生不同的結(jié)果。從上面的文檔中我們可以很容易地了解到評(píng)分F的公式:

         F = H + G

當(dāng)然根據(jù)文中提到的簡(jiǎn)便方法,我們可以對(duì)H和G的計(jì)算寫(xiě)出下面的代碼。

1private int G(int parent)
2{
3    int d = 10;
4    return d + parent;
5}
6private int H(int x, int y, Point end)
7{
8    return (Math.Abs(x - end.X) + Math.Abs(y - end.Y)) * 10;
9}
為了進(jìn)行尋路的計(jì)算,我們還需要一個(gè)類(lèi)來(lái)保存針對(duì)地圖上某些點(diǎn)遍歷信息的記錄,比如這個(gè)點(diǎn)的F、G、H值各是多少,這個(gè)點(diǎn)的坐標(biāo)以及到達(dá)這個(gè)點(diǎn)的上一個(gè)點(diǎn)的坐標(biāo)。


 1class PathNode : IComparable
 2{
 3    public int G;
 4    public int H;
 5    public int F {
 6        get{
 7            return G + H;
 8        }
 9    }
10
11    public PathNode Parent;
12    public Point Position;
13
14    public PathNode(Point pos)
15    {
16        this.Position = pos;
17        this.Parent = null;
18        this.G = 0;
19        this.H = 0;
20    }
21
22    public override string ToString()
23    {
24        return Position.ToString();
25    }
26
27    IComparable Members#region IComparable Members
28    public int CompareTo(PathNode other)
29    {
30        return F - other.F;
31    }
32    #endregion
33}

PathNode這個(gè)類(lèi)實(shí)現(xiàn)了IComparable接口,目的是為了對(duì)PathNode列表進(jìn)行排序。還記得上面提到的文章中的一句話嗎“尋找開(kāi)啟列表中F值最低的格子。我們稱(chēng)它為當(dāng)前格。”沒(méi)錯(cuò),這就是為這個(gè)條件做的準(zhǔn)備。對(duì)于尋找F值最低的“格子”,把開(kāi)啟列表一排序就OK了。

在實(shí)現(xiàn)實(shí)際的算法時(shí),還需要準(zhǔn)備3個(gè)容器對(duì)象:

private List unLockList = new List();
private Dictionary lockList = new Dictionary();
private List path = new List();


前兩個(gè)是算法中提到的“開(kāi)啟列表”和“關(guān)閉列表”,最后一個(gè)是找到的最終路徑。
最后來(lái)實(shí)現(xiàn)A*算法:

 1public List FindPath()
 2{
 3    unLockList.Clear();
 4    lockList.Clear();
 5    path.Clear();
 6    doFindPath();
 7    path.Reverse();
 8    return path;
 9}
10
11private void doFindPath()
12{
13    PathNode start = new PathNode(Start);
14    PathNode cur = start;
15    while (true)
16    {
17        if(!lockList.ContainsKey(cur.ToString()))
18            lockList.Add(cur.ToString(), cur);
19        for (int i = 0; i < delta.Length; i++)
20        {
21            Point newp = new Point(cur.Position.X + delta[i][0],
22                cur.Position.Y + delta[i][1]);
23            if (!canWalkOnIt(newp))
24                continue;
25            if (lockList.ContainsKey(newp.ToString()))
26                continue;
27            if (isPointInUnlockList(newp))
28            {
29                PathNode ulnode = __pn;
30                int newg = G(cur.G);
31                if (newg < ulnode.G)
32                {
33                    ulnode.Parent = cur;
34                    ulnode.G = newg;
35                }
36                continue;
37            }
38            PathNode newpn = new PathNode(newp);
39            newpn.G = G(cur.G);
40            newpn.H = H(newp.X, newp.Y, End);
41            newpn.Parent = cur;
42            unLockList.Add(newpn);
43        }
44        if (unLockList.Count == 0)
45            break;
46        unLockList.Sort();
47        cur = unLockList[0];
48        unLockList.Remove(cur);
49       
50        if (cur.Position.Equals(End))
51        {
52            while (cur != null)
53            {
54                path.Add(cur);
55                cur = cur.Parent;
56            }
57            break;
58        }
59    }
60}
61
62private PathNode __pn;
63
64private bool isPointInUnlockList(Point src)
65{
66    __pn = null;
67    foreach (PathNode item in unLockList)
68    {
69        if (item.Position.Equals(src))
70        {
71            __pn = item;
72            return true;
73        }
74
75    }
76    return false;
77}
78
79private bool canWalkOnIt(Point node)
80{
81    if (node.X < 0 || node.Y < 0)
82        return false;
83    if (node.X > Width - 1 || node.Y > Height - 1)
84        return false;
85    return GetNodeValue(node.X, node.Y) >= 0;
86}

沒(méi)寫(xiě)什么注釋?zhuān)悸肪褪巧衔闹械摹癆*方法總結(jié)”。在此就不重新粘貼一遍了。在此需要多啰嗦兩句的是,關(guān)閉列表用了一個(gè)Dictionary,其實(shí)關(guān)閉列表的目的就是查找下一個(gè)點(diǎn)是否在關(guān)閉列表當(dāng)中,用Dictionary的ContainsKey方法比較容易,畢竟在Hashtable中找個(gè)Key總比在List中找個(gè)元素要快。

為了簡(jiǎn)化C#實(shí)現(xiàn)算法,這里只是遍歷了當(dāng)前點(diǎn)的上下左右4個(gè)相鄰點(diǎn)。上文中介紹的是遍歷8個(gè)點(diǎn)的情況,不過(guò)這也不是很復(fù)雜,只不過(guò)麻煩點(diǎn)在于G這個(gè)方法,需要判斷一下是不是斜向走的。另外對(duì)4個(gè)相鄰點(diǎn)的遍歷,方法來(lái)源于之前看的一段AS代碼,它用了一個(gè)偏移量數(shù)組來(lái)保存8個(gè)偏移量。而這里只是保存了4個(gè)偏移量。在實(shí)際的算法中,循環(huán)一下偏移量數(shù)組就很方便了(之前見(jiàn)過(guò)一個(gè)代碼并沒(méi)有用這個(gè)方法,而是復(fù)制了8短類(lèi)似的函數(shù)調(diào)用代碼,邏輯上就不如這個(gè)看的清晰)。delta數(shù)組如下:

private int[][] delta = new int[][]{
    new int[]{0,1},
    new int[]{0,-1},
    new int[]{1,0},
    new int[]{-1,0}
};

另一個(gè)C#實(shí)現(xiàn)過(guò)程中需要注意的地方是如果4個(gè)偏移后的新點(diǎn)包含在開(kāi)啟列表中,那么應(yīng)該是對(duì)開(kāi)啟列表中對(duì)應(yīng)的PathNode的G值進(jìn)行更新。如果是重新new一個(gè)新的PathNode,然后再加入開(kāi)啟列表,那么算法就會(huì)出現(xiàn)問(wèn)題,有可能會(huì)陷入無(wú)限循環(huán)。

對(duì)于尋路的結(jié)果獲取無(wú)非就是對(duì)PathNode鏈表中每個(gè)PathNode進(jìn)行遍歷,然后放到一個(gè)List中再Reverse一下。對(duì)于地圖來(lái)說(shuō),這里用的是一個(gè)int數(shù)組,元素小于0的時(shí)候代表不能通過(guò)。而A*算法計(jì)算出的結(jié)果可能并不是最優(yōu)的結(jié)果,不過(guò)其效率還是比較高的,原因在于有了評(píng)分函數(shù)的幫助可以遍歷更少的節(jié)點(diǎn)。

最后,還是貼上整個(gè)Demo項(xiàng)目的文件吧,結(jié)構(gòu)和代碼看起來(lái)可能并不優(yōu)雅。

【編輯推薦】

  1. 為ASP.NET控件加入快捷菜單
  2. 為Asp.net控件寫(xiě)單元測(cè)試(ViewState)
  3. ASP.NET開(kāi)發(fā)程序過(guò)程中值得注意的兩個(gè)地方
  4. ASP.NET、JSP和PHP究竟哪個(gè)好
  5. ASP.NET頁(yè)面請(qǐng)求原理淺析
責(zé)任編輯:彭凡 來(lái)源: cnblogs
相關(guān)推薦

2009-08-31 13:53:03

C#創(chuàng)建一個(gè)文件

2009-06-16 10:20:05

多繼承C#

2009-08-17 17:16:19

C#實(shí)現(xiàn)在線升級(jí)

2024-06-05 08:17:37

C#算法數(shù)據(jù)科學(xué)

2009-07-30 18:18:27

C#時(shí)間計(jì)算

2011-03-29 09:14:49

Dispose模式C#

2009-08-18 17:19:33

C#事件模型

2009-08-20 18:30:33

C# ReaderWr

2011-09-21 10:56:31

C#結(jié)構(gòu)

2009-08-19 14:15:42

C# 復(fù)合控件

2009-09-17 17:13:54

C#數(shù)組

2009-08-14 10:51:43

2009-08-31 14:01:50

C#創(chuàng)建一個(gè)文件

2009-08-26 15:53:42

C#數(shù)據(jù)訪問(wèn)XML

2009-08-25 01:46:00

C# WINDOWS服

2009-09-11 12:17:59

C#控件屬性

2009-08-14 00:55:21

C#程序編譯

2009-08-07 11:26:53

C#數(shù)組結(jié)構(gòu)

2009-08-31 09:37:09

C# Employee

2009-08-12 11:24:25

C# String對(duì)象
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)