苦苦挣扎,制作算法,为益智游戏生成板

时间:2011-03-03 00:46:01

标签: c# algorithm puzzle

我正在寻找一个数字益智游戏。为了这个问题,我们假设电路板是一个由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#写的。

10 个答案:

答案 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)

没有正方形的数独听起来有点像数独。 :)

http://www.codeproject.com/KB/game/sudoku.aspx

他们在那里使用的板生成器代码有一个解释。

答案 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)即可生成新的解决方案。这些新的解决方案当然在逻辑上是相同的,但对于玩家来说,它们看起来会有所不同。

可以通过将初始解决方案中的每个标识符作为数组的索引处理,然后对该数组进行混洗来完成排列。