最近要实训需要实现迷宫,所以就先实现了之前一直总是了解算法思路的a算法。最开始我是想凭借自己对于这个寻路算法的理解,完全的按照自己的思路实现,最后结果感人,在实现函数的传递时候,才发现自己对于c语言函数参数传递的概念有些理解错误,导致一直有错误。再我测试了多次,终于发现是由于函数参数传递使用有误,在这里我分享以下自己所遇见的错误吧,并且把自己实现的a算法,所讲一下。
c语言中的函数传递方式总共有三种:
1.直接将数值传入函数中,这时函数中的形参在函数未调用前是不会分配存储空间的,只有在函数调用过程中会生成一个局部变量,这种方式,会浪费存储空间,所以如果是传递自己所定义的结构体数据类型建议传递地址。并且这个局部变量的值为实参的值,修改这个形参无法对于实参的值进行修改。
2.将实参地址传入函数,这时函数获取了实参的地址,可以通过修改这个地址所指向的变量的值,来修改实参的值。
3.声明,通过这个方式也可修改实参的值。
例如,
#include
void a(int b,int &c,int *e);
void a(int b,int &c,int *e){
b=20;
c=30;
*e=10;
}
void main(){
int b,c,e;
b=10;
c=10;
e=20;
a(b,c,&e);
printf("b=%d,c=%d,e=%d",b,c,e);
}
在这个例子里,在主函数中,b=10,c=10,e=20;
而通过调用这个a()函数后,通过调用结果,输出的结果为b=10,c=30,e=10;通过这个应该能够理解c语言中函数参数的传递。
A算法的详解,可以在以下地址去学习,这是我早些时候学习a算法思路所观看的博客
a*算法思路
讲下基本思路:
1.将起始点加入openlist之中
2.将openlist中的F值最小的节点移到closelist中
3.检测以这个点为中心的邻近8个点:
头文件源代码
#include
#include
#define MAXSIZE 50
typedef struct node {
int data;
int G;
int F;
int H;
int x;
int y;
struct node* father;
}node;
typedef struct {
int b[MAXSIZE];
}datatype;
typedef struct {
datatype a[MAXSIZE];
int x, y;
}Array2;
typedef struct {
node data[MAXSIZE + 1];//L[0]当做一个利用的储存单位,没有用来存储节点
int len;
}Array1;
函数声明
void del(Array1* L, int index);//删除指定位置的节点需修改
void append(Array1* L, node p);
Array1 *startAstar(Array2* L, node *startpath, node* lastpath);//开始进行A星寻路
void init_Array(Array1* L);
int judge_out(Array1* L, node lastpath);
void print_Array(Array2* G);//打印地图
int getMinNode(Array1* L);
int getdex(Array1* L, node* p);
void searchNear(Array1* L, node* minF, int offsetx, int offsety,Array2* G,Array1* L2,node* lastnode);
函数实现
int getdex(Array1* L, node* p) {
int i;
for (i = 1;i <= L->len;i++) {
if (L->data[i].x == p->x && L->data[i].y == p->y)
return i;
}
}
void searchNear(Array1* L, node* minF, int offsetx, int offsety,Array2* G,Array1* L2 ,node* lastnode) {
int step;
if (minF->x + offsetx<0 || minF->x + offsetx>G->x - 1 || minF->y + offsety<0 || minF->y + offsety>G->y - 1)//判断是否越界
return;
if (G->a[minF->x + offsetx][minF->y + offsety] != 0)//判断是否可行走
return;
node* p;
p = (node*)malloc(sizeof(node));
p->x = minF->x + offsetx;
p->y = minF->y + offsety;
p->G = 0;
p->father = NULL;
if (judge_out(L2, *p))//判断是否在封闭列表中,若在则返回
return;
if (offsetx == 0 || offsety == 0)
step = 10;
else step = 14;
if (!judge_out(L, *p)) { //若该点既满足以上条件又不在开放列表中,则加入开放列表
p->H = (abs(lastnode->x - p->x) + abs(lastnode->y - p->y)) * 10;
p->G = minF->G + step;
p->F = p->H + p->G;
p->father = minF;
append(L, *p);
return;
}
if (judge_out(L, *p)) {
if (minF->G + step < L->data[getdex(L,p)].G) { //若该点满足以上条件但是在开放列表中,则与当前加入closelist的最小F点到这个点P利用G值做比较,选择G值小的。然后做出以下操作
L->data[getdex(L,p)].G = minF->G + step;
L->data[getdex(L, p)].F = L->data[getdex(L, p)].G + L->data[getdex(L, p)].H;
L->data[getdex(L, p)].father = minF;
}
}
}
int getMinNode(Array1 *L) {
int i,count=1;
for (i = 2;i <= L->len;i++)
if (L->data[count].F > L->data[i].F)
count = i;
return count;
}
void print_Array(Array2* G) {
int i, j;
for (i = 0;i < G->x;i++) {
for (j = 0;j < G->y;j++)
printf("%d\t", G->a[i][j]);
printf("\n");
}
}
int judge_out(Array1* L, node lastpath) {
int i;
for (i = 1;i <= L->len;i++) {
if (L->data[i].x == lastpath.x && L->data[i].y == lastpath.y)
return 1;
}
return 0;
}
void init_Array(Array1* L) {
int i;
for (i = 0;i <= MAXSIZE;i++)
L->data[i].F = 999;
L->len = 0;
}
void append(Array1* L, node p) {
L->len++;
L->data[L->len] = p;
}
Array1* startAstar(Array2* L, node *startpath, node *lastpath) {
Array1 openlist, closelist,shortpath;
init_Array(&openlist);//初始化开放列表和封闭列表
init_Array(&closelist);
init_Array(&shortpath);
if (L->a[startpath->x][startpath->y] == 1)//检测起始点是否为障碍,若为障碍则退出,返回NULL型
return NULL;
append(&openlist, *startpath);//将起点加入到开放列表中
while (1) { //主循环中
int p;
node q;
p = getMinNode(&openlist);//利用p储存找到的具有最小F值点在openlist中的位置
//q = openlist.data[p];//获取具有最小F值的节点,将之存于q //有问题
append(&closelist, openlist.data[p]);//将该节点加入到封闭列表中
del(&openlist, p);//将开放列表中的该节点删除
searchNear(&openlist, &closelist.data[closelist.len], 0, -1, L, &closelist, lastpath);//搜索具有最小F值点上下左右点,判断是否满足条件,满足则加入openlist中
searchNear(&openlist, &closelist.data[closelist.len], 0, 1, L, &closelist, lastpath);
/*searchNear(&openlist, &closelist.data[closelist.len], 1, 1, L, &closelist, lastpath);
searchNear(&openlist, &closelist.data[closelist.len], 1, -1, L, &closelist, lastpath);
searchNear(&openlist, &closelist.data[closelist.len], -1, 1, L, &closelist, lastpath);
searchNear(&openlist, &closelist.data[closelist.len], -1, -1, L, &closelist, lastpath);*/
searchNear(&openlist, &closelist.data[closelist.len], -1, 0, L, &closelist, lastpath);
searchNear(&openlist, &closelist.data[closelist.len], 1, 0, L, &closelist, lastpath);
if (judge_out(&openlist, *lastpath)) {//寻路结束判断,当终点进入开放列表则退出寻路
node* m;
m = (node*)malloc(sizeof(node));
m = &openlist.data[getdex(&openlist, lastpath)];
while (1) {
if (m == NULL)
break;
append(&shortpath, *m);
m = m->father;
}
return &shortpath;
}
if (openlist.len == 0)
//return &closelist;//在该迷宫中所走的路径
return NULL;
}
}
void del(Array1* L, int index) {
int i;
for (i = index;i <=L->len;i++) {
L->data[i] = L->data[i + 1];
}
L->len--;
}
主函数代码
#include"AStar2.h"
void init_G(Array2* G);
void init_G(Array2* G) {
int i, j;
for (i = 0;i < G->x;i++)
for (j = 0;j < G->y;j++)
G->a[i].b[j] = 0;
}
void main() {
Array2 G;
Array1* P;
node a, b;
int i;
G.x = 10;
G.y = 10;
init_G(&G);
for (i = 0;i < 8;i++)
G.a[i].b[5] = 1;
a.x = 5;
a.y = 0;
a.data = 0;
a.G = 0;
a.F = 0;
b.x = 0;
b.y = 07;
print_Array(&G);
printf("\n");
P = startAstar(&G, &a, &b);
if (P != NULL) {
for (i = 1;i < P->len;i++)
G.a[P->data[i].x].b[P->data[i].y] = 8;
}
print_Array(&G);
}