a x 1 x x 2 c语言,A星——C语言实现

思路大致如下:

首先有一张地图x*y的地图,为了方便,我们让每个点都用一个数字(10*x+y)来表示的话,也就是每个点唯一的属性。

1、定义一个包含点的信息的结构体,包含每个点的G值,F值,x,y坐标,它的父节点的x,y坐标。并定义此结构体型变量的数组,以存储路径。因为每个结构替里都包含了节点和它的父节点,因此我们可以用递归来输出路径。

2、定义一个链表,主要储存开启列表,关闭列表中的点的信息。之所以是链表,是为了对F值进行动态排列,每增加一个F值,我们都可以按一定顺序加入列表中。这样以来,每次的查找都会很方便。

3、此外,我们还需要设计一个将某点插入链表的函数,因为我们要很频繁的变换点的归属表。

4、删除链表某一节点的函数,有插入就有删除,当然,还有创建。

5、点的归属表的判断

6、更新表的F值,因为我们要不断做出比较,路径节点不断移动,于是随着G值的改变,F值也会随之改变。

7、判断方向的可行性

8、求出可行方向的点坐标,即下面经常讲到的“新点”。

9、最后写A星主程序

开启列表=关闭列表=NULL——创建开启列表,head节点就是路径的起点,也就是第一个父节点

循环:把父节点从开启列表中删除——判断是否到达终点——是,break,跳出while

——否——从右,下,左,上四个方向判断哪个方向可通过——得到一个可通过方向——计算一个新节点——判断在哪个列表中,可以用flag来标记

——都不在,则加入开启列表

——在开启列表,比较他们的F值,更新

——在关闭列表,比较他们的F值,更新,转移到开启列表

——将父节点加入到关闭列表中——判断开启列表是否为空——否,则将刚刚的新节点又作为父节点赋值给起点坐标——回到循环开头

对应如下:

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、将某点从链表中删除

list *del(list *head,int num_x,int num_y)

{

list *p1,

*p2;

if(head ==

NULL)

{

printf("\nlist null!\n");

return (head);

}

p1 =

head;

while((num_y

!= p1->n_y ||num_x != p1->n_x

)&& p1->next !=

NULL)

{

p2=p1;

p1=p1->next;

}

if(num_x ==

p1->n_x && num_y ==

p1->n_y )

{

if(p1==head)

head=p1->next;

else

p2->next=p1->next;

}

return

(head);

}

list *creat(void)

{

list *head;

list *p1;

int n=0;

p1=(list*)malloc(sizeof(list));

p1->n_f =

18;

p1->n_x =

0;

p1->n_y =

0;

p1->nfather_x =

-1;

p1->nfather_x =

-1;

p1->next =

NULL;

head = NULL;

head=p1;

return(head);

}

5、判断是否在开启/关闭列表里,返回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;

}

6、更新链表中某点的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);

}

7、判断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;

8、求往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=del(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

flagofopen=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(closelist,dian);//更新新点的F值

closelist=del(closelist,xnewstart,ynewstart);//从关闭列表中删除

openlist=insert(openlist,dian);//加入开启列表中

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值