7个寻路算法 Dijkstra.h
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