cocos2dx A星寻路



#ifndef __AstarAlgorithm__Astar__

#define __AstarAlgorithm__Astar__


#include <iostream>

#include "cocos2d.h"


class CAstar :public cocos2d::CCObject

{

private:

   int curCol, curRow, aimCol, aimRow;

    cocos2d::CCArray *open;

    cocos2d::CCArray *close;

    cocos2d::CCArray *path;

    cocos2d::CCArray *map;

    

   int conflictValue;

   int mapWidth;

   int mapHeight;

    

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

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

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

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

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

   void starSearch(constint &fid);//搜索

   void resetSort(int last);//排序

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

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

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

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

    

public:

   static CAstar *create();

    CAstar();

    ~CAstar();

    cocos2d::CCPointArray *findPath(int curX,int curY, int aimX,int aimY,

                                    cocos2d::CCArray *passMap,

                                   int theConflictValue = 1);//入口函数

};


class AstarItem:public cocos2d::CCObject

{

public:

    // AstarItem();

    // ~AstarItem();

    

    // / setter/getter

   void setPos(constint &col, constint &row)

    {

        id_col = col;

        id_row = row;

    }

   int getCol(){return id_col;}

   int getRow(){return id_row;}

    

    //实际估价 setter/getter

   void setG(constint &g){id_g = g;}

   int getG(){return id_g;}

    

    //估计代价 setter/getter

   void setH(constint &h){id_h = h;}

   int getH(){return id_h;}

    

    //父节点 setter/getter

   void setFid(constint &fid){id_fid = fid;}

   int getFid(){return id_fid;}

    

    //估价函数 setter/getter

   void setF(constint &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










#include "CAstar.h"

#include "cocos2d.h"


using namespace cocos2d;


CAstar::CAstar():map(NULL), conflictValue(1)

{

path = CCArray::create();

    path->retain();

    

    open = CCArray::create();

    open->retain();

    

    close = CCArray::create();

    close->retain();

}


CAstar::~CAstar()

{

    CC_SAFE_RELEASE(open);

    CC_SAFE_RELEASE(close);

    CC_SAFE_RELEASE(path);

    CC_SAFE_RELEASE(map);

}


CAstar *CAstar::create()

{

    CAstar *pRet =new CAstar();

    pRet->autorelease();

   return pRet;

}


int CAstar::getG(constint &col, constint &row, constint &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 CAstar::getH(constint &col, constint &row)//获得h()

{

    //获得该点的h

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

}


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

{

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

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

    close->addObject(temp);

    removeFromOpen();

}


void CAstar::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 CAstar::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 CAstar::starSearch(constint &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 <= mapHeight && checkMap(myCol, myRow))

    {

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

        {

        addToOpen(myCol, myRow, fid);

        }

    }

    

   //

    myCol = col;

    myRow = row +1;

   if (myRow <= mapHeight && checkMap(myCol, myRow))

    {

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

        {

        addToOpen(myCol, myRow, fid);

        }

    }

    

    //--右下

    myCol = col +1;

    myRow = row +1;

   if (myCol <=mapWidth && myRow <= mapHeight && checkMap(myCol, myRow))

    {

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

        {

        addToOpen(myCol, myRow, fid);

        }

    }

    

   //

    myCol = col +1;

    myRow = row;

   if (myCol <=mapWidth && checkMap(myCol, myRow))

    {

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

        {

        addToOpen(myCol, myRow, fid);

        }

    }

    

    //--上右

    myCol = col +1;

    myRow = row -1;

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

    {

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

        {

        addToOpen(myCol, myRow, fid);

        }

    }

}


void CAstar::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 CAstar::checkClose(constint &col, constint &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 CAstar::addToOpen(constint &col, constint &row, constint &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 CAstar::checkMap(constint &col, constint &row)//检查地图

{

   if (col >= mapWidth || row >= mapHeight)

    {

        return false;

    }

    

    CCArray *line = (CCArray*)map->objectAtIndex(row);

    CCInteger *value = (CCInteger*)line->objectAtIndex(col);

    

   if (value->getValue() == conflictValue)

    {

        return false;

    }

   else

    {

       return true;

    }

}

bool CAstar::checkOpen(constint &col, constint &row, constint &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;

}


CCPointArray *CAstar::findPath(int curX,int curY, int aimX,int aimY,

                               CCArray *passMap,

                              int theConflictValue)//入口函数

{

    curCol = curX;

    curRow = curY;

    aimCol = aimX;

    aimRow = aimY;

    

    conflictValue = theConflictValue;

    

   if (map != passMap)

    {

        CC_SAFE_RELEASE(map);

        map = passMap;

        map->retain();

    }


    mapHeight = map->count();

    CCArray *line = (CCArray*)map->objectAtIndex(0);

    mapWidth = line->count();

    

    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);

        }

        

        CCPointArray *ret = CCPointArray::create(path->count());

       for (unsignedint n = 0; n < path->count(); n++)

        {

            AstarItem *item = (AstarItem*)path->objectAtIndex(n);

           int nCol = item->getCol();

           int nRow = item->getRow();

            ret->addControlPoint(ccp(nCol, nRow));

        }

       return ret;

    }

 

}



//导出后lua使用方法

local startx = 1 

local starty = 1

local endx = 10

local endy = 10

local findPathMapData = CCArray:create()

for i = 1, 50 do
local line = CCArray:create()
for j = 1, 50 do
line:addObject( CCInteger:create(1) )
index = index + 1;
end
findPathMapData:insertObject(line)
end

local path = astar:findPath(startx-1,starty-1,endx-1,endy-1,findPathMapData,0)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值