加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

Hammerwatch拼图;用Python解决

发布时间:2020-12-20 13:40:54 所属栏目:Python 来源:网络整理
导读:参见英文答案 Any algorithm for “Flip all” (Light Out) game?????????????????????????????????????3个 所以,我的妻子在Steam上玩Hammerwatch.她遇到了一个难题,我决定尝试编写一个解决方案. 以下是拼图的工作原理: 激活开关可以打开或关闭该开关,也可
参见英文答案 > Any algorithm for “Flip all” (Light Out) game?????????????????????????????????????3个
所以,我的妻子在Steam上玩Hammerwatch.她遇到了一个难题,我决定尝试编写一个解决方案.

以下是拼图的工作原理:
激活开关可以打开或关闭该开关,也可以切换其相邻的开关.

这是游戏中拼图的YouTube视频:
http://www.youtube.com/watch?v=OM1XD7IZ0cg

我想出了如何让拼图的机制正常工作.我终于意识到我有两个选择让电脑解决这个问题:
A)通过随机选择开关让计算机解决
…要么…
B)创建一种算法,使计算机能够更有效地解决难题.

作为一名新程序员(在CodeAcademy教程的中途,在LPTHW中途,目前正在通过麻省理工学院edX计算机科学Python课程),我觉得我的能力有限,无法解决这个问题.我来学习了!请帮忙!

请帮助:

我需要帮助找出一个更好的方法来随机解决这个问题,甚至更好,有一个算法,让计算机系统地解决这个难题.我唯一能做的就是让计算机将拼图状态存储在列表或字典中,通过跳过这些存储的状态来协助程序,将程序指向新的可能解决方案

当前程序的工作原理:

我打算允许用户使用前9个raw_input输入拼图板的当前状态.然后它进入一个循环,随机切换拼图板的开关,直到它们全部打开.

P.S.:当我注册StackOverflow帐户并输入此消息时,我的计算机一直在后台运行该程序以找到解决方案.大约一个小时,仍然没有找到解决方案,它目前正在进行~92,000,000次迭代.我觉得它不起作用……

import random

def switcheroo(x):
    """
    switches 'x' to 1 if it's a 0 and vice-versa
    """
    if x == 0:
        x = 1
    else:
        x = 0
    return x

# original input variables
a1 = 0
a2 = 0
a3 = 0
b1 = 0
b2 = 0
b3 = 0
c1 = 0
c2 = 0
c3 = 0


# puzzleboard   
print "nn"
print "    1   2   3   "
print "  -------------"
print "a |",a1,"|",a2,a3,"|"
print "  -------------"
print "b |",b1,b2,b3,"|"
print "  -------------"
print "c |",c1,c2,c3,"|"
print "  -------------"
print "nn"



print "What's ON/OFF? (type 0 for OFF,1 for ON)"
a1 = int(raw_input("a1: "))
a2 = int(raw_input("a2: "))
a3 = int(raw_input("a3: "))
b1 = int(raw_input("b1: "))
b2 = int(raw_input("b2: "))
b3 = int(raw_input("b3: "))
c1 = int(raw_input("c1: "))
c2 = int(raw_input("c2: "))
c3 = int(raw_input("c3: "))

# for counting the iterations within the loop
iteration = 0

# to stop loop if all switches are ON
ans = a1 and a2 and a3 and b1 and b2 and b3 and c1 and c2 and c3


while ans == False:
    # randomly generates number,flipping random switches
    counter = random.randint(1,9)
    if counter == 1:
        switch = "a1"
    elif counter == 2:
        switch = "a2"
    elif counter == 3:
        switch = "a3"
    elif counter == 4:
        switch = "b1"
    elif counter == 5:
        switch = "b2"
    elif counter == 6:
        switch = "b3"
    elif counter == 7:
        switch = "c1"
    elif counter == 8:
        switch = "c2"
    elif counter == 9:
        switch = "c9"


    # PUZZLE MECHANICES #
    if switch == "a1":
        a1 = switcheroo(a1)
        a2 = switcheroo(a2)
        b1 = switcheroo(b1)

    if switch == "a2":
        a2 = switcheroo(a2)
        a1 = switcheroo(a1)
        a3 = switcheroo(a3)
        b2 = switcheroo(b2)        

    if switch == "a3":
        a3 = switcheroo(a3)
        a2 = switcheroo(a2)
        b3 = switcheroo(b3)

    if switch == "b1":
        b1 = switcheroo(b1)
        b2 = switcheroo(b2)
        a1 = switcheroo(a1)
        c1 = switcheroo(c1)

    if switch == "b2":
        b2 = switcheroo(b2)
        a2 = switcheroo(a2)
        b1 = switcheroo(b1)
        b3 = switcheroo(b3)
        c2 = switcheroo(c2)

    if switch == "b3":
        b3 = switcheroo(b3)
        b1 = switcheroo(b1)
        b2 = switcheroo(b2)
        c3 = switcheroo(c3)
    # Edit 1
    if switch == "c1":
        c1 = switcheroo(c1)
        c2 = switcheroo(c2)
        b1 = switcheroo(b1)

    if switch == "c2":
        c2 = switcheroo(c2)
        c1 = switcheroo(c1)
        c3 = switcheroo(c3)
        b2 = switcheroo(b2)

    if switch == "c3":
        c3 = switcheroo(c3)
        c2 = switcheroo(c2)
        b3 = switcheroo(b3)
    if switch == "stop":
        break

    # prints puzzle-board state at end of loop iteration
    print "nn"
    print "    1   2   3   "
    print "  -------------"
    print "a |","|"
    print "  -------------"
    print "b |","|"
    print "  -------------"
    print "c |","|"
    print "  -------------"
    print "nn"

    # prints which # was randomly generated
    print "random #: ",counter

    # tracks loop iteration
    iteration += 1
    print "iteration",iteration



if ans == True:
    print "I figured it out!"

解决方法

有一种众所周知的方法可以解决这个问题.设x_1,…,x_n是对应于是否按下第n个按钮作为解的一部分的变量,并让a_1,a_n为初始状态.

假设您正在解决3×3问题,并且变量设置如下:

x_1 x_2 x_3
x_4 x_5 x_6
x_7 x_8 x_9

这个初始状态是:

a_1 a_2 a_3
a_4 a_5 a_6
a_7 a_8 a_9

现在,您可以写下解决方案必须满足的一些方程式(算术模2).它基本上编码关于哪些开关导致特定灯光切换的规则.

a_1 = x_1 + x_2 + x_4
a_2 = x_1 + x_2 + x_3 + x_5
...
a_5 = x_2 + x_4 + x_5 + x_6 + x_8
...
a_9 = x_6 + x_8 + x_9

现在你可以使用高斯消元法来解决这组联立方程.因为你在算术模2中工作,它实际上比实数上的联立方程更容易.例如,要删除第二个等式中的x_1,只需将第一个等式添加到其中即可.

a_1 + a_2 = (x_1 + x_2 + x_4) + (x_1 + x_2 + x_3 + x_5) = x_3 + x_4 + x_5

具体来说,这是算术模2中的高斯消元算法:

>选择一个带有x_1的等式.将其命名为E_1.
>将E_1添加到其他每个未命名的等式中,其中包含x_1.
>重复x_2,x_3,….,x_n.

现在,E_n是仅包含x_n的等式.您可以将从此处获得的x_n值替换为先前的等式.重复E_ {n-1},E_1.

总的来说,这解决了O(n ^ 3)操作中的问题.

这是一些代码.

class Unsolvable(Exception):
    pass

def switches(n,m,vs):
    eqs = []
    for i in xrange(n):
        for j in xrange(m):
            eq = set()
            for d in xrange(-1,2):
                if 0 <= i+d < n: eq.add((i+d)*m+j)
                if d != 0 and 0 <= j+d < m: eq.add(i*m+j+d)
            eqs.append([vs[i][j],eq])

    N = len(eqs)
    for i in xrange(N):
        for j in xrange(i,N):
            if i in eqs[j][1]:
                eqs[i],eqs[j] = eqs[j],eqs[i]
                break
        else:
            raise Unsolvable()
        for j in xrange(i+1,N):
            if i in eqs[j][1]:
                eqs[j][0] ^= eqs[i][0]
                eqs[j][1] ^= eqs[i][1]

    for i in xrange(N-1,-1,-1):
        for j in xrange(i):
            if i in eqs[j][1]:
                eqs[j][0] ^= eqs[i][0]
                eqs[j][1] ^= eqs[i][1]
    return [(i//m,i%m) for i,eq in enumerate(eqs) if eq[0]]

print switches(4,3,([1,0],[0,1,1],0]))

您可以为其指定开关阵列的高度和宽度,以及一次一行的初始状态.它返回您需要按下的开关以关闭所有灯.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读