【问题标题】:How to avoid cutting corners with A* pathfinding?如何避免使用 A* 寻路偷工减料?
【发布时间】:2013-07-05 15:15:34
【问题描述】:

在我第二次尝试使用 A* 时,我设法计算了回溯所需的所有值。还用 S 标记起始单元格,用 B 标记阻塞,用 F 标记目标单元格。

现在对于回溯,我将简单地跟随 G 值最低的单元格,从目标单元格开始。

这里我会遵循 G=24 => G=10 => S.

如您所见,此解决方案会创建一条无效的路径,因为在这种情况下它会穿过一堵墙。

在计算网格值时,这与切角一起挂起。正如你在这里看到的。一个人会回溯:G=50 => G= 40,接下来会取 G=20。这会导致切角。

我认为在计算每个相邻单元格的值时会出现此问题。如果在将相邻单元格添加到当前单元格时设置一些限制,也许可以避免这种情况?

public List<Cell> GetAdjacent(Cell _currentCell, List<Cell> _closedList, List<Cell> _gridList) 
    {
        List<Cell> adjacentList = new List<Cell>();
        List<Cell> gridList = _gridList;
        List<Cell> closedList = _closedList;
        Cell currentCell = _currentCell;

        foreach (Cell cell in gridList) 
        {
            bool containedInClosedList = closedList.Any(c => c.id == cell.id);

            if (!cell.blocked && !containedInClosedList && 
                ((cell.positionCR.X == currentCell.positionCR.X - 1 && cell.positionCR.Y == currentCell.positionCR.Y) ||
                (cell.positionCR.X == currentCell.positionCR.X + 1 && cell.positionCR.Y == currentCell.positionCR.Y) ||
                (cell.positionCR.X == currentCell.positionCR.X && cell.positionCR.Y == currentCell.positionCR.Y - 1) ||
                (cell.positionCR.X == currentCell.positionCR.X && cell.positionCR.Y == currentCell.positionCR.Y + 1) ||
                (cell.positionCR.X == currentCell.positionCR.X - 1 && cell.positionCR.Y == currentCell.positionCR.Y - 1) ||
                (cell.positionCR.X == currentCell.positionCR.X - 1 && cell.positionCR.Y == currentCell.positionCR.Y + 1) ||
                (cell.positionCR.X == currentCell.positionCR.X + 1 && cell.positionCR.Y == currentCell.positionCR.Y - 1) ||
                (cell.positionCR.X == currentCell.positionCR.X + 1 && cell.positionCR.Y == currentCell.positionCR.Y + 1)))
            {
                adjacentList.Add(cell);
            }

        }



        return adjacentList;
    }

我定义的自定义成本也会有问题吗?我对直线单元格取 G=10,对角单元格取 G=14。

我认为这是阻止我完成算法的最后一件事,所以我期待任何帮助或建设性意见。

提前致谢!

【问题讨论】:

  • 直线移动的成本指标为 10,对角线移动的成本指标为 14,这是合理的,但存在一个小问题。 A* 算法的正确性要求近似度量低估到目标的距离。如果您使用欧几里得度量作为近似值,那么您可能会 高估 14 到 10 倍根 2 之间的差异,大约为 1%。如此微小的高估不太可能产生非常糟糕的结果,但至少值得考虑是否有更好的权重来保持指标的可接受性。
  • 好吧,你告诉我:在路径中的一步拐角的所有情况是什么?它们只有四个,因此您应该能够轻松地枚举它们。
  • 所以这可能是一个重要的问题?
  • 您的切角问题不是权重问题。事实上,你完全允许这一步。您有一种确定相邻节点的方法;如果相邻节点会偷工减料,请不要将其添加到列表中。
  • 生成一个包含八个可能邻居的列表,然后检查每个邻居是否有效——在棋盘上,而不是偷工减料等。这样你就过滤了八件事,而不是一百万件事。

标签: c# path-finding


【解决方案1】:

正如 Eric 在上面的 cmets 中提到的,您可以生成一个包含八个可能邻居的列表,并检查它们是否有效。这里有效不仅仅意味着检查它们是否被阻塞,你还应该在这里检查切角。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-13
    • 2019-11-27
    • 1970-01-01
    • 2017-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多