#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;
}
}
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