根据上一篇,对应如下:
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");
}