我在一个简单的Winforms应用程序中实现了A * -pathfinding。人们还可以在网格上定义障碍物,以便代理人可以在他们周围进行导航。
问题是我的经纪人无法预见路径。这就是为什么他并不总是采取最佳路径。
Here you can see my exact problem.
如何让探路者预测较短的路径?一旦代理人采取错误的道路,死角也会出现问题。
此方法获取相邻单元格并计算值:
public void addAdjascent(Vector pos)
{
foreach(Cell cell in allCells)
{
bool containedInClosedList = closedList.Any(c => c.id == cell.id);
if (!containedInClosedList)
{
if (cell.positionCR.X == pos.X - 1 && cell.positionCR.Y == pos.Y)
{
bool containedInBlockedList = blockedList.Any(c => c.id == cell.id);
if(!containedInBlockedList)
{
cell.H = calcH(goal,cell);
cell.G = calcG(start, cell);
cell.F = cell.G + cell.H;
openList.Add(cell);
}
}
if (cell.positionCR.X == pos.X + 1 && cell.positionCR.Y == pos.Y)
{
bool containedInBlockedList = blockedList.Any(c => c.id == cell.id);
if (!containedInBlockedList)
{
cell.H = calcH(goal, cell);
cell.G = calcG(start, cell);
cell.F = cell.G + cell.H;
openList.Add(cell);
}
}
if (cell.positionCR.X == pos.X && cell.positionCR.Y == pos.Y - 1)
{
bool containedInBlockedList = blockedList.Any(c => c.id == cell.id);
if (!containedInBlockedList)
{
cell.H = calcH(goal, cell);
cell.G = calcG(start, cell);
cell.F = cell.G + cell.H;
openList.Add(cell);
}
}
if (cell.positionCR.X == pos.X && cell.positionCR.Y == pos.Y + 1)
{
bool containedInBlockedList = blockedList.Any(c => c.id == cell.id);
if (!containedInBlockedList)
{
cell.H = calcH(goal, cell);
cell.G = calcG(start, cell);
cell.F = cell.G + cell.H;
openList.Add(cell);
}
}
if (cell.positionCR.X == pos.X - 1 && cell.positionCR.Y == pos.Y - 1)
{
bool containedInBlockedList = blockedList.Any(c => c.id == cell.id);
if (!containedInBlockedList)
{
cell.H = calcH(goal, cell);
cell.G = calcG(start, cell);
cell.F = cell.G + cell.H;
openList.Add(cell);
}
}
if (cell.positionCR.X == pos.X - 1 && cell.positionCR.Y == pos.Y + 1)
{
bool containedInBlockedList = blockedList.Any(c => c.id == cell.id);
if (!containedInBlockedList)
{
cell.H = calcH(goal, cell);
cell.G = calcG(start, cell);
cell.F = cell.G + cell.H;
openList.Add(cell);
}
}
if (cell.positionCR.X == pos.X + 1 && cell.positionCR.Y == pos.Y - 1)
{
bool containedInBlockedList = blockedList.Any(c => c.id == cell.id);
if (!containedInBlockedList)
{
cell.H = calcH(goal, cell);
cell.G = calcG(start, cell);
cell.F = cell.G + cell.H;
openList.Add(cell);
}
}
if (cell.positionCR.X == pos.X + 1 && cell.positionCR.Y == pos.Y + 1)
{
bool containedInBlockedList = blockedList.Any(c => c.id == cell.id);
if (!containedInBlockedList)
{
cell.H = calcH(goal, cell);
cell.G = calcG(start, cell);
cell.F = cell.G + cell.H;
openList.Add(cell);
}
}
}
}
}
以下是计算G和H值的代码:
public int calcG(Vector start,Cell cell)
{
int distance = closedList.Count;
return distance;
}
public int calcH(Vector goal, Cell cell)
{
int distance;
int distanceX = (goal.X) - cell.positionCR.X;
int distanceY = (goal.Y) - cell.positionCR.Y;
if (distanceX < 0)
{
distanceX = distanceX * -1;
}
if (distanceY < 0)
{
distanceY = distanceY * -1;
}
distance = distanceX + distanceY;
return distance;
}
最后我计算了我想要踩的下一个单元格:
public void step()
{
addAdjascent(stepPos);
bool foundDestination = false;
int min = 8000;
foreach(Cell openCell in openList)
{
if (openCell.F < min)
{
min = openCell.F;
}
}
if(openList.Count > 0)
{
foreach (Cell openCell in openList)
{
if (openCell.positionCR.X == goal.X && openCell.positionCR.Y == goal.Y)
{
closedList.Add(openCell);
stepPos = openCell.positionCR;
foundDestination = true;
}
}
}
if(!foundDestination)
{
closedList.Add(openList.First(item => item.F == min));
stepPos = openList.First(item => item.F == min).positionCR;
}
openList.Clear();
}
答案 0 :(得分:3)
Dijkstra有一个类似的问题,虽然他是基于权重的。
它可能有助于Peek()的位置,然后评估它从所有位置的Peek()。Peek()移动的能力。与可导航路径相比,任何不能使用的位置都可能具有极高的权重。
但是这些算法可以完全使用递归来解决,然后从那里选择最佳路线。
(我也注意到你在视频中对角移动了,这实际上是一个有效的移动,因为直接向上移动将具有2个方格的相同净距离。)
答案 1 :(得分:3)
您的实施问题是您尚未完全实现A *算法。您已经(在step
方法中)实现了算法中单个步骤的下一个最佳猜测。
算法应该完全执行,直到达到结束,并且打开的列表中不再有更短的路径(估计)。完成此操作后,您可以从结果中构建最短路径。然后你就可以迈出正确的一步。
在没有实际计算整个路径的情况下,A *从来没有打算立即回答你的下一步应该是什么。如果正确实施,它将为您提供最佳路径,只要您的启发式算法估计给定点的余数从不过高估计实际剩余距离。
我建议进一步阅读如何实现A *算法。一个好的开始可能是wikipedia。
答案 2 :(得分:2)
A *不是找到最佳路径的算法 - 如果最佳路径是你必须使用蛮力方法之后。 A *(基于启发式函数的质量)找到接近最优的路径。
答案 3 :(得分:2)
如果正确实现A *生成非最佳路径,我认为你有一个不可接受的启发式。允许的启发式方法绝不能过高估计到目标的剩余距离。如果是这样,您在视频中显示的内容就会发生。