Cocos2D-x A星寻路法

Cocos2D-x A星寻路法

(2013-05-22 17:43:19)
标签:

it

分类: Cocos2D-x
里面的A星寻路法代码有点坑爹,考虑不是很全面,内存管理也不是很细心.因为它主要目的是为了诠释算法的思路,也没有必要面面俱到.算法是灵魂,理解算法就可以了.
但也花了我半天的时间修改它的bug,下面贴出劈人修改后的代码,节省大家的时间-直接copy它就行了.

//

// AstarItem.h

// AstarAlgorithm

//

// Created by liboxiang on 13-5-21.

//

//


#ifndef __AstarAlgorithm__AstarItem__

#define __AstarAlgorithm__AstarItem__


#include <iostream>

#include "cocos2d.h"


class AstarItem: public cocos2d::CCObject

{

public:

// AstarItem();

// ~AstarItem();

 

  // 行 / 列 setter/getter

  void setPos(const int &col, const int &row)

  {

      id_col = col;

      id_row = row;

  }

  int getCol(){return id_col;}

  int getRow(){return id_row;}

 

  //实际估价 setter/getter

  void setG(const int &g){id_g = g;}

  int getG(){return id_g;}

 

  //估计代价 setter/getter

  void setH(const int &h){id_h = h;}

  int getH(){return id_h;}

 

  //父节点 setter/getter

  void setFid(const int &fid){id_fid = fid;}

  int getFid(){return id_fid;}

 

  //估价函数 setter/getter

  void setF(const int &f){id_f = f;}

  int getF(){return id_f;}

 

private:

  int id_col;//列

  int id_row;//行

  int id_g;//实际估价

  int id_h;//估计代价

  int id_fid;//父节点 标志close中的index

  int id_f;//估价函数 f = g + h

};

#endif


//

// Astar.h

// AstarAlgorithm

//

// Created by liboxiang on 13-5-21.

//

//


#ifndef __AstarAlgorithm__Astar__

#define __AstarAlgorithm__Astar__


#include <iostream>


namespace cocos2d

{

  class CCArray;

  class CCTMXTiledMap;

}


class Astar

{

private:

  int curCol, curRow, aimCol, aimRow;

// int AimX, AimY, AimW, AimH;

  cocos2d::CCArray *open;

  cocos2d::CCArray *close;

  cocos2d::CCArray *path;

  cocos2d::CCTMXTiledMap *map;

 

  std::string conflictProerty;

int conflictValue;

 

  int getG(const int &col, const int &row, const int &id);//获得g()

  int getH(const int &col, const int &row);//获得h()

  void fromOpenToClose();//将open中的元素导入close

  void removeFromOpen();//从open列表中删除元素

  void getPath();//获得整个路径

  void starSearch(const int &fid);//搜索

  void resetSort(int last);//排序

  bool checkClose(const int &col, const int &row);//检查close

  void addToOpen(const int &col, const int &row, const int &id);//向open添加元素

  bool checkMap(const int &col, const int &row);//检查地图

  bool checkOpen(const int &col, const int &row, const int &id);//检查列表

 

public:

  Astar();

  ~Astar();

  cocos2d::CCArray *findPath(const int &curX,

                            const int &curY,

                            const int &aimX,

                            const int &aimY,

                            cocos2d::CCTMXTiledMap *passMap,

                            const std::string &theConflictProerty,

                            const int &theConflictValue);//入口函数

};




#endif


//

// Astar.cpp

// AstarAlgorithm

//

// Created by liboxiang on 13-5-21.

//

//


#include "Astar.h"

#include "cocos2d.h"

#include "AstarItem.h"


using namespace cocos2d;


Astar::Astar():map(NULL), conflictProerty("conflict"), conflictValue(1)

{

path = CCArray::create();

  path->retain();

 

  open = CCArray::create();

  open->retain();

 

  close = CCArray::create();

  close->retain();

}


Astar::~Astar()

{

  CC_SAFE_RELEASE(open);

  CC_SAFE_RELEASE(close);

  CC_SAFE_RELEASE(path);

  CC_SAFE_RELEASE(map);

}


int Astar::getG(const int &col, const int &row, const int &id)//获得g()

{

  AstarItem *closeMember = (AstarItem *)close->objectAtIndex(id);

int fx = closeMember->getCol();

  int fy = closeMember->getRow();

  int fg = closeMember->getG();

 

  if (col - fx != 0 && row - fy != 0)

  {

      return fg + 14;

  }

  else

  {

      return fg + 10;

  }

}


int Astar::getH(const int &col, const int &row)//获得h()

{

  //获得该点的h值

  return abs(aimCol - col) * 10 + abs(aimRow - row) * 10;

}


void Astar::fromOpenToClose()//将open中的元素导入close

{

  //把open列表中的点 放到close列表

  AstarItem *temp = (AstarItem *)open->objectAtIndex(1);

  close->addObject(temp);

  removeFromOpen();

}


void Astar::removeFromOpen()//从open列表中删除元素

{

  //最後一个 替换第一个

  open->replaceObjectAtIndex(1, open->lastObject(), true);

 

  //删除最後一个

  open->removeLastObject();

 

  int last = open->count() - 1;

 

  //对排序

  int head = 1;

  while ( (head * 2) <= last )

  {

      int child1 = head * 2;

      int child2 = child1 + 1;

      int childMin(0);

     

      //找出 childMin

      if (child2 <= last)

      {

          AstarItem *child1AstarItem = (AstarItem *)open->objectAtIndex(child1);

          AstarItem *child2AstarItem = (AstarItem *)open->objectAtIndex(child2);

          childMin = child1AstarItem->getF() < child2AstarItem->getF() ? child1 : child2;

      }

      else

      {

          childMin = child1;

      }

     

      //head > childMin就交换

      AstarItem *headAstarItem = (AstarItem *)open->objectAtIndex(head);

      AstarItem *childMinAstarItem = (AstarItem *)open->objectAtIndex(childMin);

      if (headAstarItem->getF() <= childMinAstarItem->getF())

      {

          break;

      }


      open->exchangeObject(headAstarItem, childMinAstarItem);


     

      head = childMin;

  }

}


void Astar::getPath()//获得整个路径

{

  path->addObject(close->lastObject());

 

  while (true)

  {

      if (((AstarItem *)path->objectAtIndex(0))->getG() == 0 )

      { //达到终点时,结束循环

          break;

      }

     

      path->insertObject(

                        close->objectAtIndex(((AstarItem *)path->objectAtIndex(0))->getFid()),

                        0);

  }

  curCol = aimCol;

  curRow = aimRow;

}


void Astar::starSearch(const int &fid)//搜索

{

  AstarItem *fidAstarItem = (AstarItem *)close->objectAtIndex(fid);

 

  //view coordinate

  int col = fidAstarItem->getCol();

  int row = fidAstarItem->getRow();

 

  //搜索目前点的上 左 下 右 四个方向

 

  //上

  int myCol = col;

  int myRow = row - 1;

  if (myRow >= 0 && checkMap(myCol, myRow))

  {

      if (checkOpen(myCol, myRow, fid) && checkClose(myCol, myRow))

      {

      addToOpen(myCol, myRow, fid);

      }

  }

 

  //--上左

  myCol = col -1;

  myRow = row - 1;

  if (myCol >= 0 && myRow >= 0 && checkMap(myCol, myRow))

  {

      if (checkOpen(myCol, myRow, fid) && checkClose(myCol, myRow))

      {

      addToOpen(myCol, myRow, fid);

      }

  }

 

  //左

  myCol = col - 1;

  myRow = row;

  if (myCol >= 0 && checkMap(myCol, myRow))

  {

      if (checkOpen(myCol, myRow, fid) && checkClose(myCol, myRow))

      {

      addToOpen(myCol, myRow, fid);

      }

  }

 

  //--左下

  myCol = col -1;

  myRow = row + 1;

  if (myCol >= 0 && myRow <= map->getMapSize().height && checkMap(myCol, myRow))

  {

      if (checkOpen(myCol, myRow, fid) && checkClose(myCol, myRow))

      {

      addToOpen(myCol, myRow, fid);

      }

  }

 

  //下

  myCol = col;

  myRow = row + 1;

  if (myRow <= map->getMapSize().height && checkMap(myCol, myRow))

  {

      if (checkOpen(myCol, myRow, fid) && checkClose(myCol, myRow))

      {

      addToOpen(myCol, myRow, fid);

      }

  }

 

  //--右下

  myCol = col + 1;

  myRow = row + 1;

  if (myCol <=map->getMapSize().width && myRow <= map->getMapSize().height && checkMap(myCol, myRow))

  {

      if (checkOpen(myCol, myRow, fid) && checkClose(myCol, myRow))

      {

      addToOpen(myCol, myRow, fid);

      }

  }

 

  //右

  myCol = col + 1;

  myRow = row;

  if (myCol <=map->getMapSize().width && checkMap(myCol, myRow))

  {

      if (checkOpen(myCol, myRow, fid) && checkClose(myCol, myRow))

      {

      addToOpen(myCol, myRow, fid);

      }

  }

 

  //--上右

  myCol = col + 1;

  myRow = row - 1;

  if (myCol <=map->getMapSize().width && myRow >= 0 && checkMap(myCol, myRow))

  {

      if (checkOpen(myCol, myRow, fid) && checkClose(myCol, myRow))

      {

      addToOpen(myCol, myRow, fid);

      }

  }

}


void Astar::resetSort(int last)//排序

{

  while (last > 1)

  {

      int half = last / 2;

     

      AstarItem *lastAstarItem = (AstarItem *)open->objectAtIndex(last);

      AstarItem *halfAstarItem = (AstarItem *)open->objectAtIndex(half);

      if (halfAstarItem->getF() <= lastAstarItem->getF()) break;

     

      open->exchangeObject(halfAstarItem, lastAstarItem);

     

      last = half;

  }

}


bool Astar::checkClose(const int &col, const int &row)//检查close

{

  AstarItem *closeMember = NULL;

  CCObject *theObject = NULL;

  CCARRAY_FOREACH_REVERSE(close, theObject)

  {

      closeMember = (AstarItem *)theObject;

      if (closeMember->getCol() == col && closeMember->getRow() == row)

      {

          return false;

      }

  }

  return true;

}


void Astar::addToOpen(const int &col, const int &row, const int &id)//向open添加元素

{

  AstarItem *temp = new AstarItem();

  temp->setPos(col, row);

  temp->setFid(id);

 

  int g = getG(col, row, id);

  int h = getH(col, row);

 

  temp->setG(g);

  temp->setH(h);

  temp->setF(g + h);

  open->addObject(temp);

  resetSort(open->count() - 1);

}


bool Astar::checkMap(const int &col, const int &row)//检查地图

{

  CCTMXLayer *layer = map->layerNamed("grass");

  CCAssert(layer, "grass layer is not found at Astar::checkMap");

 

  if (col >= map->getMapSize().width || row >= map->getMapSize().height)

  {

      return false;

  }

  unsigned int tileGid = layer->tileGIDAt(ccp(col, row));CCAssert(tileGid > 0, "tileGid is empty");

 

  CCDictionary *tileDic = map->propertiesForGID(tileGid);CCAssert(tileDic, "tileDic is not found at Astar::checkMap");

 

  CCString *mValue = (CCString *)tileDic->objectForKey(conflictProerty.c_str());CCAssert(mValue, "mValue is not found at Astar::checkMap");

 

  if (mValue->intValue() == conflictValue)

  {

      return false;

  }

  else

  {

      return true;

  }

}

bool Astar::checkOpen(const int &col, const int &row, const int &id)//检查列表

{

  AstarItem *openMember = NULL;

  CCObject *theObject = NULL;

  unsigned int index = open->count() - 1;

  CCARRAY_FOREACH_REVERSE(open, theObject)

  {

      openMember = (AstarItem *)theObject;

      if (openMember->getCol() == col && openMember->getRow() == row)

      {

          int tempG = getG(col, row, id);

          if (tempG < openMember->getG())

          {

              openMember->setG(tempG);

              openMember->setFid(id);

              openMember->setF(openMember->getG() + openMember->getH());

              resetSort(index);

          }

         

          return false;

      }

      --index;

  }

 

  return true;

}


CCArray *Astar::findPath(const int &curX,

                      const int &curY,

                      const int &aimX,

                      const int &aimY,

                      CCTMXTiledMap *passMap,

                      const std::string &theConflictProerty,

                      const int &theConflictValue)//入口函数

{

curCol = curX;

  curRow = curY;

aimCol = aimX;

  aimRow = aimY;

 

  conflictProerty = theConflictProerty;

  conflictValue = theConflictValue;

 

  if (map != passMap)

  {

      CC_SAFE_RELEASE(map);

      map = passMap;

      map->retain();

  }

 

  path->removeAllObjects();

 

  // index = 0;

  AstarItem *temp = new AstarItem();

  open->addObject(temp);

 

  //index = 1;

  AstarItem *temp1 = new AstarItem();

  temp1->setPos(curCol, curRow);

  temp1->setG(0);

  int ag = getH(curCol, curRow);

  temp1->setH(ag);

  temp1->setFid(0);

  temp1->setF(0 + ag);

  open->addObject(temp1); 

  //遍历寻找路径

  while (open->count() > 1)

  {

      //open 中 最小的移动啊 close

      //open 中 重新排列

      fromOpenToClose();

      int fatherid = close->count() - 1;

     

      AstarItem *lastAstarItem = (AstarItem *)close->objectAtIndex(fatherid);

      if (abs(aimCol - lastAstarItem->getCol()) == 0 &&

          abs(aimRow - lastAstarItem->getRow()) == 0)

      {

          getPath();

          break;

      }

      else

      {

          //搜索

          starSearch(fatherid);

      }

  }

 

  open->removeAllObjects();

  close->removeAllObjects();

 

  //获得路径

  if (path->count() == 0)

  {

      return NULL;

  }

  else

  {

      AstarItem *lastAstarItem = (AstarItem *)path->lastObject();

      if (lastAstarItem->getCol() != aimCol ||

          lastAstarItem->getRow() != aimRow)

      {

          AstarItem *temp = new AstarItem();

          temp->setPos(aimCol, aimRow);

          path->addObject(temp);

      }

      return path;

  }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值