我正在尝试为游戏算法创建一个可解决性函数。基本上是一个函数,如果可以解决,它会为给定的游戏返回true或false。
游戏是Buttonia.com(目前还没有实现算法),这是一种熄灯游戏。基本上你有一个按钮网格,按下时,每个按钮都会改变它的某些邻居的状态。目前我生成随机游戏配置,然后尽可能应用启发式。剩下的就是蛮力搜索。
到目前为止,我的进步是建立一个方程系统来模拟游戏。由于每个按钮需要改变状态奇数次才能以向下状态结束,所以它的等式是这样的:
button_A = 1 - (button_1 + button_2 + ... + button_X)%2
其中button_1到button_X是按钮状态,对button_A有效。如果某些按钮不依赖于其他按钮,则可以立即解决这些按钮。其余的,我尝试一个配置,直到我遇到冲突然后回溯。
目前,该算法适用于较小的游戏配置。我已经从3x3游戏测试了它,尺寸为10x10。 6x6接近实际比赛的上限。
这些方程式大大减少了蛮力的搜索空间,使其变得实用。可能存在一种解决方程组的纯粹数学方法。
ascii的示例3x3游戏(来自buttonia.com/?game=2964):
||#
-o-
+#|
Legend:
o = affect only self
- = affect left and right neighbors
| = affect above and below neighbors
+ = affect left, right, above and below neighbors
# = affect all 8 surrounding neighbors
解决方案,按下这些:(0,0),(2,0),(1,2),(0,1),(1,1),(2,1)
此游戏的等式:
Button_0_0 = 1 - (0) % 2
Button_1_0 = 1 - (Button_2_0) % 2
Button_2_0 = 1 - (0) % 2
Button_0_1 = 1 - (Button_0_0 + Button_0_2 + Button_1_2) % 2
Button_1_1 = 1 - (Button_1_0 + Button_2_0 + Button_0_1 + Button_2_1 + Button_1_2) % 2
Button_2_1 = 1 - (Button_2_0 + Button_1_2 + Button_2_2) % 2
Button_0_2 = 1 - (Button_1_2) % 2
Button_1_2 = 1 - (Button_0_2) % 2
Button_2_2 = 1 - (Button_1_2) % 2
潜在的解决方案:
更改数学函数以避免模数的需要让我们将左侧的项移动到右侧,创建了高斯方法所需的整齐矩阵设置。所以前两个方程将分别转换为:
-1 = -1*B00 + 0*B10 + 0*B20 + 0*B01 + 0*B11 + 0*B21 + 0*B02 + 0*B12 + 0*B22
-1 = 0*B00 + -1*B10 + -1*B20 + 0*B01 + 0*B11 + 0*B21 + 0*B02 + 0*B12 + 0*B22
在这里讨论解决方案:Gaussian Elimination with custom operators
越来越近了。几乎准备好发布完整的解决方案:Inverting binary networks
答案 0 :(得分:4)
这是一个F 2 上的线性方程组,该字段包含两个元素0和1.
你可以像普通线性方程一样解决它,但你必须做算术模2。
修改强> 这种情况下的线性代数与实数完全相同,除了你必须替换操作:
加法和减法变为异或,即0 + 0 = 0,0 + 1 = 1,1 + 1 = 0.
乘法变为AND:0 * 0 = 0,0 * 1 = 0,1 * 1 = 1
只能通过一个除法:0/1 = 0,1 / 1 = 1.
方程中的所有系数和未知数的可能值都是0或1。
因此,模数不会像你所写的那样在方程的外部被打耳光,它隐含在操作中。
如果你的方程组不可解,你会得到一个等式0 = 1,这显然是无法解决的。
答案 1 :(得分:2)
不是以随机状态开始,而是为什么不通过翻转随机开关来产生起始位置,即从解决状态向后工作到起始状态。这样你只会产生可解决的谜题。
答案 2 :(得分:1)
这看起来几乎像一个线性方程组(mod 2除外),所以你可能能够采用一种常规技术来解决这些问题 - 例如以矩阵形式(wikipedia)对行进行行减少。
答案 3 :(得分:0)
由于这不是一个有时间限制的问题(好吧,假设它可以在不到一天的时间内完成),我可能会进行深度限制的广度优先搜索,将每个可能的移动放在一个级别然后每次移动后的每一步动作。
它会很慢,但如果有答案,几乎可以保证找到答案!
答案 4 :(得分:0)
假设您构建了一个方程组并尽可能地解决它们,但是某些行最终得到了等式左边的所有0(我将方程表示为增广矩阵) 假设您尝试在Z2环中解决系统(实际上这个特定示例意味着唯一的变化是1 + 1 = 0,否则一切都保持不变......因为我们需要的唯一运算符是XOR)并最终得到以下矩阵:
1001 1
0100 1
0011 0
0000 0
正如您在此示例中所看到的,第4行全部为0,这意味着我们没有得到答案。但是请这样考虑:所有0的行意味着该变量不会影响解决方案。这实际上是一个糟糕的词语选择...它只是意味着它们可以有任何价值(我们在这里很幸运,因为所有值都意味着1或0,与实际数字不同......所以这意味着我们有2个该系统的解决方案)。
原因如下:此时您需要知道的是,最右侧的列仍然包含有效的游戏解决方案。我们以第一行为例。它说
button_0 + button_3 = 1
但我们知道按钮3可以是任何东西(因为第3行都是0)。此时按钮3为0(此时第3行最右边的列为0)所以现在我们知道它意味着
button_0 + 0 = 1
所以我们知道button_0是1.因此在这个系统中,即使我们无法直接找到button_3,我们仍然有一个有效的解决方案。
上面生成的矩阵足以检查可解性。如果一行包含全0,那么它基本上就是说
nothing = nothing
或者,为了更好地说明其工作原理,
0x = 0
这是有道理的,系统仍然有效。但是,如果我们遇到一个全部为0 的行,除了最右边的位,即
0000 1
那会说
0x = 1
这是不可能的,因此我们现在知道系统无法解决,因为我们无法解决这样的不可能的情况。
因此,简而言之,尽量尝试解决方程式,不要担心,如果你不能确切地找出一些变量是什么,只要你没有遇到,在任何时候,不可能我刚刚提到的那一行游戏是可以解决的。
但是如果我们想要系统的最短解决方案呢?在这里,我们将不得不检查所有可能的解决方案。我们有button_3可以是任何值,这意味着第3列中的任何1意味着找到它的行受button_3的影响。因此,假设我们想要检查使用button_3的解决方案是否会更短。我们创建另一个矩阵,但是现在将button_3设置为1(因为我们之前已经确定它可以是任何东西,我们已经有了0,所以现在我们检查1)。我们现在最终得到以下矩阵:
1001 1
0100 1
0011 0
0001 1
我们尽可能地减少这一点,现在最终得到这个矩阵:
1000 0
0100 1
0010 1
0001 1
这仍然是一个有效的解决方案,但是我们可以看到解决方案更长(需要3个,而不是按下2个按钮),因此我们将其丢弃。我们必须为每个将我们发现的行设置为0到1的每个排列都这样做。因此,如果我们有x行全部为0,那么系统有x ^ 2个解决方案,我们必须检查所有这些。< / p>