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

6
namespace PathFinder7


{8
public class PathFinder9

{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;//是否寻路成功15

/**//// <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)23

{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)36

{37
InsertPahtNode(endNode);//如果寻找成功,则从终点开始从关闭列表中把最近路径添加到最佳路径列表38
return bestPaht;39
}40
else41
return null;42
}43

/**//// <summary>44
/// 尝试寻路45
/// </summary>46
/// <param name="node">开始节点</param>47
private void TryToFindPaht(PathNode node)48

{49
if (openPath.Count > 0)50

{51
closePath.Add(openPath[0]);//每次从开启列表中取第一个添加到关闭列表,注意这个列表已经是排序后的,第一个既是F值最小的52
openPath.RemoveAt(0);//把该节点从开启列表中移除53
}54
AddOpenNode(node);//以这个节点为基准,把它四周的节点添加到开启列表中,排除障碍物、已经在开启列表或关闭列表中的55
//当目标节点已经在开启列表中时表示寻路成功56
if (IsInOpenPaht(endNode))57

{58
closePath.Add(endNode);//将目标节点添到关闭列表中59
endNode.ParentPoint = currentNode.Point;//目标节点的父节点为当前节点60
findSuccess = true;61
return;62
}63
SortPathByF();//按F值从小到大排序64
if (openPath.Count > 0)65

{66
currentNode = openPath[0];//从开启列表中取F值最小的作为当前节点67
TryToFindPaht(currentNode);//递归调用,再次寻路68
}69
}70

/**//// <summary>71
/// 把当前节点四周的八个节点尝试全部添加到开启列表中72
/// </summary>73
/// <param name="node">当前节点</param>74
private void AddOpenNode(PathNode node)75

{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
}85

/**//// <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)92

{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))96

{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
}106

/**//// <summary>107
/// 从关闭列表中,从目标点开始倒着查找所有父节点并将其添加到最佳路径中108
/// </summary>109
/// <param name="node"></param>110
private void InsertPahtNode(PathNode node)111

{112
bestPaht.Insert(0, node.Point);113
foreach (PathNode item in closePath)114

{115
if (item.Point == node.ParentPoint)116
InsertPahtNode(item);117
}118
}119

/**//// <summary>120
/// 按F值从小到大排序121
/// </summary>122
private void SortPathByF()123

{124
for (int i = 0; i < openPath.Count; i++)125

{126
for (int j = 0; j < openPath.Count - i - 1; j++)127

{128
if (openPath[j].F > openPath[j + 1].F)129

{130
PathNode temp = openPath[j + 1];131
openPath[j + 1] = openPath[j];132
openPath[j] = temp;133
}134
}135
}136
}137

/**//// <summary>138
/// 判断某个阶段是否在关闭列表中139
/// </summary>140
/// <param name="node"></param>141
/// <returns></returns>142
private bool IsInClosePaht(PathNode node)143

{144
foreach (PathNode item in closePath)145

{146
if (item.X == node.X && item.Y == node.Y)147
return true;148
}149
return false;150
}151

/**//// <summary>152
/// 判断某个节点是否在开启列表中153
/// </summary>154
/// <param name="node"></param>155
/// <returns></returns>156
private bool IsInOpenPaht(PathNode node)157

{158
foreach (PathNode item in openPath)159

{160
if (item.X == node.X && item.Y == node.Y)161
return true;162
}163
return false;164
}165
}166

/**//// <summary>167
/// 定义节点类168
/// </summary>169
public class PathNode170

{171
public PathNode(int x, int y)172

{173
this.X = x;174
this.Y = y;175
}176

/**//// <summary>177
/// 节点坐标178
/// </summary>179

public Point Point
{ get
{ return new Point(X,Y); } }180

/**//// <summary>181
/// 父节点坐标182
/// </summary>183

public Point ParentPoint
{ get; set; }184

/**//// <summary>185
/// X坐标点186
/// </summary>187

public int X
{ get; set; }188

/**//// <summary>189
/// Y坐标点190
/// </summary>191

public int Y
{ get; set; }192

/**//// <summary>193
/// F值=G+H194
/// </summary>195

public int F
{ get
{ return G + H; } }196

/**//// <summary>197
/// G值,即从起始节点到当前节点的距离,直线规定为10,对角线规定为14198
/// </summary>199

public int G
{ get; set; }200

/**//// <summary>201
/// 从当前节点到目标节点纵向坐标距离和横向坐标距离之和202
/// </summary>203

public int H
{ get; set; }204

/**//// <summary>205
/// 该节点父节点的G值206
/// </summary>207

public int ParentG
{ get; set; }208
}209
}210

浙公网安备 33010602011771号