A*算法

Astar.cpp

#include<math.h>
#include"Astar.h"
#include<iostream>
#include<vector>


static int *maze;	//迷宫对应的二维数组,用一级指针表示
static int cols;	//二维数组对应的列数
static int lines;	//二维数组对应的行数

static list<Point *> openlList;		//开放列表
static list<Point *> closeList;	//关闭列表


/*搜索从起点到终点的最佳路径*/
static Point* findPath(Point *startPoint, Point *endPoint);

/*从开启列表中返回F值最小的节点*/
static Point *getLeastFpoint();

/*获取当前点周围可达的节点*/
static vector<Point *> getSurroundPoints(const Point *point);

/*判断某点是否可以用于下一判断*/
static bool isCanreach(const Point *point, const Point *target);

/*判断开放/关闭列表中是否包含某点*/
static Point *isInList(const list<Point *> &list, const Point *point);

/*计算FGH值*/
static int calcG(Point *temp_start, Point *point);
static int calcH(Point *point, Point *end);
static int calcF(Point *point);


/*分配一个节点(格子)*/
Point* AllocPoint(int x, int y)
{
	Point *temp = new Point;

	memset(temp, 0, sizeof(Point));//初始化清零

	temp->x = x;
	temp->y = y;
	return temp;
}


/*初始化A*搜索的地图*/
void InitAstarMaze(int *_maze, int _lines, int _colums)
{
	maze = _maze;
	lines = _lines;
	cols = _colums;
}

/*通过A*算法寻找路径*/
list<Point *> GetPath(Point *startPoint, Point *endPoint)
{
	Point *result = findPath(startPoint, endPoint);

	list<Point *> path;

	//返回路径,如果没有找到路径,返回空链表
	while (result)
	{
		path.push_front(result);
		result = result->parent;
	}

	return path;
}

/*搜索从起点到终点的最佳路径*/
static Point* findPath(Point *startPoint, Point *endPoint)
{
	openlList.push_back(AllocPoint(startPoint->x,startPoint->y));//置入起点,拷贝开辟一个节点,内外隔离

	while (!openlList.empty())
	{
		//第一步,从开放列表中取最小F的节点
		Point *curPoint = getLeastFpoint();	//找到F值最小的点

		//第二步,把当前节点放到关闭列表中
		openlList.remove(curPoint);
		closeList.push_back(curPoint);

		//第三步,找到当前节点周围可达的节点,并计算F值
		vector<Point *> surroundPoints = getSurroundPoints(curPoint);

		vector<Point *>::const_iterator iter;
		for (iter = surroundPoints.begin(); iter != surroundPoints.end(); iter++)
		{
			Point *target = *iter;

			//对某一个格子,如果它不在开放列表中,加入到开放列表,设置当前格为父节点,计算F G H
			Point *exist = isInList(openlList, target);

			if (!exist)
			{
				target->parent = curPoint;

				target->G = calcG(curPoint, target);
				target->H = calcH(target, endPoint);
				target->F = calcF(target);

				openlList.push_back(target);
			}
			else
			{
				int tempG = calcG(curPoint, target);
				if (tempG < target->G)
				{
					exist->parent = curPoint;
					exist->G = tempG;
					exist->F = calcF(target);
				}

				delete target;
			}
		}//end for
		surroundPoints.clear();

		Point *resPoint = isInList(openlList, endPoint);
		if (resPoint)
		{
			return resPoint;
		}
	}
	return NULL;
}

/*从开启列表中返回F值最小的节点*/
static Point *getLeastFpoint()
{
	if (!openlList.empty())
	{
		Point *resPoint = openlList.front();

		list<Point *>::const_iterator itor;
		for (itor = openlList.begin(); itor != openlList.end(); itor++)
		{
			if ((*itor)->F < resPoint->F)
			{
				resPoint = *itor;
			}
		}
		return resPoint;
	}
	return NULL;
}

/*获取当前点周围可达的节点*/
static vector<Point *> getSurroundPoints(const Point *point)
{
	vector<Point *> surroundPoints;

	for (int x = point->x - 1; x < point->x + 1; x++)
	{
		for (int y = point->y - 1; y < point->y + 1; y++)
		{
			Point *temp = AllocPoint(x, y);
			if (isCanreach(point, temp))
			{
				surroundPoints.push_back(temp);
			}
			else
			{
				delete temp;
			}
		}
	}
	return surroundPoints;
}

/*判断某点是否可以用于下一判断*/
static bool isCanreach(const Point *point, const Point *target)
{
	if (target->x<0 || target->x>(lines - 1)		//行不能越界
		|| target->y<0 || target->y>(cols - 1)		//列不能越界
		|| maze[target->x*cols + target->y] == 1	//判断当前格子是否为障碍
		|| maze[target->x*cols + target->y] == 2	//判断当前格子是否为障碍
		|| (target->x == point->x &&target->y == point->y)	//不能跟当前点重叠
		|| isInList(closeList, target))	//判断是否在封闭列表里面
	{
		return false;
	}

	if ((abs(point->x - target->x) + abs(point->y - target->y)) == 1)
	{
		return true;
	}
	else
	{
		return false;
	}
}

/*判断开放/关闭列表中是否包含某点*/
static Point *isInList(const std::list<Point *> &list, const Point *point)
{
	//判断某个节点是否在列表中,这里不能比较指针,因为每次加入列表是新开辟的节点,只能比较坐标
	std::list<Point *>::const_iterator itor;
	for (itor = list.begin(); itor != list.end(); itor++)
	{
		if ((*itor)->x == point->x && (*itor)->y == point->y)
		{
			return *itor;
		}
	}
	return NULL;
}

/*计算FGH值*/
static int calcG(Point *temp_start, Point *point)
{
	int extraG = (abs(point->x - temp_start->x) + abs(point->y - temp_start->y)) == 1 ? kCost1 : kCost2;
	//如果是初始节点,则其父节点是空
	int parentG = (point->parent == NULL ? NULL : point->parent->G);

	return parentG + extraG;
}
static int calcH(Point *point, Point *end)
{
	//用简单的欧几里得距离计算H
	return (int)sqrt((double)(end->x - point->x)*(double)(end->x - point->x) + (double)(end->y - point->y)*(double)(end->y - point->y))*kCost1;
}
static int calcF(Point *point)
{
	return point->G + point->H;
}

/*清理资源,结束后必须调用*/
void ClearAstarMaze()
{
	maze = NULL;
	lines = 0;
	cols = 0;

	list<Point *>::iterator itor;

	//清除openList 中的元素
	for (itor = openlList.begin(); itor != openlList.end();)
	{
		delete *itor;
		itor = openlList.erase(itor);//获取下一个节点
	}

	//清理closeList 中的元素
	for (itor = closeList.begin(); itor != closeList.end();)
	{
		delete *itor;
		itor = closeList.erase(itor);//获取下一个节点
	}
}

Astar.h

#pragma once

#include<list>

using namespace std;

const int kCost1 = 10;//直移一格消耗
const int kCost2 = 12;//斜移一格消耗

typedef struct _Point
{
	int x, y;		//点坐标
	int F, G, H;	//F=G+H
	struct _Point *parent;	//parent的坐标
}Point;


/*分配一个节点*/
Point* AllocPoint(int x, int y);

/*初始化地图*/
void InitAstarMaze(int *_maze, int _lines, int _colums);

/*通过A*算法寻找路径*/
list<Point *> GetPath(Point *startPoint, Point *endPoint);

/*清理资源,结束后必须调用*/
void ClearAstarMaze();

main.cpp

#include"Astar.h"
#include<iostream>
#include<list>
#include<Windows.h>

using namespace std;

//定义地图数组
int map[13][13] =
{
	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
	{0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,},
	{0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,},
	{0, 1, 0, 1, 0, 1, 2, 1, 0, 1, 0, 1, 0,},
	{0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,},
	{0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0,},
	{0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0,},
	{2, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 2,},
	{0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,},
	{0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,},
	{0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,},
	{0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,},
	{0, 0, 0, 0, 0, 1, 3, 1, 0, 0, 0, 0, 0,},
};


void AStarTest()
{
	InitAstarMaze(&map[0][0], 13, 13);

	//设置起始和结束点
	Point* start = AllocPoint(12, 4);
	Point* end = AllocPoint(0, 0);

	//A*算法找寻路径
	list<Point *> path = GetPath(start, end);

	cout << "寻路结果:" << endl;

	list<Point *>::const_iterator iter;
	for (iter = path.begin(); iter != path.end(); iter++)
	{
		Point *cur = *iter;
		cout << '(' << cur->x << ',' << cur->y << ')' << endl;

		Sleep(800);
	}

	ClearAstarMaze();
}


int main()
{
	AStarTest();

	system("pause");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值