【问题标题】:Solving logic game Lights out with A* algorithm用 A* 算法解决逻辑游戏熄灯
【发布时间】:2019-05-27 22:36:36
【问题描述】:

我在使用 A* 算法解决名为 Lights out 的逻辑难题时遇到了一些问题。目前,我正在使用 A* 算法的实现,其中我将整个灯光矩阵视为算法中的一个节点(其中 1 代表灯亮,0 代表灯熄灭)以及当前节点的坐标这将被切换。从打开列表中选择 f 分数最低的节点后,我将切换它并获取其 8 个相邻邻居,然后将它们附加到打开列表并重复,直到找到所有灯的总和等于的节点0(所有灯都关闭)。

为了计算每个节点的 f 分数,我只是计算其本地矩阵中所有灯的总和,因此每次选择具有最少灯数的矩阵的节点。

我知道该算法的性能不会那么好,即使与“Chasing the Lights”方法相比也是如此,但我不明白如何告诉算法选择下一个节点,所以使用哪个 f 评分函数,因为考虑到矩阵中光的总和,算法最终会循环遍历相同的 3/4 个节点。

另外,我想就如何表示算法的节点提出一些建议,因为我无法了解如何使用通常用于在有目标节点的矩阵内进行路径优化的算法,用于以下情况在这里,您将整个矩阵视为节点,并且您的目标不是到达特定节点,而只是检查其总和是否为 0。

我实现所有工作的语言是 Lua。

谢谢。

编辑 2019 年 5 月 27 日 由于我是 Lua 的新手,我将自己的错误和在其中编写代码的能力以及我对算法的理解归咎于我无法找到解决方案的事实。 我不擅长解释我遇到的问题,所以我试图从我收到的 cmets 中获得最好的结果,现在我将发布修改后的代码,以便如果你想帮助,你会更好地理解(代码 >> 单词哈哈)。

注意:我是根据这篇文章写的算法A* algorithm

lua source code

【问题讨论】:

  • 您所说的“...最终会导致算法每次都循环通过相同的 3/4 个节点”是什么意思? A* 永远不会第二次访问同一个节点。顺便说一句,如果您可以添加有关游戏规则的详细信息,将会有很大帮助。你如何决定在矩阵中切换什么光?
  • 我建议f = 9 + (sum of all the lights in their local matrix),其中 9 是您可以在一个步骤中打开/关闭的最大灯数。
  • 要正确实现 A*,您应该将下一个节点及其 f(node) 放入优先级队列。一个节点应该只是一个矩阵,没有“当前单元格”。
  • 如果您正在解决 5x5 拼图,那么您可以将拼图建模为具有 2^25 个节点的图,其中每个节点有 25 个邻居。
  • 如果我不考虑当前单元格而只考虑矩阵,我如何确定哪个是该节点的邻居?

标签: algorithm lua a-star


【解决方案1】:

不知道你在找什么。

首先,简单的观察:游戏板中的每个字段最多切换一次(切换一个字段两次不会做任何事情)。

您可以采用一种非常糟糕的方法并创建 2^n 个游戏状态(图表中的节点),其中 n 是游戏板上的字段数量。为什么可怕?创建图形至少需要 O(2^n) 时间和空间。在 O(2^n) 时间内,您只需检查所有可能的移动(因为您想切换每个板一次)并立即告诉结果而不是运行额外的 A*。

更好的主意(?):我们不要在物理上创建整个图表。你不想访问一个节点两次,所以你应该存储某个地方(可能是一些位掩码,在那里你可以快速检查一个节点是否已经在集合中)已经访问过的节点。然后,当您在某个节点中时,您检查所有邻居 - 切换一个字段后的游戏状态。如果他们被访问过,请忽略它们,否则将它们添加到您的优先级队列中。然后从优先级队列中取出第一个节点,将其移除并“进入”它所代表的游戏状态。

正如我所说,如果第 i 个字段尚未切换,您可以将游戏状态表示为第 i 个位置上大小为 n - 0 的位掩码,否则为 1。

这会比天真的方法更好吗?取决于您的启发式函数。我不知道哪个更好,你必须尝试一些并检查结果。在最坏的情况下,您的 A* 将检查每个节点,使得复杂性比简单的蛮力更糟糕。如果幸运的话,它可能会大大加快速度。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-09
    • 1970-01-01
    • 2016-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多