A星代碼—整理

根據上一篇,對應如下:

1、節點屬性Of結構體

struct dian
  {
    int ng;//G值
    int nf; //F值
    int myx;

    int myy;//自己
    int fatherx;
    int fathery;//父節點
  };

路徑的輸出:

void putout()

{
    int nxx = spaydian[nend].nfatherx;
    int nyy = spaydian[nend].nfathery;

    digui(nxx,nyy) ;
}
void digui(int nxx,int nyy)

{   map[nxx][nyy] = '通過標誌‘;

  if( nxx != 0 || nyy != 0 )

    {
        int  nxxyy = 10*nxx+nyy;
        nxx = dian[nxxyy].nfatherx;
        nyy = dian[nxxyy].nfathery;
         digui(nxx,nyy);
     }
}

2、鏈表

typedef struct list {
 int n_f;
 int n_x;
 int n_y;
 int nfather_x;
 int nfather_y;
 struct list *next;
};

3、將dian(屬性值)插入開啓或關閉鏈表中

list * insert(list *head,int dian)
  {
    list *p0,*p1,*p2;
    p1=head;
    p0=(list*)malloc(sizeof(list));//以下的將數據逐一賦值
    p0->n_f = dian[dian].nf;
    p0->n_x = dian[dian].myx;
    p0->n_y = dian[dian].myy;
    p0->nfather_x = dian[dian].fatherx;
    p0->nfather_x = dian[dian].fathery;
    p0->next = NULL;
    if(head==NULL)
    {
       head=p0;
       p0->next=NULL;
    }
    else
    {
       while((p0->n_f > p1->n_f)&&(p1->next!=NULL))//查找臨界點
      {
         p2=p1;
         p1=p1->next;
      }
    if(p0->n_f <= p1->n_f)//將dian插入合適的位置(F值排列)
    {
     if(head==p1)
        head=p0;
     else
        p2->next=p0;
     p0->next=p1;
    }
    else
    {
     p1->next=p0;
     p0->next=NULL;
    }
   }
   return (head);
  }

4、判斷是否在開啓/關閉列表裏,返回1在,0則不在

 int isinopenlist/isincloselist(int nx,int ny)(兩個函數)
{
    list *p1, *p2;
    p1 = openlist;
    while((ny != p1->n_y || nx != p1->n_x )&& p1->next != NULL)
    {
       p2 = p1;
       p1 = p1->next;
     }
     if(nx == p1->n_x && ny == p1->n_y)
       return 1;
     else
      return 0;
    }

5、更新鏈表中某點的F值

list * tonewlist(list *head,int dian)

{
    list *p1, *p2;
    p1=head;
    while(dian[dian].myx!=p1->n_x && dian[dian].myy!=p1->n_y && p1->next!=NULL)
    {
    p2=p1;
    p1=p1->next;
    }
   if(dian[dian].myx==p1->n_x && dian[dian].myy==p1->n_y)
      p1->n_f = dian[dian].nf;

   return (head);
}

6、判斷i(1右,2下,3左,4上)方向是否可走,返回1爲可走,0爲不可走

 int judge(int nx,int ny,int i)

    if (i==1)  //判斷向右可否行走
    {
     if (map[nx][ny+1]==可過 && ny<邊界)
         return 1;

     else
     return 0;

    }

    else if (i==2)  //判斷向下可否行走
    {
     if (map[nx+1][ny]==可過 && nx<邊界)
     return 1;
     else
     return 0;
    }
    else if (i==3)//判斷向左可否行走
      {
         if (ny >0&&map[nx][ny-1]==可過)
          return 1;
         else
         return 0;
       }
    else if (i==4)//判斷向上可否行走
      {
        if (nx > 0&&map[nx-1][ny]==可過)
        return 1;
        else
        return 0;
       }
    else
     return 0;

7、求往i方向上的新的x/y點(兩個函數)

int newx/y(int nx/ny,int i)
{
    if(i == 1)//右
        nx = nx;/ny = ny+1;
    else if(i == 2)//下
        nx = nx+1;/ny = ny;
    else if(i == 3)//左
        nx = nx;/ny = ny-1;
    else if(i == 4)//上
        nx = nx-1;/ny = ny;
    return nx/ny;
}

接下來,就是寫主要的A*了:

void astar()

{

openlist=closelist=NULL;
openlist=creat();
while(openlist!=NULL)
{
   openlist=delete(openlist,xstart,ystart);//將父節點從開啓列表中刪除
   if(xstart==xend&&ystart==yend)
   {
       map[9][9] = '通過標誌';

       break;
   }
  for(int i=1;i<=4;i++)//逐個判斷4個方向。1右,2下,3左,4上
  { 
      if(judge(xstart , ystart ,i ))
      {
          xnewstar=newx(xstart , i);
          ynewstar=newy(ystart , i);

 

          if(openlist!=NULL)
             flagofopen=isinopenlist(xnewstar,ynewstar);
          else
             flagofcopen=0;

 

         if(openlist!=NULL)
             flagofclose=isincloselist(xnewstar,ynewstar);
          else
             flagofclose=0;

 

          dian=10*xnewstar+ynewstar;//新點屬性
          dian[dian].ng=dian[10*xstart+ystart].ng+1;//新點G值
          nh=(nend-dian)/10+(nend-dian)%10;//新點H值


          if(flagofopen==0&&flagofclose==0)//新點都不在列表中
          {
              dian[dian].nf=dian[dian].ng+nh;
              dian[dian].nfatherx=xstart;
              dian[dian].nfathery=ystart;
              dian[dian].myx=xnewstart;
              dian[dian].myy=ynewstary;
              openlist=insret(openlist,dian);//新點插入開啓列表
          }
          else if(flagofopen==1)//若已經在開啓列表,則比較他們的F值,更新

         {
             if(dian[dian].nf>dian[dian].ng+nh&&dian[dian].nf!=最大的的F值)
             {
                  dian[dian].nf=dian[dian].ng+nh;
                  openlist=tonewlist(openlist,dian);//更新dian的F值
             }
         }
          else if(flagofclose==1)//若已經在關閉列表,則比較他們的F值,更新,轉移列表
          {
               if(dian[dian].nf>dian[dian].ng+nh&&dian[dian].nf!=最大的的F值)
                     {
                       dian[dian].nf=dian[dian].ng+nh;
                       closelist=tonewlist(close.dian);//更新新點的F值
                       closelist=delete(closelist,xnewstart,ynewstart);//從關閉列表中刪除
                       openlist=insert(openlist,dian);//加入開啓列表中
                     }
          }
      }
  }//end for for
  closelist=insret(closelist,(10*xstart+ystart));//將父節點插入關閉列表
  if(openlist!=NULL)
  {
    xstart=openlist->n_x;//取開啓列表
    ystart=openlist->n_y;
  }
}//end for while
if(openlist==NULL)//若此時開啓列表仍是空表,說明沒有路徑可以到達。
printf("無路可走/n");

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章