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

 

posted @ 2013-11-23 01:38  liusijian  阅读(293)  评论(0编辑  收藏  举报