A* search ,find the shortest path

本文介绍了一种基于A*搜索算法实现寻路的功能,并详细展示了算法的具体实现过程,包括节点结构定义、开放列表与关闭列表操作、路径评估与扩展等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/********************************************
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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值