/********************************************
Function: A* search ,find the shortest path
Create Date: 2010 5.28
By: LiHong
********************************************/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <cstdlib>/*系统暂停头文件*/
#include <malloc.h>
#include <math.h>
#include <iostream>
#define MAP_W 60
#define MAP_H 30
struct POSITION{
int x;
int y;
};
typedef struct Node NODE;
struct Node {
int x_axis;
int y_axis;
int g;
int h;
int f;
NODE *Parent;
NODE *Child[4]; /* a node may have upto 4(NULL) children. */
NODE *next;
};
struct STACK {
NODE *node;
struct STACK *next;
};
class AiSearch{
public:
struct POSITION path[441];
int cost;
char map[MAP_H][MAP_W];
protected:
NODE *OPEN,*CLOSED;
struct STACK *stack;/*全局变量*/
private:
public:
AiSearch();
virtual ~AiSearch();
void initMap(char mapinfo[][MAP_W]);
NODE *returnBestNode();
void insertNode(NODE *Successor);
NODE *checkOpenTable(int x,int y);
NODE *checkClosedTable(int x,int y);
void expandNode(NODE *BestNode,int dx,int dy);
void expandNodeSucc(NODE *BestNode,int x, int y, int dx, int dy);
void freshOldValue(NODE *Old);
void Push(NODE *Node);
NODE *Pop();
void findPath(int sx,int sy,int dx,int dy);
};
AiSearch::AiSearch()
{
cost=0;
}
AiSearch::~AiSearch()
{
}
void AiSearch::initMap(char mapinfo[][MAP_W])
{
int i,j;
for(i=0;i<MAP_H;i++){
for(j=0;j<MAP_W;j++){
map[i][j]=mapinfo[i][j];
}
}
}
NODE * AiSearch::returnBestNode()
{
NODE *tmp;
if(OPEN->next==NULL){
return NULL;
}
tmp = OPEN->next;
OPEN->next = tmp->next;
tmp->next = CLOSED->next;
CLOSED->next = tmp;
return(tmp);
}
void AiSearch::insertNode(NODE *Successor)
{
NODE *tmp1,*tmp2;
int f;
if(OPEN->next == NULL) {
OPEN->next = Successor;
return;
}
f = Successor->f;
tmp1 = OPEN;
tmp2 = OPEN->next;
while( ( tmp2 != NULL ) && ( tmp2->f < f ) ) {
tmp1 = tmp2;
tmp2 = tmp2->next;
}
Successor->next = tmp2;
tmp1->next = Successor;
}
NODE * AiSearch::checkOpenTable(int x,int y)
{
NODE *tmp;
if(OPEN->next==NULL){
return NULL;
}
tmp= OPEN->next;
while( tmp!=NULL ) {
if( tmp->x_axis == x && tmp->y_axis==y )
return( tmp );
else
tmp = tmp->next;
}
return( NULL );
}
NODE * AiSearch::checkClosedTable(int x,int y)
{
NODE *tmp;
if(CLOSED->next==NULL){
return NULL;
}
tmp = CLOSED->next;
while( tmp!=NULL ) {
if( tmp->x_axis == x && tmp->y_axis==y )
return( tmp );
else
tmp = tmp->next;
}
return( NULL );
}
void AiSearch::expandNode(NODE *BestNode,int dx,int dy)
{
int x,y;
/* Upper */
x = BestNode->x_axis;
y = BestNode->y_axis - 1;
if( y >= 0 && map[y][x]!='#' )
{ expandNodeSucc(BestNode,x,y,dx,dy);}
/* Right */
x = BestNode->x_axis + 1;
y = BestNode->y_axis;
if( x < MAP_W && map[y][x]!='#')
{expandNodeSucc(BestNode,x,y,dx,dy);}
/* Lower */
x = BestNode->x_axis;
y = BestNode->y_axis + 1;
if( y < MAP_H && map[y][x]!='#')
{expandNodeSucc(BestNode,x,y,dx,dy);}
/* Left */
x = BestNode->x_axis - 1;
y = BestNode->y_axis;
if( x >= 0 && map[y][x]!='#' )
{ expandNodeSucc(BestNode,x,y,dx,dy);}
}
void AiSearch::expandNodeSucc(NODE *BestNode,int x, int y, int dx, int dy)
{
int g, c;
NODE *Old,*Successor;
//g = BestNode->g + TileMap[TileNumS];
g = BestNode->g + 1;
if( ( Old = checkOpenTable(x,y) ) != NULL ) {
for( c = 0; c < 4; c ++ ) {
if( BestNode->Child[c] == NULL ) break;
}
BestNode->Child[c] = Old;
if( g < Old->g ) {
Old->Parent = BestNode;
Old->g = g;
//Old->f = g + Old->h + Old->i;
Old->f = g + Old->h;
}
}
else if( ( Old = checkClosedTable(x,y) ) != NULL ) {
for( c = 0; c < 4; c ++ ) {
if( BestNode->Child[c] == NULL ) break;
}
BestNode->Child[c] = Old;
if( g < Old->g ) {
Old->Parent = BestNode;
Old->g = g;
Old->f = g + Old->h;
//Old->f = g + Old->h + Old->i;
freshOldValue( Old );
}
}
else {
Successor = (NODE *)calloc(1,sizeof(NODE ));
Successor->Parent = BestNode;
Successor->g = g;
//Successor->h = abs( x - dx ) + abs( y - dy );
Successor->h =abs( x - dx ) + abs( y - dy );
Successor->f = g + Successor->h;
Successor->x_axis = x;
Successor->y_axis = y;
Successor->next=NULL;
insertNode(Successor);
for( c = 0; c < 4; c ++ ) {
if( BestNode->Child[c] == NULL ) break;
}
BestNode->Child[c]=Successor;
}
}
void AiSearch::freshOldValue(NODE *Old)
{
int c,g;
NODE *Child, *Father;
g = Old->g;
for( c = 0; c < 4; c ++ ) {
if( ( Child = Old->Child[c] ) == NULL ) break;
if( g + 1 < Child->g ) {
Child->g = g + 1;
//Child->f = Child->g + Child->h + Child->i;
Child->f = Child->g + Child->h;
Child->Parent = Old;
Push( Child );
}
}
while( stack->next!= NULL ) {
Father = Pop();
for( c = 0; c < 4; c ++ ) {
if( ( Child = Father->Child[c] ) == NULL ) break;
if( Father->g + 1 < Child->g ) {
Child->g = Father->g + 1;
//Child->f = Child->g + Child->h + Child->i;
Child->f = Child->g + Child->h;
Child->Parent = Father;
Push( Child );
}
}
}
}
void AiSearch::Push(NODE *Node)
{
struct STACK *tmp;
tmp = ( struct STACK *)calloc(1,sizeof(struct STACK));
tmp->node = Node;
if(stack->next == NULL) {
tmp->next = NULL;
}else{
tmp->next = stack->next;
}
stack->next = tmp;
}
NODE * AiSearch::Pop()
{
NODE *tmp;
struct STACK *tmpstack;
tmpstack = stack->next;
tmp = tmpstack->node;
stack->next = tmpstack->next;
free( tmpstack );
return( tmp );
}
void AiSearch::findPath(int sx,int sy,int dx,int dy)
{
NODE *node, *bestnode;
NODE *father;
int i=0;
stack=( struct STACK *)calloc(1,sizeof(struct STACK));
OPEN=(NODE *)calloc(1,sizeof(NODE ));
CLOSED=(NODE *)calloc(1,sizeof(NODE ));
node=(NODE *)calloc(1,sizeof(NODE ));//source 节点
node->g = 0;
//这是计算h值
//node->h =int(sqrt( (dx-sx)*(dx-sx) + (dy-sy)*(dy-sy)));
node->h =abs(dx-sx)+abs(dy-sy);
//这是计算f值,即估价值
node->f = node->g+node->h;
node->x_axis =sx; node->y_axis = sy;
node->next=NULL;
// make Open List point to first node
OPEN->next=node;
for(;;){
bestnode=returnBestNode();
if (bestnode==NULL){
cost=0;
break;
}
if(bestnode->x_axis==dx && bestnode->y_axis==dy) {
father=bestnode;
cost=0;
while(father!=node && father->Parent!=NULL){
path[i].x=father->x_axis, path[i].y=father->y_axis;
i++;
cost++;
father=father->Parent;
}
break;
}else{
expandNode(bestnode, dx, dy);//扩展这个节点
}
}
}
char map[MAP_H][MAP_W];
int start_x=0,start_y,end_x=0,end_y;
//将地图信息map.dat载入到map全局数组中,map.dat中只含#,s,e和空格字符
int readMap()
{
FILE *f;
int i,j;
if((f=fopen("map.dat","r"))==NULL){
printf("open file err!");
return 0;
}
for(i=0;i<MAP_H;i++){
fgets(&map[i][0],MAP_W+2,f) ;
}
fclose(f);
for (i=0;i<MAP_H;i++){
for (j=0;j<MAP_W;j++){
if (map[i][j]=='s') {
map[i][j]=' ',start_x=j,start_y=i;
}
if (map[i][j]=='e'){
map[i][j]=' ',end_x=j,end_y=i;
}
}
}
if(start_x>0 && end_x>0)
return 1;
else
return 0;
}
//打印地图和找到的一条路径
void showMap(struct POSITION path[],int cost)
{
int i,j;
int ii,flag=0;
for (i=0;i<MAP_H;i++){
for (j=0;j<MAP_W;j++){
for(ii=0;ii<cost;ii++){
flag=0;
if(path[ii].x==j && path[ii].y==i){
printf("o");
flag=1;
break;
}
}
if(flag==0){
printf("%c",map[i][j]);
}
}
printf("/n");
}
}
// the main fucnction is for test
int main(int argc, char *argv[])
{ int i;
AiSearch ai;
if(!readMap()){
printf("the map is err!");
system("PAUSE");
}
ai.initMap(map);
ai.findPath(start_x,start_y,end_x,end_y);
showMap(ai.path,ai.cost);
for(i=0;i<ai.cost;i++){
printf("%d_%d ",ai.path[i].x,ai.path[i].y);
}
printf("/ncost:%d/n",ai.cost);
//printf("%d %d/n",start_x,start_y);
system("PAUSE");
return EXIT_SUCCESS;
}