代码中使用的链表List为作者自己写的,不是标准库的。原文章未把自写List粘贴出来,所以想要看List这部分代码的,可以去作者提供的地址下载,一个叫A星算法自寻路的文件,里面有控制台、win32和精灵三个版本的A*算法演示程序,还有List的源文件,地址:lj56456311.ys168.com/
作者把A星算法封装成了一个类(Astart),大家可以通过代码来学习。
/// //Astart.h /// #pragma once #include "List.h" class Rect //结点,也就是每个格子 { public: int map_x; //在地图中的列数 int map_y; //在地图中的行数 int h_value; // H值 int g_value; // G值 Rect *pre; // 父结点指针 }; class Astart { public: //构造函数中 a 为一个二维数组,代表地图,这个类有个缺点就是使用不 //同大小的地图时你得手动修改这里的a[10][10]和下面的map[10][10]的大小 //w为地图的列数,l为地图的行数,s为起点结点编号,e为终点结点编号; Astart(int a[10][10],int w,int l,int s,int e); ~Astart(void); bool Find(); //寻找最短路径 int get_h_value(int i); //获取H值 int get_g_value(int i); //获取G值 void GetResult(); //获取结果,让最短路径的结点值修改为2 int map[10][10]; //地图对象,用来保存构造函数中传递进来的地图信息,这里的大小也要实际运用来改变 private: Rect *rect; //结点指针,最后通过该指针来遍历最短路径 int WIDTH; //地图的列数 int LENGTH; //地图的行数 int start; //起点结点编号 int end; //终点结点编号 List<int> open_list; //OPEN表 List<int> close_list; //CLOSE表 };
/// //Astart.cpp /// #include <math.h>#include ".\astart.h" #include "List.cpp" #include <math.h> Astart::Astart(int a[10][10],int w,int l,int s,int e) { for(int i=0; i<l; i++) { for(int j=0; j<w; j++) { map[i][j] = a[i][j]; } } WIDTH = w; start = s; end = e; LENGTH = l; rect = new Rect[WIDTH*LENGTH]; for(int i=0; i<WIDTH*LENGTH; i++) { rect[i].map_x = i%WIDTH; rect[i].map_y = i/WIDTH; } rect[start].g_value = 0; rect[start].pre = NULL; } Astart::~Astart(void) { } bool Astart::Find() { if(close_list.IsEmpty()) { if((start+WIDTH)/WIDTH < LENGTH && (start+WIDTH)/WIDTH >=0 && (start+WIDTH)%WIDTH >=0&& (start+WIDTH)%WIDTH < WIDTH) { if( map[(start+WIDTH)/WIDTH][(start+WIDTH)%WIDTH]!=1 ) { rect[start+WIDTH].pre = &rect[start]; rect[start+WIDTH].h_value = get_h_value(start+WIDTH); rect[start+WIDTH].g_value = get_g_value(start+WIDTH); open_list.Insert(open_list.Length(),start+WIDTH); } } if((start-WIDTH)/WIDTH < LENGTH && (start-WIDTH)/WIDTH >=0 && (start-WIDTH)%WIDTH >= 0 &&(start-WIDTH)%WIDTH < WIDTH) { if( map[(start-WIDTH)/WIDTH][(start-WIDTH)%WIDTH]!=1) { rect[start-WIDTH].pre = &rect[start]; rect[start-WIDTH].h_value = get_h_value(start-WIDTH); rect[start-WIDTH].g_value = get_g_value(start-WIDTH); open_list.Insert(open_list.Length(),start-WIDTH); } } if((start+1)/WIDTH < LENGTH && (start+1)/WIDTH >=0 && (start+1)%WIDTH >= 0 && (start+1)%WIDTH < WIDTH) { if( map[(start+1)/WIDTH][(start+1)%WIDTH]!=1) { rect[start+1].pre = &rect[start]; rect[start+1].h_value = get_h_value(start+1); rect[start+1].g_value = get_g_value(start+1); open_list.Insert(open_list.Length(),start+1); } } if((start-1)/WIDTH < LENGTH && (start-1)/WIDTH >=0 && (start-1)%WIDTH >= 0 && (start-1)%WIDTH < WIDTH) { if( map[(start-1)/WIDTH][(start-1)%WIDTH]!=1) { rect[start-1].pre = &rect[start]; rect[start-1].h_value = get_h_value(start-1); rect[start-1].g_value = get_g_value(start-1); open_list.Insert(open_list.Length(),start-1); } } close_list.Insert(close_list.Length(),start); } int i = 0; int num = -1; int rectcount = 0; for(int z=1; z<=open_list.Length(); z++) { int counttemp,numtemp; open_list.Find(z,counttemp); numtemp = rect[counttemp].h_value + rect[counttemp].g_value; if(num==-1) { num = numtemp; } if(numtemp <= num) { i = z; num = numtemp; rectcount = counttemp; } } int temp; if(i==0) { return false; } open_list.Delete(i,temp); close_list.Insert(close_list.Length(),rectcount); if((rectcount+WIDTH)/WIDTH < LENGTH && (rectcount+WIDTH)/WIDTH >=0 && (rectcount+WIDTH)%WIDTH >= 0 && (rectcount+WIDTH)%WIDTH < WIDTH) { if(rectcount+WIDTH == end) { rect[rectcount+WIDTH].pre = &rect[rectcount]; return true; } if( map[(rectcount+WIDTH)/WIDTH][(rectcount+WIDTH)%WIDTH]!=1 ) { if(close_list.Search(rectcount+WIDTH) == 0) { if(open_list.Search(rectcount+WIDTH) == 0) { rect[rectcount+WIDTH].pre = &rect[rectcount]; rect[rectcount+WIDTH].h_value = get_h_value(rectcount+WIDTH); rect[rectcount+WIDTH].g_value = get_g_value(rectcount+WIDTH); open_list.Insert(open_list.Length(),rectcount+WIDTH); } else { if(rect[rectcount].g_value + 10 < rect[rectcount+WIDTH].g_value) { rect[rectcount+WIDTH].pre = &rect[rectcount]; rect[rectcount+WIDTH].g_value = get_g_value(rectcount+WIDTH); } } } } } if((rectcount-WIDTH)/WIDTH < LENGTH && (rectcount-WIDTH)/WIDTH >=0 && (rectcount-WIDTH)%WIDTH >= 0 && (rectcount-WIDTH)%WIDTH < WIDTH) { if(rectcount-WIDTH == end) { rect[rectcount-WIDTH].pre = &rect[rectcount]; return true; } if( map[(rectcount-WIDTH)/WIDTH][(rectcount-WIDTH)%WIDTH]!=1) { if(close_list.Search(rectcount-WIDTH) == 0) { if(open_list.Search(rectcount-WIDTH) == 0) { rect[rectcount-WIDTH].pre = &rect[rectcount]; rect[rectcount-WIDTH].h_value = get_h_value(rectcount-WIDTH); rect[rectcount-WIDTH].g_value = get_g_value(rectcount-WIDTH); open_list.Insert(open_list.Length(),rectcount-WIDTH); } else { if(rect[rectcount].g_value + 10 < rect[rectcount-WIDTH].g_value) { rect[rectcount-WIDTH].pre = &rect[rectcount]; rect[rectcount-WIDTH].g_value = get_g_value(rectcount-WIDTH); } } } } } if((rectcount+1)/WIDTH < LENGTH && (rectcount+1)/WIDTH >=0 && (rectcount+1)%WIDTH >= 0 && (rectcount+1)%WIDTH < WIDTH && rectcount%(WIDTH-1)!=0) { if(rectcount+1 == end) { rect[rectcount+1].pre = &rect[rectcount]; return true; } if( map[(rectcount+1)/WIDTH][(rectcount+1)%WIDTH]!=1) { if(close_list.Search(rectcount+1) == 0) { if(open_list.Search(rectcount+1) == 0) { rect[rectcount+1].pre = &rect[rectcount]; rect[rectcount+1].h_value = get_h_value(rectcount+1); rect[rectcount+1].g_value = get_g_value(rectcount+1); open_list.Insert(open_list.Length(),rectcount+1); } else { if(rect[rectcount].g_value + 10 < rect[rectcount+1].g_value) { rect[rectcount+1].pre = &rect[rectcount]; rect[rectcount+1].g_value = get_g_value(rectcount+1); } } } } } if((rectcount-1)/WIDTH < LENGTH && (rectcount-1)/WIDTH >=0 && (rectcount-1)%WIDTH >= 0 && (rectcount-1)%WIDTH < WIDTH && rectcount%WIDTH!=0) { if(rectcount-1 == end) { rect[rectcount-1].pre = &rect[rectcount]; return true; } if( map[(rectcount-1)/WIDTH][(rectcount-1)%WIDTH]!=1) { if(close_list.Search(rectcount-1) == 0) { if(open_list.Search(rectcount-1) == 0) { rect[rectcount-1].pre = &rect[rectcount]; rect[rectcount-1].h_value = get_h_value(rectcount-1); rect[rectcount-1].g_value = get_g_value(rectcount-1); open_list.Insert(open_list.Length(),rectcount-1); } else { if(rect[rectcount].g_value + 10 < rect[rectcount-1].g_value) { rect[rectcount-1].pre = &rect[rectcount]; rect[rectcount-1].g_value = get_g_value(rectcount-1); } } } } } return Find(); } int Astart::get_h_value(int i) { return ((abs(end/WIDTH - i/WIDTH) + abs(end%WIDTH - i%WIDTH)) * 10); } int Astart::get_g_value(int i) { return (rect[i].pre->g_value + 10); } void Astart::GetResult() { Rect *p = &rect[end]; while(p != NULL) { map[p->map_y][p->map_x] = 2; p = p->pre; } }
/// //main.cpp /// #include <iostream> #include "Astart.h" #include "List.h" #include "List.cpp" using namespace std; const int WIDTH = 10; //地图列数 const int LENGTH = 10; //地图行数 Rect rect[WIDTH*LENGTH];//定义rect数组,存放所有格子rect[0]代表0号格子一直到rect[WIDTH*LENGTH]; List<int> open_list; List<int> close_list; int start = 0; //起点编号为0(左上角) int end = 99; //终点编号为99(右下角) //地图信息 int map[10][10]={ {0,0,1,0,0,0,0,1,0,0}, {0,0,1,1,0,0,0,1,0,0}, {1,0,0,0,1,0,0,1,0,0}, {1,0,1,1,1,1,1,1,0,0}, {1,0,0,0,0,0,0,1,0,0}, {1,0,0,0,0,0,0,1,0,0}, {1,0,0,0,0,0,0,1,0,0}, {1,0,0,0,0,0,0,1,0,0}, {1,0,0,0,0,0,0,0,0,0}, {1,0,0,0,0,0,0,1,0,0} }; //主函数 void main() { Astart a(map,WIDTH,LENGTH,start,end); if(!a.Find()) { cout<<"无可到达的路线!"<<endl; return; } a.GetResult(); for(int i=0;i<LENGTH;i++) { for(int j=0;j<WIDTH;j++) { cout<<a.map[i][j]<<" "; } cout<<endl; } }
转载自: http://hi.baidu.com/%BA%DA%B5%C4%B7%A2%D7%CF/blog/item/ded949953be42e4ed0135ef3.html