66
\$\开始组\$

我做了一种益智游戏,目标是去掉所有的白色瓷砖。你可以在问题的最后试一试。

每一次,板都是随机生成的,在5*5网格上的任意位置都有白色瓷砖。您可以单击该网格上的任何瓷砖,它将切换其颜色以及与之接触的所有瓷砖。我的困境是,我不知道这是否会产生一个不可能的董事会。检查这种情况的最佳方法是什么?

函数newgame(){移动=0;document.getElementById(“moves”).innerHTML=“moves:”+moves;对于(var i=0;i<25;i++){if(数学随机数()>=0.5){$(document.getElementsByClassName('block')[i]).toggleClass(“b1-b2”)}}}新游戏();功能切换(a,b){移动+=1;document.getElementById(“移动”).innerHTML=“移动:”+移动;$(document.getElementsByClassName('block')[a+(b*5)]).toggleClass(“b1-b2”);if(a<4){$(document.getElementsByClassName('block')[(a+1)+(b*5)]).toggleClass(“b1-b2”)}如果(a>0){$(document.getElementsByClassName('block')[(a-1)+(b*5)]).thoggleClass(“b1 b2”)}if(b<4){$(document.getElementsByClassName('block')[a+((b+1)*5)]).toggleClass(“b1-b2”)}如果(b>0){$(document.getElementsByClassName('block')[a+((b-1)*5)]).toggleClass(“b1-b2”)}}
车身{背景色:#000000;}.游戏{浮动:左;背景色:#000000;宽度:300px;高度:300px;溢出:隐藏;溢出-x:隐藏;user-select:无;显示:嵌入式块;}.容器{border-color:#ffffff;边宽:5px;边框样式:实心;边距:5px;宽度:600px;高度:300px;文本对齐:居中;}.侧面{浮动:左;背景颜色:#000000;宽度:300px;高度:300px;溢出:隐藏;溢出-x:隐藏;user-select:无;显示:嵌入式块;}.块{过渡:背景色0.2s;浮动:左;}.b1:悬停{背景色:#444444;光标:指针;}.b2:悬停{背景色:#bbbbbb;光标:指针;}.行{宽度:300px;溢出:自动;溢出-x:隐藏;}b1号{显示:嵌入式块;高度:50px;宽度:50px;背景色:#000000;border-color:#000000;边宽:5px;边框样式:实心;}.b2型{显示:嵌入式块;高度:50px;宽度:50px;背景色:#ffffff;border-color:#000000;边宽:5px;边框样式:实心;}.title(标题){宽度:200px;高度:50px;颜色:#ffffff;字体大小:55px;font-weight:粗体;font-family:宋体;显示:table-cell;垂直对齐:中间;}.按钮{光标:指针;宽度:200px;高度:50px;背景色:#000000;边框颜色:#ffffff;边框样式:实心;边宽:5px;颜色:#ffffff;字体大小:25px;font-weight:粗体;font-family:宋体;显示:table-cell;垂直对齐:中间;边距:5px;过渡:背景颜色0.3s,颜色0.3s;}.按钮:悬停{背景色:#ffffff;颜色:#000000;}.侧置{填充:30px 0px;高度:200px;}#移动{宽度:200px;高度:50px;颜色:#aaaaaa;字体大小:30px;font-weight:粗体;font-family:宋体;显示:table-cell;垂直对齐:中间;}
<script src=“https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js“></script><中心><div class=“container”><div class=“game”><div class=“row”><div onclick=“toggle(0,0);”class=“block b1”></div><div onclick=“tockle(1,0);“class=“block-b1”></div><div onlick=“tookle(2,0);/div></div><div class=“row”><div onclick=“切换(0,1);”class=“block b1”></div><div onclick=“toggle(1,1);”class=“block-b1”></div><div onlick=“tockle(2,1);class=“block b1”></div><div onclick=“切换(1,2);”class=“块b1”></div><div onclick=“切换(2,2);”class=“块b1”></div><div on click=”切换(3,2);“class=”块b1“></div><div onclick=“切换(2,3);”class=“块b1”></div><div onclick=“toggle(3,3);”class=“block b1”></div><div on click=”toggle</div><div onclick=“切换(3,4);”class=“块b1”></div><div onclick=“切换(4,4);”class=“块b1”></div><div class=“side”><center class=“sidestable”>瓷砖<br>新游戏<br><br>移动次数:0</中心></div></div></中心>

\$\端组\$
7
  • 9
    \$\开始组\$ 如果你对这种益智游戏感兴趣,看看西蒙·塔塔姆的便携式拼图收藏除了这种类型(称为Flip there)外,你还可以找到许多日语和其他拼图的变体。所有内容都在BSD许可下,这可能是一个有趣的阅读。 \$\端组\$
    – 迪比
    评论 2018年2月8日11:22
  • 12
    \$\开始组\$ 反向工程怎么样?从一块白板开始,然后自动操作,比如在随机方块上点击20次。这样你就知道最后一定会有解决方案。 \$\端组\$ 评论 2018年2月9日12:48
  • \$\开始组\$ 我想继续比赛,但由于你的问题,我是否会赢的不确定性正在折磨着我!趣味游戏:) \$\端组\$
    – Duk先生
    评论 2018年2月9日15:54
  • \$\开始组\$ @Duk先生codepen.io/qwertyquerty/pen/WMGwVW这是完成的项目!这一个是固定的,并抛光。我还制作了一个电子应用程序。 \$\端组\$ 评论 2018年2月9日18:17
  • \$\开始组\$ @Qwerty当我尝试以全屏视图查看您的画笔时,我收到消息“此画笔的所有者需要验证他们的电子邮件地址才能启用全屏视图。”请在CodePen上验证您的电子邮件地址,这样我就可以在整个窗口中享受您的游戏了!:) \$\端组\$ 评论 2018年2月11日21:33

6个答案6

重置为默认值
163
\$\开始组\$

这是一种游戏,在这种游戏中,执行两次相同的动作会将棋盘反转到其先前的状态。因此,为了确保棋盘是可解的,请通过反向播放生成它。从一块已解决的(空白)板开始,然后以编程方式随机“单击”一定次数,或直到板具有所需数量的白色方块。一种解决方案是简单地以相反的顺序执行相同的动作。可能存在其他较短的解决方案,但保证您至少有一个。

另一个更复杂的解决方案是定义一个求解算法,该算法从你的起始位置开始遍历所有可能的游戏状态,试图找到解决方案。这将需要更长的时间来实现和运行,但将允许真正随机生成板。我不会详细讨论这个解决方案,因为它并不是一个好主意。

\$\端组\$
10
  • 23
    \$\开始组\$ @Qwerty:对于您的具体问题,两次单击同一个方块会自动取消,因此没有任何理由多次单击任何方块。你可能想选择一定数量的方块点击而不重复,或者考虑一个解决方案,为电路板上的每个方块分配XX%的点击机会。(埃德:回答得好,+1!) \$\端组\$ 评论 2018年2月8日0:08
  • \$\开始组\$ 我以前玩过几乎完全一样的游戏,最后使用了这种方法。我在开始时加入了一个动画,以快速显示已解决状态到未解决状态;它很漂亮。 \$\端组\$ 评论 2018年2月8日2:47
  • 1
    \$\开始组\$ @杰瑞德·戈根(Jared Goguen)很奇怪,我补充了这一点,然后回来看你的评论。 \$\端组\$ 评论 2018年2月8日3:56
  • 4
    \$\开始组\$ @JeffBowman事实上,这组可解游戏可以被视为一个25位的值,每个位对应一个正方形,即它被翻转的次数mod 2。因此,可以生成一个范围为0..33554432的随机数,然后从中快速计算板上每个方块的值。 \$\端组\$ 评论 2018年2月8日20:06
  • 7
    \$\开始组\$ 尽管这是对数学的关于如何回答这个问题,从设计的角度来看,这通常是一个可疑的实践。这种类型的一代人,如果没有任何特定的计划,通常会产生感觉非常“相同”的谜题,没有任何特殊的兴趣点或任何统一的主题。有可能为益智游戏“程序性地生成”有趣的问题实例,但通常需要更仔细地查看益智游戏的有趣特性。 \$\端组\$ 评论 2018年2月9日1:53
95
\$\开始组\$

虽然上面的答案很聪明(也许我会怎么做),但这个特别的游戏是众所周知的。它被称为熄灯,并已通过数学求解。只有当各种元素的两个总和(在维基百科页面上给出)加上0 mod 2(即偶数)时,才有解决方案。一般来说,对于任何棋盘上的游戏,一点线性代数都应该给出类似的求解条件。

\$\端组\$
7
  • 2
    \$\开始组\$ 发现它已经被制作出来了,真是有点难过。我以为我知道了什么。 \$\端组\$ 评论 2018年2月8日4:05
  • 42
    \$\开始组\$ @Qwerty几乎没有原创想法,你当然不需要有一个才能成功(c.f.Rovio,King)。 \$\端组\$ 评论 2018年2月8日9:48
  • 14
    \$\开始组\$ 这个特殊的游戏是存在的,但你可以随时扩展这个想法!添加更多功能!为单击某个位置时发生的情况添加不同的规则,例如根据其激活/停用的方向添加颜色。添加您必须使用的不同“工具”。添加非矩形板!有很多有趣的事情要做。只需记住,一个动作总是要反转。 \$\端组\$ 评论 2018年2月8日13:25
  • 7
    \$\开始组\$ @OrangeDog:即使“Lights Out”也不是原创,这只是90年代流行的品牌名称。例如,维基百科文章列出了 \$\端组\$ 评论 2018年2月8日17:17
  • 1
    \$\开始组\$ 你所指的“上述答案”是什么?这完全不清楚,因为在我的屏幕上,只有一个答案高于你的答案。请记住,根据投票和用户选项回答更改顺序。你应该总是链接到具体的答案,而不是指“上面”的内容。 \$\端组\$ 评论 2018年2月12日16:50
12
\$\开始组\$

在生成拼图时,请使用另一种方法。

与其随机选择瓷砖并将其从白色变为黑色,不如从空白板岩开始,然后选择瓷砖,但不要旋转那个平铺为黑色,使其看起来就像用户选择了它,从而使周围的所有其他平铺都翻转过来。

这样你就可以保证至少一个解决方案是:用户必须撤销“AI”玩家创建关卡所做的操作。

\$\端组\$
7
\$\开始组\$

Ed和Alexandre有这个权利。

但是如果你想知道如果每个解决方案都可行,有很多方法。

可能的谜题数量有限

在同一个方块上单击两次会产生与根本不单击相同的结果,无论它们之间进行了多少次单击。这意味着每个解决方案都可以通过给每个正方形一个“点击”或“未点击”的二进制值来描述。类似地,每个谜题都可以通过给每个方块一个二进制值“toggled”或“not togged”来描述。这意味着有2^25个可能的谜题和2^25种可能的解决方案。如果你能证明每个解决方案都能解决一个独特的谜题,那么每个谜题都必须有一个解决方案。同样,如果你找到两个解决同一个难题的解决方案,那么不可能每个难题都有一个解决方案。

此外,2^25是33554432。这相当多,但这不是一个难以控制的数字。一个好的算法和一台像样的计算机可能会在几个小时内将其强行破解,特别是当你考虑到一半的谜题是另一半的反比时。

\$\端组\$
6
  • 4
    \$\开始组\$ 一半以上是“反向”——除了水平反射外,还有垂直反射和旋转。 \$\端组\$ 评论 2018年2月8日3:31
  • \$\开始组\$ @Clockwork-Muse,是的,但很难计算其确切数字,因为虽然不对称设计可以在8个排列中旋转和翻转,但对称设计的排列更少。所以我只提到了白/黑反转,因为每个解正好有一个反转。(尽管要使这一反向有效,你必须证明你可以翻转整个棋盘) \$\端组\$ 评论 2018年2月8日5:32
  • \$\开始组\$ 事实证明,正如罗伯特·马斯特拉戈斯蒂诺(Robert Mastragostino)在回答中提到的那样,这实际上是一个众所周知的、经过充分研究的问题。每个可解的谜题正好有4个解,而大多数随机棋盘都是不可解的。搜索所有这些空间可能很有趣,但因为已经有了证据(math.ksu.edu/math551/math551a.f06/lights_out.pdf)你也可以做几个点积,在几微秒内得到相同的答案 \$\端组\$ 评论 2018年2月8日8:13
  • \$\开始组\$ 数学时间:如果你想计算不同的电路板(不管可解性如何),考虑到所有对称性,那么伯恩赛德引理就是这样:有16个对称(一个平凡、三个旋转、四个反射,然后这8个对称中的每一个都与开/关反转相结合),对于每一个对称,一些电路板的数量完全不变。如果你取每个对称完全不变的电路板的平均值,那等于不同电路板的数量。 \$\端组\$
    – 亚瑟
    评论 2018年2月8日10:06
  • 1
    \$\开始组\$ @PeterTaylor编写模拟器的时间肯定要比运行结果的时间长得多。 \$\端组\$ 评论 2018年2月8日23:39
4
\$\开始组\$

通用答案:

  1. 创建一个大小为(#moves)x(#lights)的矩阵。
  2. 如果移动对应于该行的位置会切换对应于该列的灯光,则在单元格中输入1,否则为0。
  3. 在矩阵上执行Gauss-Jordan消元(模2)。
  4. 如果得到的矩阵每列中只有一个1,每行最多只有一个,那么每个网格都是可解的。
\$\端组\$
1
\$\开始组\$

其他人已经提到了确定随机生成的谜题是否可解的方法。不过,你应该问的问题是,你是否真的想要随机生成的谜题。

随机生成的谜题都有相同的核心缺陷:它们的难度几乎无法预测。你可能遇到的难题可能是已经解决的,也可能是微不足道的(解决方案显而易见),也可能很难解决(解决方案不明显),甚至是不可能解决的(难题根本无法解决)。因为难度是不可预测的,这会给玩家带来不满意的体验,尤其是当他们连续做多个谜题时。他们不太可能获得平滑的难度曲线,这可能会让他们感到厌烦或沮丧,这取决于他们得到了什么样的难题。

随机生成的另一个问题是,谜题初始化所需的时间是不可预测的。一般来说,你会(几乎)立即得到一个可解的谜题,但如果运气不好,你随机生成的谜题可能会出现一连串无法解的谜题。

解决这两个问题的一种方法是,将每个可解谜题的预定义向量都设置为难度组,然后根据难度从可解谜语中选择一个随机谜题。这样,你就可以确信每一个难题都是可以解决的,困难是可以预测的,并且生成将在恒定的时间内完成。

\$\端组\$

你必须登录来回答这个问题。

不是你想要的答案吗?浏览标记的其他问题.