A*与二叉堆结合

        把昨天的A*用C++类封装了下,然后用open表用二叉堆,效率上比SORT快,参照的是<在A*寻路中使用二叉堆
>,效率快了不少,我用70*70的地图测试,昨天的sort时间609ms,今天的94ms.

        我还添加了4个方向或者8方向,一般4方向现在没用了,效率低很多,还加了个在障碍物是否拐角绕开,效率影响不大.然后为了A*类能在后面中重复利用,在判断地图格子是否可通时,继承接口类实现IsObstruction(int r,int c),可根据不同地图存储信息判断障碍物,在游戏里也不需要改变地图数据结构.还加了个地图移动成本,也通过上面接口类实现.效率上会有所降低.

        二叉堆中存储的是节点,包含6个int,如果改成单独int索引,在交换数据时会快点点吧.

  1. //CAStarFindPath.h
  2. #pragma once
  3. #include 
  4. #include 
  5. #include "BinaryHeap.h"
  6. class IMapData  //需要实现的地图数据接口       
  7. {
  8. public:
  9.     //该格子是否障碍物 能否通过 true是障碍物不能通过
  10.     virtual bool IsObstruction(int r,int c)=0;  
  11.     virtual int GetMapCost(int r,int c)//格子地图成本 不需要时返回1
  12.     {
  13.         return 1;
  14.     }
  15. };
  16. class CAStarFindPath //A*类
  17. {
  18. public:
  19.     CAStarFindPath(void);
  20. public:
  21.     ~CAStarFindPath(void);
  22. private:
  23.     int m_R,m_C;    //行列
  24.     int m_srcR,m_srcC,m_desR,m_desC;    //源 目的
  25.     bool m_turnCorner;      //是否绕过拐角
  26.     bool m_eight;           //4方向和8方向扩展
  27.     bool m_cost;            //地图成本
  28.     CBinaryHeap openList;   //open表
  29.     std::vector closeList;    //close表
  30.     std::vector bestList;    //最短路径表
  31.     IMapData *m_Map;
  32. public:
  33.     void SetMapSize(int sizeR,int sizeC,IMapData *mapData); //设置地图大小和地图数据接口
  34.     void SetMapCost(bool cost=false);   //地图成本开销 默认关
  35.     void SetCorner(bool eight=true,bool turn=false);            //设置4或8个方向 拐角默认关
  36.     bool FindPath(int beginR,int beginC,int endR,int endC); //寻找路径无路径时返回false
  37.     std::vector GetPath(void);   //获取路径
  38.     int GetStepNum();   //获取步长
  39. private:
  40.     void KuoZhan(Node &node);   //扩展新节点
  41.     bool IsReach(int r,int c);  //是否可到通过
  42.     int GetCost(int r,int c);//获取地图成本
  43.     void Generate(Node &node,int r,int c);  //产生新节点
  44.     bool Check(Node &value);        //是否重复
  45.     bool DaYu(Node & l,Node & r);   //大于比较
  46.     void Init(Node &start);     //初始
  47.     void BestPath(Node &best);  //最优路径
  48.     int ABS(int a,int b)
  49.     {
  50.         return a>b?(a-b):(b-a);
  51.     }
  52. };
    1. //CAStarFindPath.cpp
    2. #include "AStarFindPath.h"
    3. using namespace std;
    4. CAStarFindPath::CAStarFindPath(void)
    5. {
    6. }
    7. CAStarFindPath::~CAStarFindPath(void)
    8. {
    9. }
    10. void CAStarFindPath::SetMapSize(int sizeR,int sizeC,IMapData *mapData)
    11. {
    12.     m_R=sizeR,m_C=sizeC;
    13.     m_Map=mapData;
    14. }
    15. void CAStarFindPath::SetMapCost(bool cost)
    16. {
    17.     m_cost=cost;
    18. }
    19. void CAStarFindPath::SetCorner(bool eight,bool turn)
    20. {
    21.     m_eight=eight;
    22.     m_turnCorner=turn;
    23. }
    24. bool CAStarFindPath::FindPath(int sr,int sc,int dr,int dc)
    25. {
    26.     m_srcR=sr,m_srcC=sc,m_desR=dr,m_desC=dc;
    27.     Node temp,best;
    28.     temp.r=sr;
    29.     temp.c=sc;
    30.     temp.g=0;
    31.     temp.h=ABS(m_srcR,m_desR)+ABS(m_srcC,m_desC);
    32.     temp.f=temp.g+temp.h;
    33.     temp.parent=-1;
    34.     Init(temp);
    35.     while (!openList.Empty())
    36.     {
    37.         openList.Top(best);
    38.         openList.Pop();
    39.         if (best.r==dr&&best.c==dc)//找到
    40.         {
    41.             BestPath(best);
    42.             return true;
    43.         }
    44.         KuoZhan(best);
    45.         closeList.push_back(best);
    46.     }
    47.     //没路径
    48.     bestList.clear();
    49.     return false;
    50. }
    51. vector CAStarFindPath::GetPath(void)
    52. {
    53.     return bestList;
    54. }
    55. int CAStarFindPath::GetStepNum()
    56. {
    57.     return bestList.size();
    58. }
    59. void CAStarFindPath::KuoZhan(Node &node)
    60. {
    61.     bool flag[4]={true,true,true,true};
    62.     if (IsReach(node.r-1,node.c))// 上 
    63.     {
    64.         Generate(node,node.r-1,node.c);
    65.     }
    66.     else 
    67.     {
    68.         flag[0]=false,flag[1]=false;
    69.     }
    70.     if (IsReach(node.r,node.c+1))//右
    71.     {
    72.         Generate(node,node.r,node.c+1);
    73.     }
    74.     else 
    75.     {
    76.         flag[1]=false,flag[2]=false;
    77.     }
    78.     if (IsReach(node.r+1,node.c))// 下
    79.     {
    80.         Generate(node,node.r+1,node.c);
    81.     }
    82.     else 
    83.     {
    84.         flag[2]=false,flag[3]=false;
    85.     }
    86.     if (IsReach(node.r,node.c-1))// 左 
    87.     {
    88.         Generate(node,node.r,node.c-1);
    89.     }
    90.     else 
    91.     {
    92.         flag[3]=false,flag[0]=false;
    93.     }
    94.     if (!m_eight)
    95.     {
    96.         return;
    97.     }
    98.     if (!m_turnCorner)
    99.     {
    100.         for(int i=0;i<4;i++)
    101.             flag[i]=true;
    102.     }
    103.     if (flag[0]&&IsReach(node.r-1,node.c-1))// 左上 
    104.     {
    105.         Generate(node,node.r-1,node.c-1);
    106.     }
    107.     if (flag[1]&&IsReach(node.r-1,node.c+1))//右上
    108.     {
    109.         Generate(node,node.r-1,node.c+1);
    110.     }
    111.     if (flag[2]&&IsReach(node.r+1,node.c+1))// 右下
    112.     {
    113.         Generate(node,node.r+1,node.c+1);
    114.     }
    115.     if (flag[3]&&IsReach(node.r+1,node.c-1))// 左下 
    116.     {
    117.         Generate(node,node.r+1,node.c-1);
    118.     }
    119. }
    120. bool CAStarFindPath::IsReach(int r,int c)
    121. {
    122.     if (m_Map->IsObstruction(r,c)||r<0||c<0||r>m_R||c>m_C)
    123.         return false;
    124.     return true;
    125. }
    126. int CAStarFindPath::GetCost(int r,int c)
    127. {
    128.     if (m_cost)
    129.         return m_Map->GetMapCost(r,c);
    130.     return 1;
    131. }
    132. void CAStarFindPath::Generate(Node &node,int r,int c)
    133. {
    134.     Node child;
    135.     child.r=r;
    136.     child.c=c;
    137.     int pos=openList.Find(child);
    138.     vector::iterator posCL;
    139.     for (posCL=closeList.begin();posCL!=closeList.end();++posCL)
    140.     {
    141.         if (posCL->r==r&&posCL->c==c)
    142.         {
    143.             break;
    144.         }
    145.     }
    146.     int cost=GetCost(r,c);
    147.     if (pos)    //在openlist中
    148.     {
    149.         if (node.g+cost>=child.g)   //在新节点的g比在open中的小就更新open中的
    150.             return;
    151.         child.parent=closeList.size();
    152.         child.g=node.g+cost;
    153.         child.f=child.g+child.h;
    154.         openList.Change(pos,child);
    155.     }
    156.     else if (!pos&&posCL==closeList.end())//不再open和close中
    157.     {
    158.         child.parent=closeList.size();
    159.         child.g=node.g+cost;    //计成本的地图
    160.         child.h=ABS(m_desR,r)+ABS(m_desC,c);    //(tr-r)*(tr-r)+(tc-c)*(tc-c)
    161.         child.f=child.g+child.h;
    162.         openList.Push(child);
    163.     }
    164. }
    165. void CAStarFindPath::Init(Node &start)
    166. {
    167.     if (!openList.Empty())
    168.     {
    169.         openList.Clear();
    170.     }
    171.     openList.Push(start);
    172.     if (!closeList.empty())
    173.     {
    174.         closeList.clear();
    175.     }
    176. }
    177. void CAStarFindPath::BestPath(Node &best)
    178. {
    179.     Node mudi=best;
    180.     Point node;
    181.     if (!bestList.empty())
    182.     {
    183.         bestList.clear();
    184.     }
    185.     while (mudi.parent>-1)
    186.     {
    187.         node.r=mudi.r;
    188.         node.c=mudi.c;
    189.         bestList.push_back(node);
    190.         mudi=closeList[mudi.parent];
    191.     }
    192. }

你可能感兴趣的:(游戏编程)