7个寻路算法 BStar.h
1 #ifndef __BSTAR__H 2 #define __BSTAR__H 3 4 #include "AIDefine.h" 5 #include <vector> 6 7 class BStar 8 { 9 private: 10 BStar(); 11 public: 12 static bool find(const PointI &size, const PointI &start, const PointI &end, AI_VisitFun visitFun, Path **path = NULL) 13 { 14 if(size.x <= 0 || size.y <= 0 || start.x < 0 || start.y < 0 || end.x < 0 || end.y < 0 || 15 start.x >= size.x || start.y >= size.y || end.x >= size.x || end.y >= size.y || 16 !visitFun(start.x, start.y), !visitFun(end.x, end.y)) 17 { 18 if(NULL != path){*path = new Path(false, 0.0f);} 19 return false; 20 } 21 if(start.x == end.x && start.y == end.y) 22 { 23 if(NULL != path){*path = new Path(true, 0.0f);} 24 return true; 25 } 26 27 EDIRTYPE curDir = DIR_LEFT, nextDir = DIR_NONE; 28 if(AI_ABS(end.x - start.x) >= AI_ABS(end.y - start.y)) 29 { 30 if(end.x > start.x){curDir = DIR_RIGHT;} 31 else{curDir = DIR_LEFT;} 32 }else 33 { 34 if(end.y > start.y){curDir = DIR_DOWN;} 35 else{curDir = DIR_UP;} 36 } 37 38 std::vector<Info*> visit; 39 std::vector<Info*>::iterator iter; 40 Info *nodeArr = new Info[size.x * size.y]; 41 Info *cur, *next; 42 PointI pos; 43 44 cur = &nodeArr[size.x * start.y + start.x]; 45 cur->x = start.x; cur->y = start.y; cur->visited = true;cur->dir = curDir; 46 visit.push_back(cur); 47 48 while(!visit.empty()) 49 { 50 iter = visit.end(); --iter; cur = *iter;curDir = cur->dir; 51 if(cur->x == end.x && cur->y == end.y) 52 { 53 if(NULL != path) 54 { 55 *path = new Path(true, 0.0f); 56 for(iter = visit.begin(); iter != visit.end(); ++iter) 57 { 58 (*path)->push_back(PointI((*iter)->x, (*iter)->y)); 59 } 60 } 61 if(NULL != nodeArr){delete[] nodeArr;} 62 return true; 63 } 64 if(DIR_LEFT == curDir){pos.x = cur->x - 1;pos.y = cur->y;} 65 else if(DIR_RIGHT == curDir){pos.x = cur->x + 1;pos.y = cur->y;} 66 else if(DIR_DOWN == curDir){pos.x = cur->x;pos.y = cur->y + 1;} 67 else if(DIR_UP == curDir){pos.x = cur->x;pos.y = cur->y - 1;} 68 if(AI_CheckRange(pos,size) && !nodeArr[size.x * pos.y + pos.x].visited && visitFun(pos.x, pos.y)) 69 { 70 next = &nodeArr[size.x * pos.y + pos.x]; 71 next->x = pos.x; next->y = pos.y; next->visited = true;next->dir = curDir; 72 visit.push_back(next); 73 if(DIR_LEFT == curDir || DIR_RIGHT == curDir) 74 { 75 if(next->x == end.x) 76 { 77 if(end.y >= cur->y) 78 { 79 pos.x = cur->x; pos.y = cur->y + 1; 80 if(AI_CheckRange(pos,size) && !nodeArr[size.x * pos.y + pos.x].visited && visitFun(pos.x, pos.y)) 81 { 82 next->dir = curDir = DIR_DOWN; 83 } 84 }else 85 { 86 pos.x = cur->x; pos.y = cur->y - 1; 87 if(AI_CheckRange(pos,size) && !nodeArr[size.x * pos.y + pos.x].visited && visitFun(pos.x, pos.y)) 88 { 89 next->dir = curDir = DIR_UP; 90 } 91 } 92 } 93 }else if(DIR_DOWN == curDir || DIR_UP == curDir) 94 { 95 if(next->y == end.y) 96 { 97 if(end.x >= cur->x) 98 { 99 pos.x = cur->x + 1; pos.y = cur->y; 100 if(AI_CheckRange(pos,size) && !nodeArr[size.x * pos.y + pos.x].visited && visitFun(pos.x, pos.y)) 101 { 102 next->dir = curDir = DIR_RIGHT; 103 } 104 }else 105 { 106 pos.x = cur->x - 1; pos.y = cur->y; 107 if(AI_CheckRange(pos,size) && !nodeArr[size.x * pos.y + pos.x].visited && visitFun(pos.x, pos.y)) 108 { 109 next->dir = curDir = DIR_LEFT; 110 } 111 } 112 } 113 } 114 }else 115 { 116 if(DIR_LEFT == curDir || DIR_RIGHT == curDir) 117 { 118 if(end.y >= cur->y) 119 { 120 pos.x = cur->x; pos.y = cur->y + 1;nextDir = DIR_DOWN; 121 if(!AI_CheckRange(pos,size) || nodeArr[size.x * pos.y + pos.x].visited || !visitFun(pos.x, pos.y)) 122 { 123 pos.x = cur->x; pos.y = cur->y - 1;nextDir = DIR_UP; 124 } 125 }else 126 { 127 pos.x = cur->x; pos.y = cur->y - 1;nextDir = DIR_UP; 128 if(!AI_CheckRange(pos,size) || nodeArr[size.x * pos.y + pos.x].visited || !visitFun(pos.x, pos.y)) 129 { 130 pos.x = cur->x; pos.y = cur->y + 1;nextDir = DIR_DOWN; 131 } 132 } 133 }else if(DIR_DOWN == curDir || DIR_UP == curDir) 134 { 135 if(end.x >= cur->x) 136 { 137 pos.x = cur->x + 1; pos.y = cur->y;nextDir = DIR_RIGHT; 138 if(!AI_CheckRange(pos,size) || nodeArr[size.x * pos.y + pos.x].visited || !visitFun(pos.x, pos.y)) 139 { 140 pos.x = cur->x - 1; pos.y = cur->y;nextDir = DIR_LEFT; 141 } 142 }else 143 { 144 pos.x = cur->x - 1; pos.y = cur->y;nextDir = DIR_LEFT; 145 if(!AI_CheckRange(pos,size) || nodeArr[size.x * pos.y + pos.x].visited || !visitFun(pos.x, pos.y)) 146 { 147 pos.x = cur->x + 1; pos.y = cur->y;nextDir = DIR_RIGHT; 148 } 149 } 150 } 151 if(!AI_CheckRange(pos,size) || nodeArr[size.x * pos.y + pos.x].visited || !visitFun(pos.x, pos.y)) 152 { 153 visit.pop_back(); 154 }else 155 { 156 next = &nodeArr[size.x * pos.y + pos.x]; 157 next->x = pos.x; next->y = pos.y; next->visited = true;next->dir = nextDir; 158 visit.push_back(next); 159 } 160 } 161 } 162 if(NULL != path){*path = new Path(false, 0.0f);} 163 if(NULL != nodeArr){delete[] nodeArr;} 164 return false; 165 } 166 private: 167 enum EDIRTYPE 168 { 169 DIR_NONE, 170 DIR_LEFT, 171 DIR_RIGHT, 172 DIR_UP, 173 DIR_DOWN 174 }; 175 struct Info 176 { 177 Info():visited(false),x(0),y(0),dir(DIR_NONE){} 178 bool visited; 179 int x,y; 180 EDIRTYPE dir; 181 }; 182 }; 183 184 #endif