代码中使用的链表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