A-star(A*)寻路算法 C++ 自己实现的完整代码(小白) - 注释,输出都保留,欢迎讨论指出问题

想做游戏,所以最近看了下算法,看到了常用的 A*算法 索性就学了一学,感觉unity3d上面好像有封装的寻路算法,还是想着去实现一下,大概就看了很多百度,一共用了两天,把它简单实现了下。

前提
我很久没有用C++了,所以很多概念模糊,也是边查边用的,一直再用JAVA,所以很多传指针,返回指针(我返回的数组),就感觉没JAVA直接返回数组那么顺手。不过东查西查的按照自己的想法,还是简单的实现了一下。如果有错误希望指出,仅供大家参考、交流。

还有就是如果有朋友没看过A*算法的,可以先去百度搜一下,看一下是个怎么回事,才来看我这个小白实现简单A*的代码,毕竟能写代码才是王道。

思路
我的思路是创建一个地图 可以自己设定 具体在#defind MapSize 100(我建的是10*10),地图中给出障碍物、起点和终点。
然后地图分成100块,每一块是一个用一个结构体表示,程序中 struct A_map,里面有几个值

  1. int Map_symbol(代表是什么东西,1为普通 2为围墙 3为起点 4为钟点)
  2. int x,y(分别代表地图块的坐标)
  3. float already_Cost (实际走过的路径的花费,网上的g(n))
  4. float expect_Cost (估计花费 算法使用那个什么哦,用曼哈顿距离是的,因为简单,地图全都被分成了块状,简单,简单。)
  5. int Visit_symbol(1是已经访问 2是没访问 3是准备访问 )
  6. 注释//struct A_map *next;(代码中的这个东西是被我注释了,因为本来想用指针来指一下路径,一个接一个,像链表一样。结果没法,语法错误,想用,可以试试,好像用处也不够大)
  7. Cost=already_Cost+expect_Cost

———–结构体代码————

//定义地图块结构体
struct A_map{
    int Map_symbol;//1为普通  2为围墙  3为起点 4为重点
    int x;//坐标 x
    int y;//坐标 y
    //网上找的g(n)可以看做从start到current所花费的cost,h(n)从current到end的花费。  这里虽然是感觉是多余的,但是这样应该清晰点吧。。。火火火。
    float already_Cost;//实际走过的路径的花费
    float expect_Cost;//估计花费 算法使用那个什么哦,因为简单,地图全都被分成了块状,简单,简单。
    float Cost;//总花费
    int Visit_symbol;//1是已经访问 2是没访问 3是准备访问  
    //struct A_map *next;
};

好了有了上面这个结构体,我们的地图就有了存储信息的功能。
(我看文档里面的都是把东西放入一个数组里面,openlist ……closelist,就是标记那些访问了,那些没访问,那些需要访问的。,我这里用visit_symbol代替咯,意思就是每当我要访问的时候先检测这个A_map的访问标识,是可以访问呢,还是已经访问过了,还是马上需要判断,需要访问

有了地图,并且知道地图上的每个块可以存储一定的信息,那么,我们初始化地图

init

//初始化地图
void MapInit(A_map maps[],int goods[]){
    int i,j=0;//循环变量
    for(i=0;i< MapSize;i++){//把所有的地图块全都初始化,Map_symbol=1(平地),visit_symbol=2(没有访问的状态,意思是可访问)
        maps[i].Map_symbol=1;//map 1是平地
        maps[i].x=i%10;//下一行  给x 值,从0到9,满10归0
        maps[i].Visit_symbol=2;//2是没访问的,可访问的
        if(i%10==0&&i!=0){
            j++;
        }
        maps[i].y=j;//给Y赋值
    }
    maps[goods[0]].already_Cost=0;//初始化起点的消耗为0
    maps[goods[0]].expect_Cost=0;//初始化
    maps[goods[0]].Cost=0;//初始化  Cost=already_Cost+expect_Cost;
    i=0;//再把i变为0,重复利用
    for(i;i<9;i++){
        if(i==0){//开始点 开始点是已访问的 - 0是开始
            maps[goods[i]].Map_symbol=3;//3代表起点
            maps[goods[i]].Visit_symbol=1;//1代表已访问
        }else if(i==8){//结束点   结束点是可访问的。 - 8是结束点,可以改成数组的长度-1,感觉C++没那么方便,我就直接以我知道的给他赋8了,这样是不够灵活的。
            maps[goods[i]].Map_symbol=4;//4代表终点
            maps[goods[i]].Visit_symbol=2;//2代表可访问
        }else{//障碍物 已访问的(不用再访问)。
            maps[goods[i]].Map_symbol=2;//2代表障碍物
            maps[goods[i]].Visit_symbol=1;//1代表以访问-就是不可访问了
        }
    }
}

一一解释一下里面的数组到底是什么用
1. maps[]:一百个地图块结构体的集合。index 0-99
2.goods[]:存储起点终点、还有障碍物的集合。具体的讲。goods[index],里面的index是maps[]数组的索引值。意思是 index的范围是0~99下面看goods[]的定义:

int goods[]={12,41,42,43,44,45,46,47,76};//记录  起点,障碍物的排列数字,终点的排列数字

goods[0]:默认为起点
goods[sizeof(goods)/sizeof(int)]:也就是最后一位,默认为终点。
其余的就全是障碍物。

地图初始化完成了,我们就要按照步骤来。
1、先检验起点周围的可以访问的点,放入一个数组。
2、计算每个点的f(n)=g(n)+h(n),就是结构体里面的 cost,选择最小的cost 作为下一步将要去的点。
3、下次去的点赋值给curretMap,然后把没选中的点全部设置为不可访问。
4、又从currentMap,循环上面的123……最后给出到达终点的判定,结束整个寻路。

———说着挺简单——–做着,其实还好,就是我的代码写的有点不好看。
1、检验周围的可访问点,放入一个数组,用指针返回。

//获得周围的8个地图块  传入当前坐标
//currentMap是代表当前所处的地图快。 maps老规矩,是所有地图块的集合。
int * GetExpect_Map(A_map currentMap,A_map maps[]){
    static int Map_Index[8];//这里我一如既往的已经给他规定死了8个因为一个地图块周围最多就只有8个是可以前进的。
    int index=0;//可行的mps索引值
    int i;//循环变量
    for(i=0;i< MapSize;i++){//开始循环,找出所有的可行的地图快
        if(currentMap.x-1<=maps[i].x&&maps[i].x<=currentMap.x+1&&currentMap.y-1<=maps[i].y&&maps[i].y<=currentMap.y+1){//写出条件(就是将currtMap周围的8个点全部检测)
            if(maps[i].Visit_symbol==2){//如果是2的话就是可以访问,
                maps[i].Visit_symbol=3;//准备访问,可以访问,我们马上把它变成即将访问3。
                Map_Index[index++]=i;//记录可以访问的下标
            }
        }
    }
    return Map_Index;//返回数组
}

2、计算每个点的f(n)=g(n)+h(n),就是结构体里面的 cost,选择最小的cost 作为下一步将要去的点,并返回将要去的点的maps的索引值

//循环计算欲走的路 并输出下一步的map
//Expect_Index[]数组中的东西就是步骤1中返回的Map_Index,里面装了currtMap周围可访问的几个地图块。
//endPoint代表结束点的地图块
//currentMap是当前所在的地图块。
int ReckonTheExpect(int Expect_Index[],A_map maps[],A_map EndPoint,A_map *currentMap){
    int index=0;//下一步要走的下标
    int AlreadyCost=currentMap->already_Cost;//记录从起点到当前的消耗。
    int MHD_distance=0;//曼哈顿距离
    //那就先计算消耗吧
    while(Expect_Index[index]!='\0'){
        //先计算曼哈距离 存入
        MHD_distance=GetExpect_Cost(maps[Expect_Index[index]].x,maps[Expect_Index[index]].y,EndPoint.x,EndPoint.y);//传入两点的横坐标纵坐标算出曼哈顿距离的函数GetExpect_Cost(x1,y1,x2,y2);
        maps[Expect_Index[index]].expect_Cost=MHD_distance;//算出后,立即将曼哈顿距离放进当前检测的Expect_Index中的地图块。让她的信息保存
        if(maps[Expect_Index[index]].x==currentMap->x||maps[Expect_Index[index]].y==currentMap->y){//上下左右直线。 LINE=1
            maps[Expect_Index[index]].already_Cost=AlreadyCost+LINE;//直线向加在当前的距离上加上1,为检测的地图块到终点的already距离       
        }else{//斜线    根号2  大约  1.41   SKEW 为 1.41
            maps[Expect_Index[index]].already_Cost=AlreadyCost+SKEW;//斜向加1.41
        }
          maps[Expect_Index[index]].Cost=maps[Expect_Index[index]].already_Cost+maps[Expect_Index[index]].expect_Cost;//Cost=alreadycost+expectcost;

        index++;//下标自增
    }
    return Expect_Index[CompareToMap(maps,Expect_Index)];//返回下一步的具体Maps索引值。 
    //比较函数   CompareToMap(maps,expect_index); 上面获取到信息后,由此函数对里面的大小值一一进行对比,对比成功后,返回 expect_index的索引值。
}

//对比地图块的代价
int CompareToMap(A_map maps[],int Expect_Index[]){//这个函数就和比较大小的函数一样的道理,只是里面加了一些条件,如果 cost相同就找 expectcost ,如果expectcost相同就找alreadycost,如果都相同了,那就随便选一个,不变无所谓。
    int index=0;
    int record_index=0;//记录最小下标
    float areadyCost=maps[Expect_Index[index]].already_Cost;//装第一个对比对象
    float expectCost=maps[Expect_Index[index]].expect_Cost;
    float cost=maps[Expect_Index[index]].Cost;
    //对比大小
    index=1;
    record_index=index;
    while(Expect_Index[index]!='\0'){
        if(cost>maps[Expect_Index[index]].Cost){//>对比cost
            cost=maps[Expect_Index[index]].Cost;
            record_index=index;
        }else if(cost==maps[Expect_Index[index]].Cost){//=cost相同
            if(expectCost>maps[Expect_Index[index]].expect_Cost){//>对比 expect
                expectCost=maps[Expect_Index[index]].expect_Cost;
                record_index=index;
            }else if(expectCost==maps[Expect_Index[index]].expect_Cost){//= expect相同
                if(areadyCost>maps[Expect_Index[index]].already_Cost){//>对比 areadycost
                    areadyCost=maps[Expect_Index[index]].already_Cost;
                    record_index=index;
                }
            }
        }
        index++;
    }
    return record_index;
}

3、下次去的点赋值给curretMap,然后把没选中的点全部设置为不可访问。

//这里就是跳到已经选定了的方向走了。上面已经把需要的index传过来了,就是这里的形参  nextStep,那么在行走后还需要把所有没选中的地图块改为 visitSymbol = 1(就是已经访问了,不能再访问了。),
//将路径连接起来,并且改变symbol
void NextStep(A_map *currentMap,A_map maps[],int nextStep,int Expect_Index[]){
    //前面的位置检测
    //cout<<"前一位置:("<<currentMap->x<<","<<currentMap->y<<")\n";
    int index=0;
    if(currentMap->Visit_symbol==3){//是3就跳1这个主要是用来检测如果当前的地图块是3,就变为1,不可访问。因为当前的已经选定不需要再访问了。
        currentMap->Visit_symbol=1;
    }   
    //循环把所有的都变为1,不可访问
    while(Expect_Index[index]!='\0'){
        maps[Expect_Index[index]].Visit_symbol=1;
        index++;
    }
    //这样的话,这里的currentMap还是原来那个位置,并没有向预定的方向走一步,所以把连以前的位置和它走位的几块可选的位置全部射程1。不可访问。那么cuerrentMap应该在哪里变化,我选择在最外部,等下看main函数就知道了。
}

///我还写了几个打印的函数。

  1. void PrintMap(A_map everyMap[]):打印地图信息,格式 “数字 - 坐标” 这里的数字是 map_symbol
  2. void PrintMap2(A_map everyMap[])打印的是地图信息,格式“数字-坐标” 这里的数字是 visible_symbol
  3. void PrintExpect(int *expect_Point)打印的是,当前点的周围有那些点是可以移动的。

——————————–贴个完整代码吧————–用的VC++6.0,代码赋值粘贴直接跑—————

#include <iostream>

using namespace std;
//函数声明

#define MapSize 100
#define LINE 1//横竖 消耗
#define SKEW 1.41//斜 消耗


//定义地图块结构体
struct A_map{
    int Map_symbol;//1为普通  2为围墙  3为起点 4为重点
    int x;//坐标 x
    int y;//坐标 y
    //网上找的g(n)可以看做从start到current所花费的cost,h(n)从current到end的花费。  这里虽然是感觉是多余的,但是这样应该清晰点吧。。。火火火。
    float already_Cost;//实际走过的路径的花费
    float expect_Cost;//估计花费 算法使用那个什么哦,因为简单,地图全都被分成了块状,简单,简单。
    float Cost;//总花费
    int Visit_symbol;//1是已经访问 2是没访问 3是准备访问  
    //struct A_map *next;
};

//函数-计算两个地图之间的 expect_Cost   return  int  曼哈顿距离???
//传入两点的 xy
int GetExpect_Cost(int x1,int y1,int x2,int y2){
    int x=x2-x1;
    int y=y2-y1;
    if(x<0) x=-x;
    if(y<0) y=-y;
    return x+y;
}

//获得周围的8个地图块  传入当前坐标
int * GetExpect_Map(A_map currentMap,A_map maps[]){
    static int Map_Index[8];
    int index=0;
    int i;
    //测试方法输出
    //cout<<currentMap.x<<","<<currentMap.y<<"   "<<currentMap.Map_symbol<<" |";
    for(i=0;i<MapSize;i++){
        if(currentMap.x-1<=maps[i].x&&maps[i].x<=currentMap.x+1&&currentMap.y-1<=maps[i].y&&maps[i].y<=currentMap.y+1){//写出条件
            if(maps[i].Visit_symbol==2){//如果是1 就是未被访问。那么要即将访问。
                maps[i].Visit_symbol=3;//准备访问
                Map_Index[index++]=i;//记录下标
            }
        }
    }
    return Map_Index;
}

//初始化地图
void MapInit(A_map maps[],int goods[]){
    int i,j=0;
    //int index=0;
    for(i=0;i<MapSize;i++){
        maps[i].Map_symbol=1;//map 1是平地
        maps[i].x=i%10;
        maps[i].Visit_symbol=2;//2是没访问的
        if(i%10==0&&i!=0){
            j++;
        }
        maps[i].y=j;
    }
    maps[goods[0]].already_Cost=0;
    maps[goods[0]].expect_Cost=0;
    maps[goods[0]].Cost=0;
    i=0;
    for(i;i<9;i++){
        if(i==0){//开始点 开始点是已访问的
            maps[goods[i]].Map_symbol=3;
            maps[goods[i]].Visit_symbol=1;
        }else if(i==8){//结束点   结束点是可访问的。
            maps[goods[i]].Map_symbol=4;
            maps[goods[i]].Visit_symbol=2;
        }else{//障碍物 已访问的(不用再访问)。
            maps[goods[i]].Map_symbol=2;
            maps[goods[i]].Visit_symbol=1;
        }
    }
}

//对比地图块的代价
int CompareToMap(A_map maps[],int Expect_Index[]){
    int index=0;
    int record_index=0;//记录最小下标
    float areadyCost=maps[Expect_Index[index]].already_Cost;
    float expectCost=maps[Expect_Index[index]].expect_Cost;
    float cost=maps[Expect_Index[index]].Cost;
    //对比大小
    index=1;
    record_index=index;
    while(Expect_Index[index]!='\0'){
        if(cost>maps[Expect_Index[index]].Cost){//>对比cost
            cost=maps[Expect_Index[index]].Cost;
            record_index=index;
        }else if(cost==maps[Expect_Index[index]].Cost){//=cost相同
            if(expectCost>maps[Expect_Index[index]].expect_Cost){//>对比 expect
                expectCost=maps[Expect_Index[index]].expect_Cost;
                record_index=index;
            }else if(expectCost==maps[Expect_Index[index]].expect_Cost){//= expect相同
                if(areadyCost>maps[Expect_Index[index]].already_Cost){//>对比 areadycost
                    areadyCost=maps[Expect_Index[index]].already_Cost;
                    record_index=index;
                }
            }
        }
        index++;
    }
    return record_index;
}


//循环计算欲走的路 并输出下一步的map
int ReckonTheExpect(int Expect_Index[],A_map maps[],A_map EndPoint,A_map *currentMap){
    //要先初始化float类型的变量要不然输出试一串-3242232+008
    int index=0;//下一步要走的下标
    int AlreadyCost=currentMap->already_Cost;//记录从起点到当前的消耗。
    int MHD_distance=0;
    //那就先计算消耗吧
    //cout<<"   Cost:"<<maps[Expect_Index[index]].Cost<<"\n";
    while(Expect_Index[index]!='\0'){
        //先计算曼哈距离 存入
        MHD_distance=GetExpect_Cost(maps[Expect_Index[index]].x,maps[Expect_Index[index]].y,EndPoint.x,EndPoint.y);
        maps[Expect_Index[index]].expect_Cost=MHD_distance;
        if(maps[Expect_Index[index]].x==currentMap->x||maps[Expect_Index[index]].y==currentMap->y){//上下左右
            maps[Expect_Index[index]].already_Cost=AlreadyCost+LINE;//横向加1      
        }else{
            maps[Expect_Index[index]].already_Cost=AlreadyCost+SKEW;//纵向加1.41
        }
    //  maps[Expect_Index[index]].expect_Cost=MHD_distance;

        maps[Expect_Index[index]].Cost=maps[Expect_Index[index]].already_Cost+maps[Expect_Index[index]].expect_Cost;

        cout<<"MHD_distance:"<<MHD_distance<<" Expect_Index[index]:"<< Expect_Index[index]<<"   Cost:"<<maps[Expect_Index[index]].Cost<<"\n";
        index++;
    }
    //测试输出的最佳路子,并且包出下一个节点的坐标
    cout<<"最佳路子:"<<Expect_Index[CompareToMap(maps,Expect_Index)]<<"  地图块的位置("<<maps[Expect_Index[CompareToMap(maps,Expect_Index)]].x<<","<<maps[Expect_Index[CompareToMap(maps,Expect_Index)]].y<<")\n";
    return Expect_Index[CompareToMap(maps,Expect_Index)]; 
}



//打印地图----------------------------------------------------------以下  辅助函数------------------------------------------------------

void PrintMap(A_map everyMap[]){
    for(int i=0;i<MapSize;i++){
        if(i%10==0){
            cout<<"\n";
        }
        cout<<everyMap[i].Map_symbol<<"-"<<"("<<everyMap[i].x<<","<<everyMap[i].y<<") ";
    }
    cout<<"\n------------------------------- map is already ok  ----------------------------\n\n";  
}

//打印检测形态
void PrintMap2(A_map everyMap[]){
    for(int i=0;i<MapSize;i++){
        if(i%10==0){
            cout<<"\n";
        }
        cout<<everyMap[i].Visit_symbol<<"-"<<"("<<everyMap[i].x<<","<<everyMap[i].y<<") ";
    }
    cout<<"\n------------------------------- ExpectMap is already ok  ----------------------------\n\n";    
}

//打印即将走的路线
void PrintExpect(int *expect_Point){
    int h=0;
    while(*(expect_Point+h)!='\0'){
        cout<<"index: "<<*(expect_Point+h++)<<" \n";
    }
    cout<<"   count:"<<h<<"\n";
    cout<<"\n------------------------------- printExpect is already ok  ----------------------------\n\n";
}

//--------------------------------------------------------以上 辅助函数--------------------------------------------------------------------



//将路径连接起来,并且改变symbol
void NextStep(A_map *currentMap,A_map maps[],int nextStep,int Expect_Index[]){
    //前面的位置检测
    cout<<"前一位置:("<<currentMap->x<<","<<currentMap->y<<")\n";
    int index=0;
    if(currentMap->Visit_symbol==3){//是3就跳1
        currentMap->Visit_symbol=1;
    }   
    //currentMap->next=&maps[nextStep];//当前路径指向下一个选定的路
    while(Expect_Index[index]!='\0'){
        maps[Expect_Index[index]].Visit_symbol=1;
        index++;
    }
    PrintMap2(maps);//地图下一步要检测的范围检测 

}




main(){

    cout<<"程序启动,初始化地图\n";   

    A_map currentMap;

    A_map everyMap[MapSize];//定义一个10*10的地图 100个map

    int goods[]={12,41,42,43,44,45,46,47,76};//记录  起点,障碍物的排列数字,终点的排列数字

    int *expect_Point;//定义指向像一个的指针
    //保存路线-定义-开始
    int keepStep[50];
    //keepStep的索引变量
    int keepStep_index=0;
    //保存路线-定义-结束
    int nextStep=0;//下一步 maps索引值 的记录
    //int init_i=0;//初始化循环变量
    /*测试结构体是否可用 
    eveyMap[0].Map_symbol=1;
    cout<<"eveyMap[0].Map_symbol: "<<eveyMap[0].Map_symbol;
    */
    /*
    地图绘制-参考
    1 1 1 1 1 1 1 1 1 1
    1 1 3 1 1 1 1 1 1 1
    1 1 1 1 1 1 1 1 1 1
    1 1 1 1 1 1 1 1 1 1
    1 2 2 2 2 2 2 2 1 1
    1 1 1 1 1 1 1 1 1 1
    1 1 1 1 1 1 1 1 1 1
    1 1 1 1 1 1 4 1 1 1
    1 1 1 1 1 1 1 1 1 1
    1 1 1 1 1 1 1 1 1 1
    1-(0,0) 1-(1,0) 1-(2,0) 1-(3,0) 1-(4,0) 1-(5,0) 1-(6,0) 1-(7,0) 1-(8,0) 1-(9,0)
    1-(0,1) 1-(1,1) 3-(2,1) 1-(3,1) 1-(4,1) 1-(5,1) 1-(6,1) 1-(7,1) 1-(8,1) 1-(9,1)
    1-(0,2) 1-(1,2) 1-(2,2) 1-(3,2) 1-(4,2) 1-(5,2) 1-(6,2) 1-(7,2) 1-(8,2) 1-(9,2)
    1-(0,3) 1-(1,3) 1-(2,3) 1-(3,3) 1-(4,3) 1-(5,3) 1-(6,3) 1-(7,3) 1-(8,3) 1-(9,3)
    1-(0,4) 2-(1,4) 2-(2,4) 2-(3,4) 2-(4,4) 2-(5,4) 2-(6,4) 2-(7,4) 1-(8,4) 1-(9,4)
    1-(0,5) 1-(1,5) 1-(2,5) 1-(3,5) 1-(4,5) 1-(5,5) 1-(6,5) 1-(7,5) 1-(8,5) 1-(9,5)
    1-(0,6) 1-(1,6) 1-(2,6) 1-(3,6) 1-(4,6) 1-(5,6) 1-(6,6) 1-(7,6) 1-(8,6) 1-(9,6)
    1-(0,7) 1-(1,7) 1-(2,7) 1-(3,7) 1-(4,7) 1-(5,7) 4-(6,7) 1-(7,7) 1-(8,7) 1-(9,7)
    1-(0,8) 1-(1,8) 1-(2,8) 1-(3,8) 1-(4,8) 1-(5,8) 1-(6,8) 1-(7,8) 1-(8,8) 1-(9,8)
    1-(0,9) 1-(1,9) 1-(2,9) 1-(3,9) 1-(4,9) 1-(5,9) 1-(6,9) 1-(7,9) 1-(8,9) 1-(9,9)
    */
    //goods元素计数-----------饿用到上面吧不知道为什么传入函数数组的长度会变成4能试sizeof出了指针的地址长度
    //printf("%d",sizeof(goods)/sizeof(int));

    MapInit(everyMap,goods);//地图初始化
    PrintMap(everyMap); //地图初始化检验

    currentMap=everyMap[goods[0]];//当前位置初始化,初始化的化,地图的当前位置就是起点

//★主要循环体,里面的函数对照上面的说明,可以看。
    while(nextStep!=goods[sizeof(goods)/sizeof(int)-1]){
            expect_Point=GetExpect_Map(currentMap,everyMap);//寻找下一个圈需要检测的,准备走的路
            nextStep=ReckonTheExpect(expect_Point,everyMap,everyMap[goods[sizeof(goods)/sizeof(int)-1]],&currentMap);
            cout<<"1  next-Step:"<<nextStep<<"\n";
            keepStep[keepStep_index++]=nextStep;//保存路径
            NextStep(&currentMap,everyMap,nextStep,expect_Point);
            currentMap=everyMap[nextStep];//这个就是让currentMap走到预定好的下一个位置。
            cout<<"\n★现在位置:("<<currentMap.x<<","<<currentMap.y<<")\n\n";
    }
    keepStep_index=0;
    //输出打印   (x,y)==》(x,y)==》……的路径格式
    while(keepStep[keepStep_index]!='\0'){      
            cout<<"("<<everyMap[keepStep[keepStep_index]].x<<","<<everyMap[keepStep[keepStep_index]].y<<")==>";
            keepStep_index++;
    }

    return 0;
}

———————————————————第一次写博客就很渣,而且代码写得也不好,所以大家见谅,为了更清楚我给大家做个关系图,看起来就清晰一点了。
简单的关系图

————-有问题和错误希望指出————-

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的C语言实现的A*算法: ```c #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #define ROW 5 #define COL 5 typedef struct { int x, y; } Point; typedef struct { Point parent; int f, g, h; } Node; Node map[ROW][COL]; Point start, end; bool is_valid(int x, int y) { return x >= 0 && x < ROW && y >= 0 && y < COL; } bool is_obstacle(int x, int y) { return map[x][y].f == -1; } int heuristic(int x, int y) { return abs(x - end.x) + abs(y - end.y); } void print_path() { Point path[ROW * COL]; int count = 0; Point current = end; while (current.x != start.x || current.y != start.y) { path[count++] = current; current = map[current.x][current.y].parent; } path[count++] = start; printf("Path: "); for (int i = count - 1; i >= 0; i--) { printf("(%d, %d) ", path[i].x, path[i].y); } printf("\n"); } void a_star() { int dx[8] = {-1, -1, 0, 1, 1, 1, 0, -1}; int dy[8] = {0, 1, 1, 1, 0, -1, -1, -1}; map[start.x][start.y].f = 0; map[start.x][start.y].g = 0; map[start.x][start.y].h = heuristic(start.x, start.y); Node open_set[ROW * COL]; int open_set_size = 1; open_set[0] = map[start.x][start.y]; while (open_set_size > 0) { int current_index = 0; for (int i = 1; i < open_set_size; i++) { if (open_set[i].f < open_set[current_index].f) { current_index = i; } } Node current = open_set[current_index]; if (current.parent.x == end.x && current.parent.y == end.y) { print_path(); return; } open_set[current_index] = open_set[open_set_size - 1]; open_set_size--; for (int i = 0; i < 8; i++) { int new_x = current.parent.x + dx[i]; int new_y = current.parent.y + dy[i]; if (!is_valid(new_x, new_y) || is_obstacle(new_x, new_y)) { continue; } int new_g = current.g + 1; int new_h = heuristic(new_x, new_y); int new_f = new_g + new_h; if (map[new_x][new_y].f == -2 || new_f < map[new_x][new_y].f) { map[new_x][new_y].parent = current.parent; map[new_x][new_y].f = new_f; map[new_x][new_y].g = new_g; map[new_x][new_y].h = new_h; if (map[new_x][new_y].f == -2) { open_set[open_set_size++] = map[new_x][new_y]; } } } } printf("No path found!\n"); } int main() { // initialize map for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { map[i][j].parent.x = i; map[i][j].parent.y = j; map[i][j].f = -2; map[i][j].g = -2; map[i][j].h = -2; } } // set obstacles map[1][1].f = -1; map[1][2].f = -1; map[1][3].f = -1; map[2][3].f = -1; map[3][3].f = -1; map[3][2].f = -1; // set start and end points start.x = 0; start.y = 0; end.x = 4; end.y = 4; // run A* algorithm a_star(); return 0; } ``` 这个程序实现了一个简单的A*算法,可以在一个5x5的地图上找到从起点到终点的最短径。其中,-1表示障碍物,-2表示未访问过的节点,其它数字表示已访问过的节点的f值。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值