【发布时间】:2021-04-07 18:36:20
【问题描述】:
我开发了一款益智游戏。游戏的状态可以表示为一个大小为 12 的 Int 数组。玩家只能进行 4 次移动。游戏的目的是达到某种状态。我正在尝试用 python z3 解决这个难题。这是代码。
a = Int('a')
b = Int('b')
s = Solver()
s.add(And(a >= 0, b >= 0, b <= a, a == 100))
f = Function('f', IntSort(), IntSort(), IntSort())
init = And(f(0, 1) == 1 , f(0, 2) == 1 , f(0, 3) == 1 , f(0, 4) == 2, f(0, 5) == 2 ,
f(0, 6) == 2, f(0, 7) == 3, f(0, 8) == 3, f(0, 9) == 3 , f(0, 10) == 4 ,
f(0, 11) == 4 , f(0, 12) == 4)
goal = And(f(b, 1) == 1 , f(b, 2) == 1 , f(b, 3) == 1 , f(b, 4)
== 2 , f(b, 5) == 2 , f(b, 6) == 2 , f(b, 7) == 3 , f(b, 8) == 3 ,
f(b, 9) == 3 , f(b, 10) == 4 , f(b, 11) == 4 , f(b, 12) == 4)
a 是最大移动次数。 b 是解决问题的最小移动次数。 f 是状态数组。目标是最终获胜者状态。
def move(k):
RIGHT = And(f(k + 1, 1) == f(k, 1), f(k + 1, 2) == f(k, 2), f(k + 1, 3) == f(k, 3),
f(k + 1, 4) == f(k, 4), f(k + 1, 5) == f(k, 11) , f(k + 1, 6) == f(k, 5),
f(k + 1, 7) == f(k, 6), f(k + 1, 8) == f(k, 8), f(k + 1, 9) == f(k, 7),
f(k + 1, 10) == f(k, 9), f(k + 1, 11) == f(k, 10), f(k + 1, 12) == f(k, 12))
UP = And(f(k + 1, 1) == f(k, 1), f(k + 1, 2) == f(k, 8), f(k + 1, 3) == f(k, 2),
f(k + 1, 4) == f(k, 3), f(k + 1, 5) == f(k, 5), f(k + 1, 6) == f(k, 4),
f(k + 1, 7) == f(k, 6), f(k + 1, 8) == f(k, 7), f(k + 1, 9) == f(k, 9),
f(k + 1, 10) == f(k, 10), f(k + 1, 11) == f(k, 11), f(k + 1, 12) == f(k, 12))
BOT = And(f(k + 1, 1) == f(k, 12), f(k + 1, 2) == f(k, 1), f(k + 1, 3) == f(k, 3),
f(k + 1, 4) == f(k, 4), f(k + 1, 5) == f(k, 5), f(k + 1, 6) == f(k, 6),
f(k + 1, 7) == f(k, 7), f(k + 1, 8) == f(k, 2), f(k + 1, 9) == f(k, 8),
f(k + 1, 10) == f(k, 9), f(k + 1, 11) == f(k, 11), f(k + 1, 12) == f(k, 10))
LEFT = And(f(k + 1, 1) == f(k, 3), f(k + 1, 2) == f(k, 2), f(k + 1, 3) == f(k, 4),
f(k + 1, 4) == f(k, 5), f(k + 1, 5) == f(k, 11), f(k + 1, 6) == f(k, 6),
f(k + 1, 7) == f(k, 7), f(k + 1, 8) == f(k, 8), f(k + 1, 9) == f(k, 9),
f(k + 1, 10) == f(k, 10), f(k + 1, 11) == f(k, 12), f(k + 1, 12) == f(k, 1))
return Or(LEFT, UP, BOT, LEFT)
s.add(ForAll([b], move(b)))
s.add(init)
s.add(goal)
print(s.check())
move(k) 表示连接 k+1 和 k 状态的第 k 个移动。使用 s.add(ForAll([b], move(b))),我希望所有整数 k k>=0 k
任何建议将不胜感激。
【问题讨论】:
-
您的
init和goal状态是等价的。这是故意的吗? -
这些值是否位于某种网格上?如果您可以直观地描述该网格的外观以便于理解,那就太好了。
-
这是有意的,但 init 的其他值也是如此。游戏状态可以表示为一个大小为 12 的一维数组。数组的值是 1、2、3 和 4 各 3 次。每次移动都会以某种方式重新排列值,这可以在 right、up、left 和 bot 变量中看到。我是smt的新手,尽力解决这个问题。也许其他策略可能会更好。如果有什么不清楚的地方请告诉我。
-
@alias,我忘了给你加标签。