把昨天的A*用C++类封装了下,然后用open表用二叉堆,效率上比SORT快,参照的是<在A*寻路中使用二叉堆
>,效率快了不少,我用70*70的地图测试,昨天的sort时间609ms,今天的94ms.
我还添加了4个方向或者8方向,一般4方向现在没用了,效率低很多,还加了个在障碍物是否拐角绕开,效率影响不大.然后为了A*类能在后面中重复利用,在判断地图格子是否可通时,继承接口类实现IsObstruction(int r,int c),可根据不同地图存储信息判断障碍物,在游戏里也不需要改变地图数据结构.还加了个地图移动成本,也通过上面接口类实现.效率上会有所降低.
二叉堆中存储的是节点,包含6个int,如果改成单独int索引,在交换数据时会快点点吧.
- //CAStarFindPath.h
- #pragma once
- #include <vector>
- #include <algorithm>
- #include "BinaryHeap.h"
- class IMapData //需要实现的地图数据接口
- {
- public:
- //该格子是否障碍物 能否通过 true是障碍物不能通过
- virtual bool IsObstruction(int r,int c)=0;
- virtual int GetMapCost(int r,int c)//格子地图成本 不需要时返回1
- {
- return 1;
- }
- };
- class CAStarFindPath //A*类
- {
- public:
- CAStarFindPath(void);
- public:
- ~CAStarFindPath(void);
- private:
- int m_R,m_C; //行列
- int m_srcR,m_srcC,m_desR,m_desC; //源 目的
- bool m_turnCorner; //是否绕过拐角
- bool m_eight; //4方向和8方向扩展
- bool m_cost; //地图成本
- CBinaryHeap openList; //open表
- std::vector<Node> closeList; //close表
- std::vector<Point> bestList; //最短路径表
- IMapData *m_Map;
- public:
- void SetMapSize(int sizeR,int sizeC,IMapData *mapData); //设置地图大小和地图数据接口
- void SetMapCost(bool cost=false); //地图成本开销 默认关
- void SetCorner(bool eight=true,bool turn=false); //设置4或8个方向 拐角默认关
- bool FindPath(int beginR,int beginC,int endR,int endC); //寻找路径无路径时返回false
- std::vector<Point> GetPath(void); //获取路径
- int GetStepNum(); //获取步长
- private:
- void KuoZhan(Node &node); //扩展新节点
- bool IsReach(int r,int c); //是否可到通过
- int GetCost(int r,int c);//获取地图成本
- void Generate(Node &node,int r,int c); //产生新节点
- bool Check(Node &value); //是否重复
- bool DaYu(Node & l,Node & r); //大于比较
- void Init(Node &start); //初始
- void BestPath(Node &best); //最优路径
- int ABS(int a,int b)
- {
- return a>b?(a-b):(b-a);
- }
- };
-
- //CAStarFindPath.cpp
- #include "AStarFindPath.h"
- using namespace std;
- CAStarFindPath::CAStarFindPath(void)
- {
- }
- CAStarFindPath::~CAStarFindPath(void)
- {
- }
- void CAStarFindPath::SetMapSize(int sizeR,int sizeC,IMapData *mapData)
- {
- m_R=sizeR,m_C=sizeC;
- m_Map=mapData;
- }
- void CAStarFindPath::SetMapCost(bool cost)
- {
- m_cost=cost;
- }
- void CAStarFindPath::SetCorner(bool eight,bool turn)
- {
- m_eight=eight;
- m_turnCorner=turn;
- }
- bool CAStarFindPath::FindPath(int sr,int sc,int dr,int dc)
- {
- m_srcR=sr,m_srcC=sc,m_desR=dr,m_desC=dc;
- Node temp,best;
- temp.r=sr;
- temp.c=sc;
- temp.g=0;
- temp.h=ABS(m_srcR,m_desR)+ABS(m_srcC,m_desC);
- temp.f=temp.g+temp.h;
- temp.parent=-1;
- Init(temp);
- while (!openList.Empty())
- {
- openList.Top(best);
- openList.Pop();
- if (best.r==dr&&best.c==dc)//找到
- {
- BestPath(best);
- return true;
- }
- KuoZhan(best);
- closeList.push_back(best);
- }
- //没路径
- bestList.clear();
- return false;
- }
- vector<Point> CAStarFindPath::GetPath(void)
- {
- return bestList;
- }
- int CAStarFindPath::GetStepNum()
- {
- return bestList.size();
- }
- void CAStarFindPath::KuoZhan(Node &node)
- {
- bool flag[4]={true,true,true,true};
- if (IsReach(node.r-1,node.c))// 上
- {
- Generate(node,node.r-1,node.c);
- }
- else
- {
- flag[0]=false,flag[1]=false;
- }
- if (IsReach(node.r,node.c+1))//右
- {
- Generate(node,node.r,node.c+1);
- }
- else
- {
- flag[1]=false,flag[2]=false;
- }
- if (IsReach(node.r+1,node.c))// 下
- {
- Generate(node,node.r+1,node.c);
- }
- else
- {
- flag[2]=false,flag[3]=false;
- }
- if (IsReach(node.r,node.c-1))// 左
- {
- Generate(node,node.r,node.c-1);
- }
- else
- {
- flag[3]=false,flag[0]=false;
- }
- if (!m_eight)
- {
- return;
- }
- if (!m_turnCorner)
- {
- for(int i=0;i<4;i++)
- flag[i]=true;
- }
- if (flag[0]&&IsReach(node.r-1,node.c-1))// 左上
- {
- Generate(node,node.r-1,node.c-1);
- }
- if (flag[1]&&IsReach(node.r-1,node.c+1))//右上
- {
- Generate(node,node.r-1,node.c+1);
- }
- if (flag[2]&&IsReach(node.r+1,node.c+1))// 右下
- {
- Generate(node,node.r+1,node.c+1);
- }
- if (flag[3]&&IsReach(node.r+1,node.c-1))// 左下
- {
- Generate(node,node.r+1,node.c-1);
- }
- }
- bool CAStarFindPath::IsReach(int r,int c)
- {
- if (m_Map->IsObstruction(r,c)||r<0||c<0||r>m_R||c>m_C)
- return false;
- return true;
- }
- int CAStarFindPath::GetCost(int r,int c)
- {
- if (m_cost)
- return m_Map->GetMapCost(r,c);
- return 1;
- }
- void CAStarFindPath::Generate(Node &node,int r,int c)
- {
- Node child;
- child.r=r;
- child.c=c;
- int pos=openList.Find(child);
- vector<Node>::iterator posCL;
- for (posCL=closeList.begin();posCL!=closeList.end();++posCL)
- {
- if (posCL->r==r&&posCL->c==c)
- {
- break;
- }
- }
- int cost=GetCost(r,c);
- if (pos) //在openlist中
- {
- if (node.g+cost>=child.g) //在新节点的g比在open中的小就更新open中的
- return;
- child.parent=closeList.size();
- child.g=node.g+cost;
- child.f=child.g+child.h;
- openList.Change(pos,child);
- }
- else if (!pos&&posCL==closeList.end())//不再open和close中
- {
- child.parent=closeList.size();
- child.g=node.g+cost; //计成本的地图
- child.h=ABS(m_desR,r)+ABS(m_desC,c); //(tr-r)*(tr-r)+(tc-c)*(tc-c)
- child.f=child.g+child.h;
- openList.Push(child);
- }
- }
- void CAStarFindPath::Init(Node &start)
- {
- if (!openList.Empty())
- {
- openList.Clear();
- }
- openList.Push(start);
- if (!closeList.empty())
- {
- closeList.clear();
- }
- }
- void CAStarFindPath::BestPath(Node &best)
- {
- Node mudi=best;
- Point node;
- if (!bestList.empty())
- {
- bestList.clear();
- }
- while (mudi.parent>-1)
- {
- node.r=mudi.r;
- node.c=mudi.c;
- bestList.push_back(node);
- mudi=closeList[mudi.parent];
- }
- }