C# A*算法

猫要去骨头的地方

我们使用方块(一个正方形)作为寻路算法的单元

源码

//每个节点

    class NodeData
    {
        public int X;
        public int Y;
        public NodeData preNode;
        public int F;//到目的地估算值
    }

//定义的数据

private int[,] map = new int[8, 9];
private Dictionary<int, NodeData> m_closeNodeDic = new Dictionary<int, NodeData>();
private Dictionary<int, NodeData> m_openNodeDic = new Dictionary<int, NodeData>();

 

//初始化map 以及开始查找

    private void TestAStar()
        {
            //阻挡
            for (int i = 0; i < map.GetLength(0); i++)
            {
                map[i, 0] = -1;
                map[i, map.GetLength(1) -1] = -1;
            }

            for (int i = 0; i < map.GetLength(1); i++)
            {
                map[0, i] = -1;
                map[map.GetLength(0) - 1, i] = -1;
            }

            //固定障碍物
            map[2, 4] = -1;
            map[3, 4] = -1;
            map[4, 4] = -1;
            map[5, 4] = -1;
            map[5, 2] = -1;

            for (int i = 0; i < map.GetLength(0); i++)
            {
                string str = "";
                for (int j = 0; j < map.GetLength(1); j++)
                {
                    if(string.IsNullOrEmpty(str))
                    {
                        str += map[i,j];
                    }
                    else
                    {
                        str += " " + map[i, j];
                    }
                }
                DLogger.Error(str);
            }

            NodeData startNode = new NodeData();
            startNode.X = 4;
            startNode.Y = 2;

            FindPath(map,startNode,3,8);
        }
  private int GetDicKey(int x,int y)
        {
            return x * 10000 + y;
        }

        private int GetH(int curX, int curY, int targetX, int targetY)
        {
            return Mathf.Abs(targetX - curX)*10 + Mathf.Abs(targetY - curY)*10;
        }

        private void AddOpenList(int[,] map, NodeData startNode, int curX, int curY, int targetX, int targetY)
        {
            if (curX < 0 || curY < 0 || curX >= map.GetLength(0) || curY >= map.GetLength(1))
                return;

            //如果是障碍物
            if (map[curX, curY] < 0)
                return;

            if (m_closeNodeDic.ContainsKey(GetDicKey(curX, curY)))
                return;

            int curH = GetH(curX,curY,targetX,targetY);

            int curG = 10;
            NodeData preNode = startNode.preNode;
            while(preNode != null)
            {
                preNode = preNode.preNode;
                curG += 10;
            }
            int curF = curG + curH;
            NodeData nodeData;
            if(m_openNodeDic.TryGetValue(GetDicKey(curX,curY), out nodeData))
            {
                //更新F
                if(nodeData.F < curF)
                {
                    nodeData.preNode = startNode;
                    nodeData.F = curF;
                }
            }
            else
            {
                nodeData = new NodeData();
                nodeData.X = curX;
                nodeData.Y = curY;
                nodeData.preNode = startNode;
                nodeData.F = curF;
                m_openNodeDic.Add(GetDicKey(curX, curY), nodeData);
            }
        }

        private void FindPath(int[,] map,NodeData startNode, int targetX, int targetY)
        {
            m_openNodeDic.Remove(GetDicKey(startNode.X, startNode.Y));
            m_closeNodeDic.Add(GetDicKey(startNode.X, startNode.Y), startNode);

            AddOpenList(map, startNode, startNode.X - 1, startNode.Y,targetX, targetY);
            AddOpenList(map, startNode, startNode.X + 1, startNode.Y, targetX, targetY);
            AddOpenList(map, startNode, startNode.X, startNode.Y - 1, targetX, targetY);
            AddOpenList(map, startNode, startNode.X, startNode.Y + 1, targetX, targetY);

            //检查下是否已经到目的地了
            NodeData targetNode;
            if(m_openNodeDic.TryGetValue(GetDicKey(targetX,targetY), out targetNode))
            {
                while(targetNode.preNode != null)
                {
                    DLogger.Error("X:{0} Y:{1}", targetNode.preNode.X, targetNode.preNode.Y);
                    targetNode = targetNode.preNode;
                }
            }
            else
            {
                //没找到
                if(m_openNodeDic.Count > 0)
                {
                    //找到最小F值的node
                    Dictionary<int, NodeData> open_SortedByF = m_openNodeDic.OrderBy(o => o.Value.F).ToDictionary(p => p.Key, o => o.Value);

                    var itor = open_SortedByF.GetEnumerator();
                    itor.MoveNext();
                    FindPath(map, itor.Current.Value, targetX, targetY);
                }
                else
                {
                    //到不了
                    DLogger.Error("目的地到不了 =================");
                }
            }
        }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
此为用C#写的A*算法源代码 using System; using System.Collections.Generic; using System.Text; using System.Drawing; namespace EtSoft.AStarLib { public class AStar { private StarNodeCollection openList = new StarNodeCollection(); private StarNodeCollection closeList = new StarNodeCollection(); public StarNode currentNode = null; #region 构造函数 /// <summary> /// 使用指定的地图对象、起点和终点初始化A星算法 /// </summary> /// <param name="map">地图对象</param> public AStar(Map map) { this.map = map; } /// <summary> /// /// </summary> /// <param name="map">地图对象</param> /// <param name="start">起点坐标</param> /// <param name="end">终点坐标</param> public AStar(Map map, Point start, Point end) : this(map) { this.start = new StarNode(start); this.end = new StarNode(end); openList.Add(new StarNode(start)); //AddStartNodeToOpenList(this.start); } /// <summary> /// /// </summary> /// <param name="map">地图对象</param> /// <param name="startX">起点X坐标</param> /// <param name="startY">起点Y坐标</param> /// <param name="endX">终点X坐标</param> /// <param name="endY">终点Y坐标</param> public AStar(Map map, int startX, int startY, int endX, int endY) : this(map, new Point(startX, startY), new Point(endX, endY)) { } #endregion #region 属性 protected Map map; /// <summary> /// 地图数据 /// </summary> public Map Map { get { return map; } set { map = value; } } private StarNode start = null; /// <summary> /// 起点坐标,如果没有设置起点,返回null /// </summary> public StarNode Start { get { return start; } set { start = value; openList.Clear(); openList.Add(start); //AddNodeToOpenList(start); } } private StarNode end = null; /// <summary> /// 终点坐标,如果没有设置终点,返回null /// </summary> public StarNode End { get { return end; } set { end = value; } } private StarNodeCollection path; /// <summary> /// 返回路径节点集合,没有路径则返回null /// </summary> public StarNodeCollection Path { get { return path; } } private bool allDirection = false; /// <summary> /// true,允许八方向寻路 /// </summary> public bool AllDirection { get { return allDirection; } set { allDirection = value; } } #endregion /// <summary> /// 开始寻路 /// </summary> public void StartSearchPath() { if (start == null) throw new InvalidNodeException(InvalidNodeTypes.NoStart); if (end == null) throw new InvalidNodeException(InvalidNodeTypes.NoEnd); path = null; openList.Clear(); closeList.Clear(); currentNode = start; SearchPath(currentNode); } //寻路递归,受保护的虚方法,允许在子类重写寻路算法 protected virtual void SearchPath(StarNode starNode) { //currentNode = starNode; openList.Remove(starNode); closeList.Add(starNode); AddNodeToOpenList(); if (closeList.Contains(end)) { //如果终点在关闭列表中,找到路径 StarNode node=starNode.Parent; path = new StarNodeCollection(); do { path.Add(node); node = node.Parent; } while (node != null && !node.Equals(start)); path.Reverse(); return; } else if (openList.Count == 0) { //终点不在关闭列表,开放列表已空,没有可通行的路径 return; } currentNode = GetNextNode(); //迭代过程 SearchPath(currentNode); } /// <summary> /// 获得当前节点的下一个最佳节点 /// </summary> /// <returns></returns> public StarNode GetNextNode() { openList.SortByF(); return openList[0]; } /// <summary> /// 把当前点周围可通过的点加入到开放列表中 /// </summary>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值