现在的位置: 首页 > 综合 > 正文

A*算法(二)

2013年10月02日 ⁄ 综合 ⁄ 共 7271字 ⁄ 字号 评论关闭

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

抱歉!评论已关闭.