启发式路径搜索:A*
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.Drawing;
5
using System.Collections;
6
using Zephyr.WorldModel;
7
using Zephyr.DebugTools;
8
9
namespace Zephyr.Utility
10
{
11
public class ZPathFinder
12
{
13
private static ZPathFinder _pathFinder = null;
14
15
private BinaryHeap _opens = new BinaryHeap();
16
private List<ZPFCell> _closeLists = new List<ZPFCell>();
17
18
private static Point[] moves = new Point[] { new Point(0, 1), new Point(1, 0), new Point(0, -1), new Point(-1, 0) };
19
20
public static ZPathFinder Instance
21
{
22
get
23
{
24
if (_pathFinder == null)
25
{
26
_pathFinder = new ZPathFinder();
27
}
28
29
return _pathFinder;
30
}
31
}
32
33
private void reset()
34
{
35
_opens.Clear();
36
_closeLists.Clear();
37
}
38
39
//用二叉堆来实现,提高查找效率
40
private ZPFCell getMinCostZPFCell()
41
{
42
ZPFCell zpfc = _opens.DelMin();
43
44
_closeLists.Add(zpfc);
45
46
return zpfc;
47
}
48
49
public Stack<Point> FindPath(Point origin, Point destination)
50
{
51
//无需移动。
52
if (origin == destination)
53
{
54
ZLogger.Instance.LogError("FindPath find origin = destination");
55
return new Stack<Point>();
56
}
57
//如果目标点是不可达到的。
58
if (ZWorldModel.Instance.Terrain.GetZCell(destination) == null)
59
{
60
ZLogger.Instance.LogError("FindPath can't find path to an unreachable point");
61
return new Stack<Point>();
62
}
63
64
reset();
65
66
ZCell s = ZWorldModel.Instance.Terrain[origin.X, origin.Y];
67
68
//起点
69
ZPFCell oZPFCell = new ZPFCell(ZWorldModel.Instance.Terrain.GetZCell(origin));
70
71
_opens.Add(oZPFCell);
72
73
//终点
74
ZPFCell dZPFCell = null;
75
76
//开始搜索
77
while (_opens.Count > 0)
78
{
79
//得到未探测路径中成本最小的点
80
ZPFCell minCostzpfc = getMinCostZPFCell();
81
82
//找到了目标点。
83
if (minCostzpfc.ZCell.Location == destination)
84
{
85
dZPFCell = minCostzpfc;
86
break;
87
}
88
89
//将成本最小点周围的点添加到未探测路径中去
90
//同时计算成本。
91
foreach (Point movePoint in moves)
92
{
93
Point searchPoint = new Point(minCostzpfc.ZCell.Location.X + movePoint.X,
94
minCostzpfc.ZCell.Location.Y + movePoint.Y);
95
96
ZCell searchZCell = ZWorldModel.Instance.Terrain.GetZCell(searchPoint);
97
98
//这个点是地图上的有效的,并且不在OpenList和CloseList中。
99
if (searchZCell != null && !openListContain(searchPoint) && !closeListContain(searchPoint))
100
{
101
ZPFCell newZPFCell = new ZPFCell(searchZCell);
102
newZPFCell.Pre = minCostzpfc;
103
104
newZPFCell.CostPath = minCostzpfc.CostPath + (int)newZPFCell.ZCell.AreaType;
105
newZPFCell.Cost = newZPFCell.CostPath + heuristic(newZPFCell.ZCell.Location, destination);
106
107
_opens.Add(newZPFCell);
108
}
109
}
110
}
111
112
//返回结果。
113
if (dZPFCell != null)
114
{
115
return dZPFCell.Path;
116
}
117
else
118
{
119
ZLogger.Instance.LogError("PathFinder can't find the way from " + origin + " to " + destination);
120
return new Stack<Point>();
121
}
122
}
123
124
private int heuristic(Point from, Point to)
125
{
126
return ZUtils.GetManhattanDis(from, to);
127
}
128
129
private bool openListContain(Point p)
130
{
131
int len = _opens.Count;
132
133
for (int index = 0; index < len; index++)
134
{
135
if (_opens[index].ZCell.Location == p)
136
{
137
return true;
138
}
139
}
140
141
return false;
142
}
143
144
private bool closeListContain(Point p)
145
{
146
foreach (ZPFCell zpfc in _closeLists)
147
{
148
if (zpfc.ZCell.Location == p)
149
{
150
return true;
151
}
152
}
153
154
return false;
155
}
156
157
158
}
159
}
160
这并不是完整的代码,但是通过看以上代码足以了解AStar算法的实现思想。
2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

如果你对AStar算法不熟悉,参考一下的网址。适合初学者。
http://www.policyalmanac.org/games/aStarTutorial.htm
同时有中文翻译版:http://blog.csdn.net/johncools/archive/2006/03/13/623076.aspx