我正在寻找一个数字益智游戏。为了这个问题,我们假设电路板是一个由4 x 4个正方形组成的网格。 (在实际的益智游戏中,这个数字将是1..15)
一个数字可能只在每列中出现一次,在每一行中出现一次,有点像数独,但没有“正方形”。
有效:
[1, 2, 3, 4
2, 3, 4, 1
3, 4, 1, 2
4, 1, 2, 3]
我似乎无法想出一种能够始终生成有效的随机n x n板的算法。
我是用C#写的。
答案 0 :(得分:8)
首先阅读我关于图着色算法的系列文章:
http://blogs.msdn.com/b/ericlippert/archive/tags/graph+colouring/
这似乎与您的问题无关,但是当您完成时,您会发现它与您的问题有关。
好了,既然你已经读过了,你知道你可以使用图形着色算法来描述类似Sudoku的谜题,然后解决这个谜题的特定实例。但显然你可以使用相同的算法生成谜题。
首先定义完全连接的图形区域。
然后修改算法,使其尝试查找两个解决方案。
现在创建一个空白图表并随机将其中一个区域设置为随机颜色。尝试解决图表。有两种解决方案吗?然后添加另一种随机颜色。再试一遍。没有解决方案吗?然后备份一个步骤并添加不同的随机颜色。
继续这样做 - 添加随机颜色,在没有解决方案的情况下进行回溯,并继续直到获得具有独特解决方案的拼图。而且你已经完成了;你有一个随机的拼图生成器。
答案 1 :(得分:3)
似乎你可以使用这个有效的例子作为算法的输入,该算法随机地随机交换两行,然后随机地交换两个随机列。
答案 2 :(得分:2)
您需要尝试的组合太多。您可以随时重新排列有效的电路板,使顶行为1,2,3,4(通过重新映射符号),左列为1,2,3,4(通过重新排列第2行至第4行)。在每一行中,其余3个符号只有6个排列,因此您可以循环查看这些符号以查找216个可能的电路板中的哪些有效。你也可以存储有效的。
然后随机选择一个有效的板,随机重新排列行,并随机重新分配符号。
答案 3 :(得分:2)
我不会说C#,但以下算法应该很容易翻译。
将由数字1..N组成的集合与每行和每列相关联:
for i = 1 to N
row_set[i] = column_set[i] = Set(1 .. N)
然后单次通过矩阵,从该行和列有效的集合元素中随机选择每个位置的条目。删除从相应的行和列集中选择的数字。
for r = 1 to N
for c = 1 to N
k = RandomChoice( Intersection( column_set[c], row_set[r] ))
puzzle_board[r, c] = k
column_set[c] = column_set[c] - k
row_set[r] = row_set[r] - k
next c
next r
答案 4 :(得分:2)
您希望生成统一分布的Latin Squares。
此pdf描述了Jacobson和Matthews的方法(已在其他地方发布,其参考资料可在此处找到:http://designtheory.org/library/encyc/latinsq/z/)
或者你可以预先生成一个“很多”(在发货之前:-)),将其存储在一个文件中并随机选择一个。
希望有所帮助。
答案 5 :(得分:0)
我能想到的最简单的方法就是创造一个局部游戏并解决它。如果它不可解决,或者它是错误的,那就再做一个。 ; - )
答案 6 :(得分:0)
答案 7 :(得分:0)
查看http://www.chiark.greenend.org.uk/~sgtatham/puzzles/ - 他有几个具有这种约束的谜题(其中包括)。
答案 8 :(得分:0)
使用您的第一个有效示例:
1 2 3 4
2 3 4 1
3 4 1 2
4 1 2 3
然后,随机创建{1,2,3,4}的2个排列。
使用第一行置换行,然后使用第二行置换列。
您可以在Knuth的The Art of Computer Programming (TAOCP),第4卷分册2,生成所有元组和排列(2005),v + 128pp中找到几种创建排列的方法。国际标准书号0-201-85393-0。
如果您在图书馆中找不到副本,可以在他的网站上找到预印本(讨论排列的部分):fasc2b.ps.gz
编辑 - 更正
上述解决方案类似于500-Intenral Server Error的解决方案。但我认为两者都找不到所有有效的安排。
例如,他们会找到:
1 3 2 4
3 1 4 2
2 4 1 3
4 2 3 1
但不是这一个:
1 2 3 4
2 1 4 3
3 4 1 2
4 3 2 1
需要再做一步:重新排列行和列后(使用我或500的方式),再创建一个排列(让我们称之为s3
)并使用它来置换数组中的所有数字。< / p>
s3 = randomPermutation(1 ... n)
for i=1 to n
for j=1 to n
array[i,j] = s3( array[i,j] )
答案 9 :(得分:0)
进一步解决方案就是这样。假设您有许多解决方案。对于它们中的每一个,您只需置换标识符(1..15)即可生成新的解决方案。这些新的解决方案当然在逻辑上是相同的,但对于玩家来说,它们看起来会有所不同。
可以通过将初始解决方案中的每个标识符作为数组的索引处理,然后对该数组进行混洗来完成排列。