第七章:寻路算法:A星寻路

7 篇文章 0 订阅
3 篇文章 0 订阅

1.介绍
1.1.A星寻路是在广度寻路的基础上更加智能。
1.2.它是以周围八格中f值最小的作为下一步,一直到终点。这里引入了一个代价的概念。
代价:f = g +h
f:代价总值
g:起点到当前点走过的路线价值
h:当前点到终点的直线待评估值

2.看图
在这里插入图片描述
3.步骤
创建一个八叉树,开始吧起点当做树根,吧周围八格能走的路存入临时动态数组,下一次在数组中选择f值最小的格子作为下一步,直到终点。
4.代码区

#include<iostream>
#include<stdlib.h>
#include<vector>
using namespace std;

#define ROWS 10
#define COLS 10
#define ZXDJ 10   //直线代价
#define XXDJ 14   //斜线代价

//枚举方向
enum direct{p_up,p_left,p_down,p_right,p_lup,p_ldown,p_rdown,p_rup};

//点类
class MyPoint
{
public:
	int x;
	int y;
	int f;
	int g;
	int h;
};

//节点类
class treeNode
{
public:
	MyPoint pos;
	treeNode * pParent;
	vector<treeNode *> pChild;
	treeNode(MyPoint pos1)
	{
		pos = pos1;
		pParent = NULL;
	}
};

//测试地图类
class testMap
{
public:
	bool IsFind;
};

//能不能走
bool canWalk(int map[ROWS][COLS], testMap testmap[ROWS][COLS], MyPoint pos)
{
	//如果是障碍
	if (map[pos.x][pos.y] == 1) return false;

	//不在地图内
	if (pos.x < 0 || pos.x >= ROWS || pos.y < 0 || pos.y >= COLS) return false;

	//已经走过
	if (testmap[pos.x][pos.y].IsFind == true) return false;

	return true;
}

//求H值
int setH(const MyPoint currentPos,const MyPoint endPos)
{
	int x = endPos.x-currentPos.x;
	int y = endPos.y-currentPos.y;

	return (x + y)*ZXDJ;
}

//求F值
int setF(int g,int h)
{
	return (g + h);
}

int main()
{
	//1.寻路前准备
	//1.1地图
	int map[ROWS][COLS] = {
		0,0,0,1,0,0,0,0,0,0,
		0,0,0,1,0,0,0,0,0,0,
		0,0,0,1,0,0,0,0,0,0,
		0,0,0,1,0,0,0,0,0,0,
		0,0,0,1,0,0,0,0,0,0,
		0,0,0,1,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0,0,0,
		0,0,0,1,0,0,0,0,0,0,
		0,0,0,1,0,0,0,0,0,0,
		0,0,0,1,0,0,0,0,0,0
	};
	//1.2测试地图
	testMap testmap[ROWS][COLS] = { 0 };

	//1.3设置起点和终点
	MyPoint begPos = { 1,1 };
	MyPoint endPos = { 7,8 };

	//1.4标记起点已经走过
	testmap[begPos.x][begPos.y].IsFind = true;

	//1.5准备八叉树
	treeNode *pRoot = new treeNode(begPos); //吧开始起点作为树根

	//1.6当前节点  吧开始节点作为当前节点
	treeNode * p_CurrentNode = pRoot;

	//1.7
	vector<treeNode *> buffer ;
	vector<treeNode *> ::iterator it; 
	vector<treeNode *> ::iterator Minit;//用来管理最小的
	//1.8临时点
	treeNode * pChild;

	//是否找到终点
	bool IsFindEnd = false;

	//定义一个是否需要寻找的变量作为while()循环条件
	bool IsNeedFind = true;
	//2.开始寻路
	while (IsNeedFind)
	{
		//在当前点中
		for (int i = 0; i < 8; i++)
		{
			pChild = new treeNode(p_CurrentNode->pos);
			switch(i)
			{
				//2.1 g值增加
				//直着走
			case p_up:
				pChild->pos.y --;
				pChild->pos.g += ZXDJ;
				break;
			case p_left:
				pChild->pos.x--;
				pChild->pos.g += ZXDJ;
				break;
			case p_down:
				pChild->pos.y++;
				pChild->pos.g += ZXDJ;
				break;
			case p_right:
				pChild->pos.x++;
				pChild->pos.g += ZXDJ;
				break;
				//斜着走
			case p_lup:
				pChild->pos.x--;
				pChild->pos.y--;
				pChild->pos.g += XXDJ;
			case p_ldown:
				pChild->pos.x--;
				pChild->pos.y++;
				pChild->pos.g += XXDJ;
			case p_rdown:
				pChild->pos.x++;
				pChild->pos.y++;
				pChild->pos.g += XXDJ;
			case p_rup:
				pChild->pos.x++;
				pChild->pos.y--;
				pChild->pos.g += XXDJ;
			}
			//判断能不能走
			if (canWalk(map, testmap, pChild->pos))
			{
				//2.2入树
				p_CurrentNode->pChild.push_back(pChild);

				//2.3存入数组中
				buffer.push_back(pChild);

				//2.4计算h值
				pChild->pos.h = setH(pChild->pos , endPos);

				//2.5计算f值
				pChild->pos.f = setF(pChild->pos.g, pChild->pos.h);

				
			}
			else
			{
				//如果不能走释放空间
				delete pChild;
			}
		}//end of(i)
		//3寻路后

		//3.1选择f值最小的点
		Minit = buffer.begin();//默认为开始的点
		for (it = buffer.begin(); it < buffer.end(); it++)
		{
			if ((*Minit)->pos.f > (*it)->pos.f)
				Minit = it;
		}
		
		//3.2当前点切换成f值最小的点
		p_CurrentNode = (*Minit);
		p_CurrentNode->pParent = pChild;
		//3.3最小的点从buff中删除
		buffer.erase(Minit);

		//3.4如果是终点
		if (p_CurrentNode->pos.x == endPos.x && p_CurrentNode->pos.y == endPos.y)
		{
			IsNeedFind = false;
			IsFindEnd = true;
			break;
		}

		//3.5如果buffer为空
		if (buffer.empty())
			break;

	}//end of(while(1))

	if (IsFindEnd)
	{
		while (p_CurrentNode)
		{
			printf("路径是:\n");
			printf("(%d,%d)\n", p_CurrentNode->pos.x, p_CurrentNode->pos.y);
			p_CurrentNode = p_CurrentNode->pParent;
		}
		
		printf("找到终点啦");
	}

	return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
A寻路算法(A*算法)是一种常用于解决路径寻找问题的算法,特别适用于在网格图中寻找最短路径。下面是一个使用PHP实现A*算法的简单示例: ```php <?php class Node { public $x; public $y; public $f; public $g; public $h; public $parent; function __construct($x, $y) { $this->x = $x; $this->y = $y; $this->f = 0; $this->g = 0; $this->h = 0; $this->parent = null; } } function astar($start, $goal, $grid) { $open = array(); $closed = array(); $start->g = 0; $start->h = heuristic($start, $goal); $start->f = $start->g + $start->h; array_push($open, $start); while (!empty($open)) { $current = $open[0]; foreach ($open as $node) { if ($node->f < $current->f || ($node->f == $current->f && $node->h < $current->h)) { $current = $node; } } $key = array_search($current, $open); array_splice($open, $key, 1); array_push($closed, $current); if ($current->x == $goal->x && $current->y == $goal->y) { $path = array(); while ($current->parent) { array_push($path, $current); $current = $current->parent; } return array_reverse($path); } $neighbors = getNeighbors($current, $grid); foreach ($neighbors as $neighbor) { $gScore = $current->g + 1; $hScore = heuristic($neighbor, $goal); $fScore = $gScore + $hScore; if (in_array($neighbor, $closed) && $fScore >= $neighbor->f) { continue; } if (!in_array($neighbor, $open) || $fScore < $neighbor->f) { $neighbor->g = $gScore; $neighbor->h = $hScore; $neighbor->f = $fScore; $neighbor->parent = $current; if (!in_array($neighbor, $open)) { array_push($open, $neighbor); } } } } return null; } function heuristic($node, $goal) { return abs($node->x - $goal->x) + abs($node->y - $goal->y); } function getNeighbors($node, $grid) { $neighbors = array(); $offsets = array(array(-1, -1), array(-1, 0), array(-1, 1), array(0, -1), array(0, 1), array(1, -1), array(1, 0), array(1, 1)); foreach ($offsets as $offset) { $x = $node->x + $offset[0]; $y = $node->y + $offset[1]; if ($x >= 0 && $x < count($grid) && $y >= 0 && $y < count($grid[0]) && $grid[$x][$y] != 1) { array_push($neighbors, new Node($x, $y)); } } return $neighbors; } // 测试 $grid = array( array(0, 0, 0, 0), array(1, 1, 0, 1), array(0, 0, 0, 0), array(0, 0, 0, 0) ); $start = new Node(0, 0); $goal = new Node(3, 3); $path = astar($start, $goal, $grid); if ($path) { foreach ($path as $node) { echo "(" . $node->x . ", " . $node->y . ") "; } } else { echo "No Path Found"; } ?> ``` 上述代码实现了A*寻路算法,其中`astar`函数用于执行算法的主要逻辑,`heuristic`函数用于计算启发式函数的值,`getNeighbors`函数用于获取节点的相邻节点。在给定的网格图中,我们从起点`(0, 0)`到目标点`(3, 3)`寻找最短路径。路径的结果将根据节点坐标依次打印出来。若找不到路径,则输出"No Path Found"。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值