根據上一篇,對應如下:
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");
}