Prolog - 解决游戏,实现启发式

时间:2014-05-06 14:09:20

标签: algorithm path prolog

我想解决一个'游戏'。 我有5个圆圈,我们可以将圆圈旋转到左边或右边(90度)。

示例:

enter image description here

enter image description here

目标:1,2,3,......,14,15,16 防爆。起始情况:16,15,14,...,3,2,1

我正在使用BFS。

启发式功能:

       heuristic(NextState,Goal,H)),

功能描述:

For each number 1 <= i <= 16, find the minimum number of rotations needed to put i back in its correct position (disregarding all other numbers)
Take the maximum over all these minimums.

这相当于报告正确定位“最差”数字所需的最小转数,因此永远不会高估所需的移动次数(因为同时修复所有数字的位置至少需要与固定任何一个位置相同的移动数量)他们)。

应该怎么样?

圈A的例子:

heuristic(tiles([A,_,_,_],[_,_,_,_],[_,_,_,_],[_,_,_,_]),tiles([A,_,_,_],[_,_,_,_],[_,_,_,_],[_,_,_,_]),0).
heuristic(tiles([A,_,_,_],[_,_,_,_],[_,_,_,_],[_,_,_,_]),tiles([_,A,_,_],[_,_,_,_],[_,_,_,_],[_,_,_,_]),1).
heuristic(tiles([A,_,_,_],[_,_,_,_],[_,_,_,_],[_,_,_,_]),tiles([_,_,A,_],[_,_,_,_],[_,_,_,_],[_,_,_,_]),4).
heuristic(tiles([A,_,_,_],[_,_,_,_],[_,_,_,_],[_,_,_,_]),tiles([_,_,_,A],[_,_,_,_],[_,_,_,_],[_,_,_,_]),5).
heuristic(tiles([A,_,_,_],[_,_,_,_],[_,_,_,_],[_,_,_,_]),tiles([_,_,_,_],[A,_,_,_],[_,_,_,_],[_,_,_,_]),1).
heuristic(tiles([A,_,_,_],[_,_,_,_],[_,_,_,_],[_,_,_,_]),tiles([_,_,_,_],[_,A,_,_],[_,_,_,_],[_,_,_,_]),2).
heuristic(tiles([A,_,_,_],[_,_,_,_],[_,_,_,_],[_,_,_,_]),tiles([_,_,_,_],[_,_,A,_],[_,_,_,_],[_,_,_,_]),3).
heuristic(tiles([A,_,_,_],[_,_,_,_],[_,_,_,_],[_,_,_,_]),tiles([_,_,_,_],[_,_,_,A],[_,_,_,_],[_,_,_,_]),4).
heuristic(tiles([A,_,_,_],[_,_,_,_],[_,_,_,_],[_,_,_,_]),tiles([_,_,_,_],[_,_,_,_],[A,_,_,_],[_,_,_,_]),4).
heuristic(tiles([A,_,_,_],[_,_,_,_],[_,_,_,_],[_,_,_,_]),tiles([_,_,_,_],[_,_,_,_],[_,A,_,_],[_,_,_,_]),3).
heuristic(tiles([A,_,_,_],[_,_,_,_],[_,_,_,_],[_,_,_,_]),tiles([_,_,_,_],[_,_,_,_],[_,_,A,_],[_,_,_,_]),4).
heuristic(tiles([A,_,_,_],[_,_,_,_],[_,_,_,_],[_,_,_,_]),tiles([_,_,_,_],[_,_,_,_],[_,_,_,A],[_,_,_,_]),5).
heuristic(tiles([A,_,_,_],[_,_,_,_],[_,_,_,_],[_,_,_,_]),tiles([_,_,_,_],[_,_,_,_],[_,_,_,_],[A,_,_,_]),5).
heuristic(tiles([A,_,_,_],[_,_,_,_],[_,_,_,_],[_,_,_,_]),tiles([_,_,_,_],[_,_,_,_],[_,_,_,_],[_,A,_,_]),4).
heuristic(tiles([A,_,_,_],[_,_,_,_],[_,_,_,_],[_,_,_,_]),tiles([_,_,_,_],[_,_,_,_],[_,_,_,_],[_,_,A,_]),5).
heuristic(tiles([A,_,_,_],[_,_,_,_],[_,_,_,_],[_,_,_,_]),tiles([_,_,_,_],[_,_,_,_],[_,_,_,_],[_,_,_,A]),6).

这是个好主意吗?

1 个答案:

答案 0 :(得分:0)

您似乎正在尝试实施我建议here的可接受启发式。

我无法告诉你,你的'&#34;例如,圈A&#34;代码,我很害怕。计算将特定数字i从其当前位置移动到其最终正确位置所需的最小旋转次数的方法是将其视为一种特殊的最短路径问题,其中:

  1. 每个位置都有一个顶点(所有16个顶点)。
  2. 每当有一个可以旋转90度(在任一方向上)的圆圈时,在一对顶点x和y之间有一条边,可以将位置x中的任何数字移动到位置y。
  3. 为了具体,让我们用字母A-P标记位置(以及顶点),如下所示:

    ABCD
    EFGH
    IJKL
    MNOP
    

    因此,例如,离开顶点B的边是:

    1. A(因为逆时针旋转左上轮会将B处的任何东西移动到A)
    2. F(因为顺时针旋转左上轮将移动B到F的任何地方)
    3. 旋转任何其他4个轮子对位置B中的数字没有影响,因此这些是离开顶点B的唯一边缘。

      其他一些顶点有更多边。例如。 F有边缘:

      1. B(逆时针旋转左上轮)
      2. E(顺时针旋转左上轮)
      3. G(顺时针旋转中心轮)
      4. J(逆时针旋转中心轮)
      5. 边缘未加权(或等效,重量为1)并且是双向的,因为每次90度旋转都可以通过反向旋转来解除。

        假设我们想要计算从其初始位置(让我们说B)到最终的正确位置I所需的最小旋转次数。

        遍历边缘相当于将某个圆圈旋转90度,因此要找到将数字9从位置B移动到位置I所需的最小旋转次数,我们希望找到连接顶点B和I的路径使用最小值可能的边数。因为所有边都具有权重1,所以可以使用广度优先搜索来有效地解决这个问题(如果边具有各种权重,则可以使用Dijkstra's algorithm代替)。在9的情况下,答案将是3(例如,B-> F-> J-> I)。

        因此,这解释了如何计算移动特定号码回家的最小转数。要计算启发式,请对初始配置中的每个数字执行此操作,然后选择最大值。 (请注意,图表在每种情况下都是相同的 - 只有起始和目标顶点会发生变化。)这是您保证允许的启发式旋转计数值。