1 #ifndef __DIJKSTRA__H
2 #define __DIJKSTRA__H
3
4 #include "AIDefine.h"
5 #include <queue>
6
7 class Dijkstra
8 {
9 private:
10 #define MAXNUM 0x7FFFFFFF
11 public:
12 Dijkstra()
13 {
14 m_nodeArr = NULL;
15 m_able = false;
16 }
17 ~Dijkstra()
18 {
19 if(NULL != m_nodeArr)
20 {
21 delete[] m_nodeArr;
22 m_nodeArr = NULL;
23 }
24 }
25 static bool find(const PointI &size, const PointI &start, const PointI &end, AI_VisitFun visitFun, Path **path = NULL,
26 EFindType findType = EFIND_TYPE8, AI_DitanceFun fun = AI_Ditance1)
27 {
28 Dijkstra dijkstra;
29 if(dijkstra.init(size, end, visitFun, findType, fun))
30 {
31 return dijkstra.findPath(start, path);
32 }
33 if(NULL != path){*path = new Path(false, 0.0f);}
34 return false;
35 }
36 bool init(const PointI &size, const PointI &end, AI_VisitFun visitFun, EFindType findType = EFIND_TYPE8, AI_DitanceFun fun = AI_Ditance1)
37 {
38 if(size.x <= 0 || size.y <= 0 || end.x < 0 || end.y < 0 || end.x >= size.x || end.y >= size.y)
39 {
40 m_able = false;
41 return false;
42 }
43 m_able = true;
44 m_size.x = size.x; m_size.y = size.y;
45 m_end.x = end.x; m_end.y = end.y;
46 if(NULL != m_nodeArr){delete m_nodeArr; m_nodeArr = NULL;}
47 m_nodeArr = new Info[size.x * size.y];
48 Info *cur, *next;
49 PointI pos;
50 int i;
51 PriorityQueue<Info*, InfoCmp> visit;
52 //std::priority_queue<Info*, std::vector<Info*>, InfoCmp> visit;
53 for(i = 0; i < findType; ++i)
54 {
55 pos.x = end.x + AI_FindHelpPoint[i].x;pos.y = end.y + AI_FindHelpPoint[i].y;
56 if(pos.x >= 0 && pos.x <size.x && pos.y >= 0 && pos.y < size.y && AI_CheckPass(end.x, end.y, pos.x, pos.y, visitFun))
57 {
58 cur = &m_nodeArr[pos.y * size.x + pos.x];
59 cur->x = pos.x; cur->y = pos.y;
60 cur->dis = fun(end.x, end.y, cur->x, cur->y);
61 cur->path.x = end.x; cur->path.y = end.y; cur->hasPath = true;
62 visit.push(cur);
63 }
64 }
65 cur = &m_nodeArr[end.y * size.x + end.x];
66 cur->dis = 0; cur->visited = true;
67 cur->path.x = end.x; cur->path.y = end.y; cur->hasPath = true;
68 cur->x = end.x; cur->y = end.y;
69
70 float cost;
71 while(!visit.empty())
72 {
73 cur = visit.top();visit.pop();
74 cur->visited = true;
75 for(i = 0; i < findType; ++i)
76 {
77 pos.x = cur->x + AI_FindHelpPoint[i].x;pos.y = cur->y + AI_FindHelpPoint[i].y;
78 if(pos.x >= 0 && pos.x <size.x && pos.y >= 0 && pos.y < size.y)
79 {
80 next = &m_nodeArr[pos.y * size.x + pos.x];
81 next->x = pos.x; next->y = pos.y;
82 cost = fun(cur->x, cur->y, next->x, next->y);
83 if(!next->visited && AI_CheckPass(cur->x, cur->y, next->x, next->y, visitFun) && cur->dis + cost < next->dis)
84 {
85 next->dis = cur->dis + cost;
86 next->path.x = cur->x; next->path.y = cur->y; next->hasPath = true;
87 visit.push(next);
88 }
89 }
90 }
91 }
92 return true;
93 }
94 bool getDis(const PointI &start, float &dis)
95 {
96 dis = 0;
97 if(m_able)
98 {
99 if(start.x == m_end.x && start.y == m_end.y)
100 {
101 return true;
102 }
103 if(start.x < 0 || start.x >= m_size.x || start.y < 0 || start.y >= m_size.y)
104 {
105 return false;
106 }
107 dis = m_nodeArr[start.y * m_size.x + start.x].dis;
108 return true;
109 }
110 return false;
111 }
112 bool findPath(const PointI &start, Path **path = NULL, bool isStart = true)
113 {
114 bool result = false;
115 if(m_able)
116 {
117 Path *_path = new Path(true, 0.0f);
118 if(start.x == m_end.x && start.y == m_end.y)
119 {
120 if(NULL != path){*path = _path;}else{delete _path;}
121 return true;
122 }
123 Info *cur;
124 _path->push_front(PointI(start.x, start.y));
125 cur = &m_nodeArr[start.y * m_size.x + start.x];
126 _path->setDis(cur->dis);
127 while(cur->hasPath)
128 {
129 if(cur->path.x == m_end.x && cur->path.y == m_end.y)
130 {
131 result = true;
132 break;
133 }
134 if(isStart){_path->push_back(PointI(cur->path.x, cur->path.y));}
135 else{_path->push_front(PointI(cur->path.x, cur->path.y));}
136 cur = &m_nodeArr[cur->path.y * m_size.x + cur->path.x];
137 }
138 if(!result){delete _path; _path = new Path(false, MAXNUM);}
139 else
140 {
141 if(isStart){_path->push_back(PointI(m_end.x, m_end.y));}
142 else{_path->push_front(PointI(m_end.x, m_end.y));}
143 }
144 if(NULL != path){*path = _path;}else{delete _path;}
145 }
146 return result;
147 }
148 private:
149 struct Info
150 {
151 Info():dis(MAXNUM),visited(false), hasPath(false){}
152 int x, y;
153 PointI path;
154 float dis;
155 bool visited;
156 bool hasPath;
157 };
158 struct InfoCmp
159 {
160 bool operator () (const Info *p1, const Info *p2)
161 {
162 return p1->dis < p2->dis;
163 }
164 };
165 private:
166 Info *m_nodeArr;
167 PointI m_size;
168 PointI m_end;
169 bool m_able;
170 };
171
172 #endif