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