A星算法

这是被神化的算法。。。。用得到的地方不多
f'(n) = g'(n) + h'(n)
算法的伪程序如下:
Best_First_Search()
{
 Open = [起始节点];
 Closed = [];
 while (Open表非空)
 {
  从Open中取得一个节点X,并从OPEN表中删除。
  if (X是目标节点)
  {
   求得路径PATH;
   返回路径PATH;
  }
  for (每一个X的子节点Y)
  {
   if (Y不在OPEN表和CLOSE表中)
   {
    求Y的估价值;
    并将Y插入OPEN表中;
   }
   //还没有排序
   else if (Y在OPEN表中)
   {
    if (Y的估价值小于OPEN表的估价值)
     更新OPEN表中的估价值;
   }
   else //Y在CLOSE表中
   {
    if (Y的估价值小于CLOSE表的估价值)
    {
     更新CLOSE表中的估价值;
     从CLOSE表中移出节点,并放入OPEN表中;
    }
   }
   将X节点插入CLOSE表中;
   按照估价值将OPEN表中的节点排序;
  }//end for
 }//end while
}//end func

  先看搜索主函数:
void AstarPathfinder::FindPath(int sx, int sy, int dx, int dy)
{
    NODE *Node, *BestNode;
    int TileNumDest;
    //得到目标位置,作判断用
    TileNumDest = TileNum(sx, sy);
    //生成Open和Closed表
    OPEN = ( NODE* )calloc(1,sizeof( NODE ));
    CLOSED=( NODE* )calloc(1,sizeof( NODE ));
    //生成起始节点,并放入Open表中
    Node=( NODE* )calloc(1,sizeof( NODE ));
    Node->g = 0;
    //这是计算h值
    // should really use sqrt().
    Node->h = (dx-sx)*(dx-sx) + (dy-sy)*(dy-sy);
    //这是计算f值,即估价值
    Node->f = Node->g+Node->h;
    Node->NodeNum = TileNum(dx, dy);
    Node->x = dx; Node->y = dy;
    // make Open List point to first node
    OPEN->NextNode=Node;
    for (;;)
    {
        //从Open表中取得一个估价值最好的节点
        BestNode=ReturnBestNode();
        //如果该节点是目标节点就退出
        // if we've found the end, break and finish break;
        if (BestNode->NodeNum == TileNumDest)
        //否则生成子节点
        GenerateSuccessors(BestNode,sx,sy);
    }
    PATH = BestNode;
}
  再看看生成子节点函数:
void AstarPathfinder::GenerateSuccessors(NODE *BestNode, int dx, int dy)
{
    int x, y;
    //哦!依次生成八个方向的子节点,简单!
    // Upper-Left
    if ( FreeTile(x=BestNode->x-TILESIZE, y=BestNode->y-TILESIZE) )
        GenerateSucc(BestNode,x,y,dx,dy);
    // Upper
    if ( FreeTile(x=BestNode->x, y=BestNode->y-TILESIZE) )
        GenerateSucc(BestNode,x,y,dx,dy);
    // Upper-Right
    if ( FreeTile(x=BestNode->x+TILESIZE, y=BestNode->y-TILESIZE) )
        GenerateSucc(BestNode,x,y,dx,dy);
    // Right
    if ( FreeTile(x=BestNode->x+TILESIZE, y=BestNode->y) )
        GenerateSucc(BestNode,x,y,dx,dy);
    // Lower-Right
    if ( FreeTile(x=BestNode->x+TILESIZE, y=BestNode->y+TILESIZE) )
        GenerateSucc(BestNode,x,y,dx,dy);
    // Lower
    if ( FreeTile(x=BestNode->x, y=BestNode->y+TILESIZE) )
        GenerateSucc(BestNode,x,y,dx,dy);
    // Lower-Left
    if ( FreeTile(x=BestNode->x-TILESIZE, y=BestNode->y+TILESIZE) )
        GenerateSucc(BestNode,x,y,dx,dy);
    // Left
    if ( FreeTile(x=BestNode->x-TILESIZE, y=BestNode->y) )
        GenerateSucc(BestNode,x,y,dx,dy);
}        
  看看最重要的函数:
void AstarPathfinder::GenerateSucc(NODE *BestNode,int x, int y, int dx, int dy)
{
    int g, TileNumS, c = 0;
    NODE *Old, *Successor;
    //计算子节点的 g 值
    // g(Successor)=g(BestNode)+cost of getting from BestNode to Successor
    g = BestNode->g+1;
    // identification purposes
    TileNumS = TileNum(x,y);
    //子节点再Open表中吗?
    // if equal to NULL then not in OPEN list, else it returns the Node in Old
    if ( (Old=CheckOPEN(TileNumS)) != NULL )
    {
        //若在
        for( c = 0; c < 8; c++)
        // Add Old to the list of BestNode's Children (or Successors).
            if( BestNode->Child[c] == NULL )
                break;
        BestNode->Child[c] = Old;
        //比较Open表中的估价值和当前的估价值(只要比较g值就可以了)
        // if our new g value is < Old's then reset Old's parent to point to BestNode
        if ( g < Old->g )
        {
            //当前的估价值小就更新Open表中的估价值
            Old->Parent = BestNode;
            Old->g = g;
            Old->f = g + Old->h;
        }
    }
    else
    //在Closed表中吗?
    // if equal to NULL then not in OPEN list, else it returns the Node in Old
    if ( (Old=CheckCLOSED(TileNumS)) != NULL )
    {
        //若在
        for( c = 0; c< 8; c++)
        // Add Old to the list of BestNode's Children (or Successors).
            if ( BestNode->Child[c] == NULL )
                break;
        BestNode->Child[c] = Old;
        //比较Closed表中的估价值和当前的估价值(只要比较g值就可以了)
        // if our new g value is < Old's then reset Old's parent to point to BestNode
        if ( g < Old->g )
        {
            //当前的估价值小就更新Closed表中的估价值
            Old->Parent = BestNode;
            Old->g = g;
            Old->f = g + Old->h;
            //再依次更新Old的所有子节点的估价值
            // Since we changed the g value of Old, we need
            // to propagate this new value downwards, i.e.
            // do a Depth-First traversal of the tree!
            PropagateDown(Old);
        }
    }
    //不在Open表中也不在Close表中
    else
    {
        //生成新的节点
        Successor = ( NODE* )calloc(1,sizeof( NODE ));
        Successor->Parent = BestNode;
        Successor->g = g;
        // should do sqrt(), but since we don't really
        Successor->h = (x-dx)*(x-dx) + (y-dy)*(y-dy);
        // care about the distance but just which branch looks
        Successor->f = g+Successor->h;
        // better this should suffice. Anyayz it's faster.
        Successor->x = x;
        Successor->y = y;
        Successor->NodeNum = TileNumS;
        //再插入Open表中,同时排序。
        // Insert Successor on OPEN list wrt f
        Insert(Successor);
        for( c =0; c < 8; c++)
        // Add Old to the list of BestNode's Children (or Successors).
        if ( BestNode->Child[c] == NULL )
            break;
        BestNode->Child[c] = Successor;
    }
}
 






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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值