几年前我写了一个扫雷求解器,但可惜我似乎从那以后丢失了代码。我记得的是,这是一种蛮力方法,它编译了一组潜在的地雷,而不是像你正在做的那样把组合打包。
我相信你正在使用的算法更有能力。如果它完全充满或没有地雷,或者它是另一个条件的子集,您的方法可以“解决”一个条件。但是,有一些扣除是无法处理的。例如,考虑这个小的 7x2 板,其中a
通过h
瓷砖是未知的:
a 2 1 2 1 2 i
b c d e f g h
您的条件将是:
[2, {a, b, c, d}],
[1, {c, d, e}],
[2, {d, e, f}],
[1, {e, f, g}],
[2, {f, g, h, i}]
如果我理解正确,您的算法无法对此做出任何推论。但是,如果您是一位经验丰富的扫雷玩家,您会发现1 2 1
中心的图案只有一个解决方案,地雷低于1
s:
a 2 1 2 1 2 i
b 2 * 2 * 2 h
仍然有一些未知数,在 or 下有一个地雷,在ora
下b
还有另一个,但如果这是一个更大的谜题的一部分,您以后可能会弄清楚(或者您可能不得不猜测)。h
i
我相信我的一套地雷方法是这样工作的:
对于已扩展的每个图块,收集一组其所有未扩展的邻居(“区域”),以及包含该区域中可能出现的所有地雷组的列表。因此,例如,上面示例中的 5 个已知图块将生成(从左到右):
({a, b, c, d}, [{a, b}, {a, c}, {a, d}, {b, c}, {b, d}, {c, d}])
({c, d, e}, [{c}, {d}, {e}])
({d, e, f}, [{d, e}, {d, f}, {e, f}])
({e, f, g}, [{e}, {f}, {g}])
({f, g, h, i}, [{f, g}, {f, h}, {f, i}, {g, h}, {g, i}, {h, i}])
无论如何,要结合两个条件,我首先通过与区域集相交来检查它们是否重叠。如果没有重叠,则不能有效地组合条件。
但是,如果存在重叠,则新条件将跨越其区域的联合。至于地雷的集合,我会做外部集合的笛卡尔积以获得内部集合对,然后检查是否存在矛盾。如果在这些区域的交叉点内,这两组没有完全相同的地雷,就会产生矛盾。如果没有矛盾,一个新的组合集合将由矿山位置的联合组成。以下是上面前两行的组合方式:
Intersection of areas: {a, b, c, d} & {c, d, e} = {c, d}
New combined area: {a, b, c, d} | {c, d, e} = {a, b, c, d, e}
Cartesian product of mine sets (with X marking contradictions):
| {a, b} {a, c} {a, d} {b, c} {b, d} {c, d}
---+-------------------------------------------------
{c}| X {a, c} X {b, c} X X
{d}| X X {a, d} X {b, d} X
{e}| {a, b, e} X X X X X
New condition: ({a, b, c, d, e}, [{a, b, e}, {a, c}, {b, c}, {a, d}, {b, d}])
您可以通过简单地计算它属于多少组(相对于总共有多少组)来计算条件区域内的任何图块成为地雷的几率。因此,鉴于上述综合条件,您可以a
计算出 3/5 的时间是地雷,而e
只有 1/5 的时间。当程序需要在没有任何保证安全的图块时猜测要扩展的位置时,此信息很重要。我想我还做了一些复杂的组合来说明使用的地雷数量(因此上面的 {a, b, e} 案例的权重与其他案例略有不同,因为它使用三个地雷而不是两个),但恐怕我不记得细节了。
扫雷是一款非常具有挑战性的游戏。我相信我的程序能够在大约 50-60% 的时间内解决相当于“困难”难度的棋盘,大部分损失发生在开始时(当您必须猜测几乎没有信息可以工作时)或就在结束(当经常有一些无法解决的领域需要猜测时)。它通常非常快,尽管偶尔会出现一种瓷砖图案,导致它在下一步行动之前停滞 10 或 15 秒。(Minesweeper 是 NP-complete 的,所以有些输入不能快速求解也就不足为奇了!)