1. 程式人生 > >A*尋路演算法基於C#實現

A*尋路演算法基於C#實現

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            test mytest = new test();

            //定義出發位置
            Point pa = new Point();
            pa.x = 1;
            pa.y = 1;

            //定義目的地
            Point pb = new Point();
            pb.x = 8;
            pb.y = 8;

            mytest.FindWay(pa, pb);

            mytest.PrintMap();
            Console.ReadLine();
        }
    }
    class test
    {
        //陣列用1表示可通過,0表示障礙物
        byte[,] R = new byte[10, 10] { 
            { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
            { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
            { 1, 1, 1, 1, 0, 1, 1, 1, 1, 1 },
            { 1, 1, 1, 1, 0, 1, 1, 1, 1, 1 },
            { 1, 1, 1, 1, 0, 1, 1, 1, 1, 1 },
            { 1, 1, 1, 1, 0, 1, 1, 1, 1, 1 },
            { 1, 1, 1, 1, 0, 1, 1, 1, 1, 1 },
            { 1, 1, 1, 1, 0, 1, 1, 1, 1, 1 },
            { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
            { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }            
            };

        //開啟列表
        List<Point> Open_List = new List<Point>();

        //關閉列表
        List<Point> Close_List = new List<Point>();

        //從開啟列表查詢F值最小的節點
        private Point GetMinFFromOpenList()
        {
            Point Pmin = null;
            foreach (Point p in Open_List) if (Pmin==null || Pmin.G + Pmin.H > p.G + p.H) Pmin = p;
            return Pmin;
        }

        //判斷一個點是否為障礙物
        private bool IsBar(Point p, byte[,] map)
        {
            if (map[p.y, p.x] == 0) return true;
            return false;
        }

        //判斷關閉列表是否包含一個座標的點
        private bool IsInCloseList(int x, int y)
        {
            foreach (Point p in Close_List) if (p.x == x && p.y == y) return true;
            return false;
        }
        //從關閉列表返回對應座標的點
        private Point GetPointFromCloseList(int x, int y)
        {
            foreach (Point p in Close_List) if (p.x == x && p.y == y) return p;
            return null;
        }

        //判斷開啟列表是否包含一個座標的點
        private bool IsInOpenList(int x, int y)
        {
            foreach (Point p in Open_List) if (p.x == x && p.y == y) return true;
            return false;
        }
        //從開啟列表返回對應座標的點
        private Point GetPointFromOpenList(int x, int y)
        {
            foreach (Point p in Open_List) if (p.x == x && p.y == y) return p;
            return null;
        }

        //計算某個點的G值
        private int GetG(Point p)
        {
            if (p.father == null) return 0;
            if (p.x == p.father.x || p.y == p.father.y) return p.father.G + 10;
            else return p.father.G + 14;
        }

        //計算某個點的H值
        private int GetH(Point p, Point pb)
        {
            return Math.Abs(p.x - pb.x) + Math.Abs(p.y - pb.y);
        }

        //檢查當前節點附近的節點
        private void CheckP8(Point p0, byte[,] map, Point pa, ref Point pb)
        {
            for (int xt = p0.x - 1; xt <= p0.x + 1; xt++)
            {
                for (int yt = p0.y - 1; yt <= p0.y + 1; yt++)
                {
                    //排除超過邊界和等於自身的點
                    if ((xt >= 0 && xt < 10 && yt >= 0 && yt < 10) && !(xt == p0.x && yt == p0.y))
                    {
                        //排除障礙點和關閉列表中的點
                        if (map[yt, xt] != 0 && !IsInCloseList(xt, yt))
                        {
                            if (IsInOpenList(xt, yt))
                            {
                                Point pt = GetPointFromOpenList(xt, yt);
                                int G_new = 0;
                                if (p0.x == pt.x || p0.y == pt.y) G_new = p0.G + 10;
                                else G_new = p0.G + 14;
                                if (G_new < pt.G)
                                {
                                    Open_List.Remove(pt);
                                    pt.father = p0;
                                    pt.G = G_new;
                                    Open_List.Add(pt);
                                }
                            }
                            else
                            {
                                //不在開啟列表中
                                Point pt = new Point();
                                pt.x = xt;
                                pt.y = yt;
                                pt.father = p0;
                                pt.G = GetG(pt);
                                pt.H = GetH(pt, pb);
                                Open_List.Add(pt);
                            }
                        }
                    }
                }
            }
        }

        public void FindWay(Point pa, Point pb)
        {
            Open_List.Add(pa);
            while (!(IsInOpenList(pb.x, pb.y) || Open_List.Count == 0))
            {
                Point p0 = GetMinFFromOpenList();
                if (p0 == null) return;
                Open_List.Remove(p0);
                Close_List.Add(p0);
                CheckP8(p0, R, pa, ref pb);
            }

            Point p = GetPointFromOpenList(pb.x, pb.y);
            while (p.father != null)
            {
                p = p.father;
                R[p.y, p.x] = 3;
            }
        }

        public void SaveWay( Point pb)
        {
            Point p = pb;
            while (p.father != null)
            {
                p = p.father;
                R[p.y, p.x] = 3;
            }
        }

        public void PrintMap()
        {
            for (int a = 0; a < 10; a++)
            {
                for (int b = 0; b < 10; b++)
                {
                    if (R[a, b] == 1) Console.Write("█");
                    else if (R[a, b] == 3) Console.Write("★");
                    else if (R[a, b] == 4) Console.Write("○");

                    else Console.Write("  ");
                }
                Console.Write("\n");
            }
        }
    }

    class Point
    {
        public int y;
        public int x;
        public int G;
        public int H;

        public Point()
        {
        }
        public Point(int x0, int y0, int G0, int H0, Point F)
        {
            x = x0;
            y = y0;
            G = G0;
            H = H0;
            father = F;
        }
        public Point father;
    }


}

相關推薦

A*演算法基於C#實現

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

A演算法(遊戲演算法)的C++實現

      先吐槽一句:CODE功能太不給力了,怎麼弄怎麼崩潰,難道是CSDN也被掃黃打非了??? ---------------------------------------------     A星演算法的實現原理看這裡:http://www.cnblogs.com

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

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

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

參考文章: A*尋路演算法是遊戲中常用的AI演算法,這裡用C++簡單實現了一下演算法,便於理解。 搜尋區域 如圖所示簡易地圖, 其中綠色方塊的是起點 (用 A 表示), 中間藍色的是障礙物, 紅色的方塊 (用 B 表示) 是目的地. 為了可以用一個二

[轉] A*算法C++簡單實現

track pos endpoint 障礙 close math.h 不存在 rec 節點 參考文章: http://www.policyalmanac.org/games/aStarTutorial.htm 這是英文原文《A*入門》,最經典的講解,有demo演示 ht

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演算法的Lua實現

A*搜尋演算法俗稱A星演算法。這是一種在圖形平面上,有多個節點的路徑,求出最低通過成本的演算法。 對A星演算法的理解還是要從公式 F = G + H開始:在節點化的地圖上,每一步的操作,使得已走距離 + 距離終點距離最小。具體的實現上是維護一個open表和

Unity3d 實現 A * 演算法

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

javascript實現A*演算法

A*尋路演算法是遊戲中經常用到的一種自動路徑計算演算法,比如連連看、NPC自動巡邏等等。本文章預設使用者已經熟悉A*尋路演算法演算法,不熟悉的可參閱下面連結的文章: 先來看看效果圖: Node 定義尋路過程中的點物件 var Node =

理解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* 演算法的原理,這