开发文字游戏遇困境,借香农理论破局!超 9000 个可玩谜题库诞生

发布时间:2026/7/2 4:34:12
开发文字游戏遇困境,借香农理论破局!超 9000 个可玩谜题库诞生 “简单”的游戏游戏规则很简单。有一个未完成的填字游戏网格还有一列等待填入的字母。你拿到一个字母后点击它应填入的格子如此反复直到网格填满。一条规则我对这个游戏的要求看似微不足道游戏不应让玩家进行猜测。也就是说当玩家运用逻辑推理完成所有步骤后不应该出现游戏要求玩家随机选择一个格子的情况。每个字母都应能通过推理确定其位置。我原以为这是最容易实现的部分毕竟这只是个填字游戏我觉得最困难的是构建一个优质的词典并精心挑选填字内容。困境构建词典花了好几个月的时间。当词典终于完善后我做了件理所当然的事让程序生成数千个填字网格然后从中筛选出符合要求的。具体做法是先在网格中填入真实的单词隐藏部分字母再逐个给出剩余的字母只保留那些玩家能通过纯粹逻辑推理完成的网格。我会在晚上对这些生成的网格进行筛选。然而符合要求的网格只有大约四十个随后程序便陷入了停滞。它不断生成新的网格但几乎都因无法通过推理完成而被舍弃。经过几个通宵我重写了生成程序重新思考问题但最终符合要求的网格数量也没超过一百个。这让我彻底陷入了困境。一个 5×5 的网格要求横竖都能组成真实的单词其组合数量堪称天文数字。可能的网格组合多得超乎人类的想象但我的程序却连一百个可解的网格都找不到。不过我还是看到了一丝希望这让我有了继续前行的动力。那些被舍弃的网格和保留下来的网格之间的差距其实很小。同样的网格同样给出的字母仅仅一个未填充的格子就决定了是需要猜测还是可以确定答案。并非程序漏洞有好几个星期我都以为这是程序的漏洞比如生成器有缺陷、词典不够完善或者筛选过程过于严格。但事实并非如此。这其实就是文章开头提到的信号不好的电话问题一个古老且著名的通信问题而我一直埋头于网格和词典的工作没有意识到问题的本质。填字游戏就像一个信道我是信息发送者玩家是解码器我发送一个字母玩家要确定我想让它填入哪个格子。普通的填字游戏是“有噪声”的信道。解码器通常能猜对如果猜错了他们也会耸耸肩回溯并修正。一点小混乱在普通填字游戏中甚至是乐趣的一部分。但我承诺的是比“通常正确”更严格的标准我承诺“永远不会出错”而“永远”并非是在同一标准上的更严格设定而是完全不同的概念。可混淆性我在黑暗中摸索的正是“可混淆性”概念。为每个空格画一个点当两个空格可以填入同一个给出的字母时也就是它们“可混淆”时就在这两个点之间画一条线。这个图有个名字“可混淆性图”。当所有空格形成一个“独立集”时也就是任意两点之间都没有连线这个填字游戏就是可推理的。没有可混淆的配对就无需猜测。这正是我为自己设定的规则只是用了一种我之前不知道的方式来呈现。每个由三个比特组成的信号就像立方体的一个顶点每条边代表一个比特的翻转可能会使一个信号变成相邻的信号。一个安全的代码会选择那些至少需要三次翻转才能相互转换的顶点比如 000 和 111。“B如 Bravo 中的 B”就是人类运用这个概念的例子。有趣的是这个语音字母表在 1956 年最终确定而这一年恰好是香农发表该问题的年份。半个多世纪的数学研究成果早已摆在那里就等我去发现。我能判断一个完成的网格是否可推理但还无法有目的地构建这样的网格。为了学会这一点我首先得理解香农的发现。五大于四几十年前香农就在最简单的情况下研究出了这个问题的本质。想象时钟面上有五个信号每个信号都与相邻的两个信号非常接近以至于信号可能会相互混淆。逐个发送这些信号时你只能安全地使用其中两个选择不相邻的一对这样你发送的任何信号都不会被误认。五选二这是个小而整齐但令人失望的数字。香农发现如果不逐个发送信号而是将它们组合起来把整个序列当作一个消息效果会好很多。逐个发送时两次传输可以得到 2 × 2 4 个不会混淆的消息。但如果将信号组合起来并合理选择就能携带五个消息。而且这种增益是会累积的。逐个发送十个信号能得到 2 的十次方即 1024 个安全消息组合发送时能得到 3125 个。所以每增加一个信号安全消息的数量就会乘以 2.236而不是 2。这个数值精确来说是根号五√5 ≈ 2.236。回到填字游戏网格。一个可推理的填字游戏就是一组没有可混淆配对的空格时钟面上的安全消息也具有相同的结构可混淆性图中的“独立集”。区别只是范围不同。我只需要一个网格是安全的而香农想知道当组合不断增大时信道能容纳的最佳乘数是多少他给这个乘数起了个名字“容量”。指引之光这种数学方法的常规应用是单向的给定一个固定的图要求找出其中隐藏的独立集或者确定其最大规模。这就像一个探测器但对我来说更好的探测器并没有帮助因为我的生成程序仍然盲目地生成网格然后几乎把它们全部舍弃。我不需要在一个已有的网格中“找到”独立集我需要“构建”一个独立集从第一个字母开始就让网格的空格形成一个独立集并且拒绝填入任何会破坏这个结构的字母。生成程序仍然带有一定的随机性我始终没能找到一种完全确定的方法来构建可推理的网格。但每次随机选择都有一定的倾向性。在每一步程序都会观察网格下逐渐形成的可混淆性图权衡每个选择避免添加会产生连线的情况即一个给出的字母有两个可能的位置或者两个空格可以填入同一个字母。它会找出那个能打破僵局的方格优先选择留下最少可混淆配对的填充方式并且放弃任何无法挽救的分支。香农的理论不再只是最后用来测试的工具而是从第一步就开始指导网格的构建。最终生成的可玩网格达到了数千个。虽然仍然会遇到一些棘手的情况需要提高重试次数、放宽超时限制或重新启动生成程序但现在已经有了一个包含超过 9000 个可玩谜题的库大约相当于十年的每日谜题量。重新认识这个数字我最初给这篇文章起的标题其实是本末倒置的。“无人知晓的数字”并非数学前沿的某个遥远常数它就存在于每个网格中以微小的形式呈现。游戏中的每一步都是一个小问题只有一个答案这个字母应该填入哪个格子大多数情况下周围的单词会明确给出答案你无需思考就能做出选择。但当两个格子都能填入给定的字母并且都能组成真实的单词时问题就出现了此时棋盘上没有任何线索能让你做出选择。在那一刻正确的格子真的是无法确定的不是难以计算或计算速度慢而是仅根据字母本身根本无法确定。这就是那个无人知晓的数字。解决办法就是通信领域中最古老的方法就像你在信号不好的电话里拼写名字时所做的那样增加上下文信息。揭开一个新的方格确定一个交叉的单词那个原本无法确定的格子就会变成唯一的选择。阿尔弗雷德·诺思·怀特海曾经说过“追求简单但不要轻信简单。”这个教训我似乎注定要反复学习。而你则可以完全信任这个游戏一个字母一个格子绝无猜测。这是一款真实的游戏叫[Motplot](https://motplot.app)。如果你感兴趣不妨试试看。