A*地图寻路算法实现

上一段时间在学习WPF,用到一位前辈讲解的A*地图算法,于是自己根据算法实现了一下,具体代码如下,可供大家使用,代码大家可以再优化,具体用法就不写了,注释很清楚,另外提供源码下载:http://files.cnblogs.com/wangweixznu/PathFinder.rar 具体算法大家可参考深蓝翻译的http://data.gameres.com/message.asp?TopicID=25439

 

ContractedBlock.gif ExpandedBlockStart.gif Code
  1using System;
  2using System.Collections.Generic;
  3using System.Text;
  4using System.Drawing;
  5
  6namespace PathFinder
  7ExpandedBlockStart.gifContractedBlock.gif{
  8    public class PathFinder
  9ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 10        private PathNode startNode, endNode, currentNode;//开始点、终点、当前节点
 11        private byte[,] map;//矩阵地图0表示可行、1表示障碍物
 12        private List<PathNode> closePath, openPath;//  关闭列表、开启列表
 13        private List<Point> bestPaht;//最终保存最佳路径
 14        private bool findSuccess = false;//是否寻路成功
 15ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 16        /// 开始寻路
 17        /// </summary>
 18        /// <param name="map">二维地图矩阵</param>
 19        /// <param name="startPoint">开始坐标点</param>
 20        /// <param name="endPoint">终点</param>
 21        /// <returns></returns>

 22        public List<Point> FindBestPaht(byte[,] map, Point startPoint, Point endPoint)
 23ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 24            closePath = new List<PathNode>();
 25            openPath = new List<PathNode>();
 26            bestPaht = new List<Point>();
 27            this.map = map;
 28            startNode = new PathNode(startPoint.X, startPoint.Y);
 29            startNode.ParentPoint = new Point(-1-1);
 30            endNode = new PathNode(endPoint.X, endPoint.Y);
 31            currentNode = startNode;//开始节点设置为默认当前节点
 32            currentNode.ParentG = currentNode.G = 0;
 33            openPath.Add(startNode);//添加到开启列表
 34            TryToFindPaht(startNode);//开始寻找路径
 35            if (findSuccess)
 36ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 37                InsertPahtNode(endNode);//如果寻找成功,则从终点开始从关闭列表中把最近路径添加到最佳路径列表
 38                return bestPaht;
 39            }

 40            else
 41                return null;
 42        }

 43ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 44        /// 尝试寻路
 45        /// </summary>
 46        /// <param name="node">开始节点</param>

 47        private void TryToFindPaht(PathNode node)
 48ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 49            if (openPath.Count > 0)
 50ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 51                closePath.Add(openPath[0]);//每次从开启列表中取第一个添加到关闭列表,注意这个列表已经是排序后的,第一个既是F值最小的
 52                openPath.RemoveAt(0);//把该节点从开启列表中移除
 53            }

 54            AddOpenNode(node);//以这个节点为基准,把它四周的节点添加到开启列表中,排除障碍物、已经在开启列表或关闭列表中的
 55           //当目标节点已经在开启列表中时表示寻路成功
 56            if (IsInOpenPaht(endNode))
 57ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 58                closePath.Add(endNode);//将目标节点添到关闭列表中
 59                endNode.ParentPoint = currentNode.Point;//目标节点的父节点为当前节点
 60                findSuccess = true;
 61                return;
 62            }

 63            SortPathByF();//按F值从小到大排序
 64            if (openPath.Count > 0)
 65ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 66                currentNode = openPath[0];//从开启列表中取F值最小的作为当前节点
 67                TryToFindPaht(currentNode);//递归调用,再次寻路
 68            }

 69        }

 70ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 71        /// 把当前节点四周的八个节点尝试全部添加到开启列表中
 72        /// </summary>
 73        /// <param name="node">当前节点</param>

 74        private void AddOpenNode(PathNode node)
 75ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 76            AddOneOpenNode(node.X, node.Y + 1, node.Point);
 77            AddOneOpenNode(node.X, node.Y - 1, node.Point);
 78            AddOneOpenNode(node.X + 1, node.Y, node.Point);
 79            AddOneOpenNode(node.X - 1, node.Y, node.Point);
 80            AddOneOpenNode(node.X - 1, node.Y - 1, node.Point);
 81            AddOneOpenNode(node.X - 1, node.Y + 1, node.Point);
 82            AddOneOpenNode(node.X + 1, node.Y + 1, node.Point);
 83            AddOneOpenNode(node.X + 1, node.Y - 1, node.Point);
 84        }

 85ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 86        /// 添加一个新节点到开启列表中
 87        /// </summary>
 88        /// <param name="x">新节点X坐标</param>
 89        /// <param name="y">新节点Y坐标</param>
 90        /// <param name="point">父节点坐标</param>

 91        private void AddOneOpenNode(int x, int y, Point point)
 92ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 93            PathNode node = new PathNode(x, y);
 94            //添加前提是:x、y在当前地图二维矩阵范围内、且是可行路径、不再关闭列表中也不再开启列表中
 95            if (x >= 0 && y >= 0 && x <= map.GetUpperBound(1&& y <= map.GetUpperBound(0&& map[y, x] == 0 && !IsInClosePaht(node) && !IsInOpenPaht(node))
 96ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 97                node.X = x;
 98                node.Y = y;
 99                node.ParentPoint = point;// 新节点的父节点为当前节点
100                node.ParentG = currentNode.G;//记录新节点的父节点G值、以便与当前节点做比较
101                node.G = (currentNode.X == node.X || currentNode.Y == node.Y ? 10 : 14+ node.ParentG;//当前节点的G值为父节点G值+10(非对角线)或14 (对角线)
102                node.H = 10 * (Math.Abs(endNode.X - node.X) + Math.Abs(endNode.Y - node.Y));//更新H值
103                openPath.Add(node);
104            }

105        }

106ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
107        /// 从关闭列表中,从目标点开始倒着查找所有父节点并将其添加到最佳路径中
108        /// </summary>
109        /// <param name="node"></param>

110        private void InsertPahtNode(PathNode node)
111ExpandedSubBlockStart.gifContractedSubBlock.gif        {
112            bestPaht.Insert(0, node.Point);
113            foreach (PathNode item in closePath)
114ExpandedSubBlockStart.gifContractedSubBlock.gif            {
115                if (item.Point == node.ParentPoint)
116                    InsertPahtNode(item);
117            }

118        }

119ExpandedSubBlockStart.gifContractedSubBlock.gif   /**//// <summary>
120   /// 按F值从小到大排序
121   /// </summary>

122        private void SortPathByF()
123ExpandedSubBlockStart.gifContractedSubBlock.gif        {
124            for (int i = 0; i < openPath.Count; i++)
125ExpandedSubBlockStart.gifContractedSubBlock.gif            {
126                for (int j = 0; j < openPath.Count - i - 1; j++)
127ExpandedSubBlockStart.gifContractedSubBlock.gif                {
128                    if (openPath[j].F > openPath[j + 1].F)
129ExpandedSubBlockStart.gifContractedSubBlock.gif                    {
130                        PathNode temp = openPath[j + 1];
131                        openPath[j + 1= openPath[j];
132                        openPath[j] = temp;
133                    }

134                }

135            }

136        }

137ExpandedSubBlockStart.gifContractedSubBlock.gif    /**//// <summary>
138    /// 判断某个阶段是否在关闭列表中
139    /// </summary>
140    /// <param name="node"></param>
141    /// <returns></returns>

142        private bool IsInClosePaht(PathNode node)
143ExpandedSubBlockStart.gifContractedSubBlock.gif        {
144            foreach (PathNode item in closePath)
145ExpandedSubBlockStart.gifContractedSubBlock.gif            {
146                if (item.X == node.X && item.Y == node.Y)
147                    return true;
148            }

149            return false;
150        }

151ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
152        /// 判断某个节点是否在开启列表中
153        /// </summary>
154        /// <param name="node"></param>
155        /// <returns></returns>

156        private bool IsInOpenPaht(PathNode node)
157ExpandedSubBlockStart.gifContractedSubBlock.gif        {
158            foreach (PathNode item in openPath)
159ExpandedSubBlockStart.gifContractedSubBlock.gif            {
160                if (item.X == node.X && item.Y == node.Y)
161                    return true;
162            }

163            return false;
164        }

165    }

166ExpandedSubBlockStart.gifContractedSubBlock.gif    /**//// <summary>
167    /// 定义节点类
168    /// </summary>

169    public class PathNode
170ExpandedSubBlockStart.gifContractedSubBlock.gif    {
171        public PathNode(int x, int y)
172ExpandedSubBlockStart.gifContractedSubBlock.gif        {
173            this.X = x;
174            this.Y = y;
175        }

176ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
177        /// 节点坐标
178        /// </summary>

179ExpandedSubBlockStart.gifContractedSubBlock.gif        public Point Point get return new Point(X,Y); } }
180ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
181        ///  父节点坐标
182        /// </summary>

183ExpandedSubBlockStart.gifContractedSubBlock.gif        public Point ParentPoint getset; }
184ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
185        /// X坐标点
186        /// </summary>

187ExpandedSubBlockStart.gifContractedSubBlock.gif        public int X getset; }
188ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
189        /// Y坐标点
190        /// </summary>

191ExpandedSubBlockStart.gifContractedSubBlock.gif        public int Y getset; }
192ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
193        /// F值=G+H
194        /// </summary>

195ExpandedSubBlockStart.gifContractedSubBlock.gif        public int F get return G + H; } }
196ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
197        /// G值,即从起始节点到当前节点的距离,直线规定为10,对角线规定为14
198        /// </summary>

199ExpandedSubBlockStart.gifContractedSubBlock.gif        public int G getset; }
200ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
201        /// 从当前节点到目标节点纵向坐标距离和横向坐标距离之和
202        /// </summary>

203ExpandedSubBlockStart.gifContractedSubBlock.gif        public int H getset; }
204ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
205        /// 该节点父节点的G值
206        /// </summary>

207ExpandedSubBlockStart.gifContractedSubBlock.gif        public int ParentG getset; }
208    }

209}

210

 

转载于:https://www.cnblogs.com/wangweixznu/archive/2009/11/22/1608008.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值