是的,我知道这不是什么新鲜事,已经有很多问题(它甚至有自己的标签),但是我想用Java创建一个Sudoku Solver,仅仅是为了训练自己编写代码这更有效率。
在程序中执行此操作的最简单方法可能是在每个列和行中解析大量的for循环,收集每个单元格的可能值,然后只用一种可能性清除单元格(它们是否只包含1个)数字,或者它们是其行/列中包含此数字的唯一单元格),直到您有一个已解决的拼图。当然,纯粹想到这个动作应该会引起每个程序员的注意。
我正在寻找的是以最有效的方式解决这个问题的方法(请尽量不要包含太多的代码 - 我想自己想出那个部分)。
如果可能的话,我想避免使用数学算法 - 那些太容易了,而且100%不是我的工作。
如果有人可以为解决数独谜题(无论是通过人类还是计算机)提供一步一步,有效的思考过程,我会非常高兴:)。我正在寻找一些模糊的东西(所以这是一个挑战),但足够的信息(所以我不会完全迷失)让我开始。
非常感谢,
Justian Meyer
修改
看着我的代码,我开始思考:存储这些解决状态(即数独网格)的一些可能性。我想到了2D阵列和3D阵列。哪个可能最好? 2D可能更容易从表面进行管理,但3D阵列也会提供“盒子”/“笼子”数字。
修改
没关系。我要使用3D阵列。
答案 0 :(得分:1)
这取决于你如何定义效率。
您可以使用强力方法搜索每个列和行,收集每个单元格的可能值,然后只用一种可能性清除单元格。
如果剩下的细胞有多种可能性,保存谜题状态,选择具有最少可能性的细胞,选择其中一种可能性,并尝试解决谜题。如果您选择的可能性导致拼图矛盾,则恢复已保存的拼图状态,返回单元格并选择其他可能性。如果您选择的单元格中没有任何一种可能性解决了这个难题,请选择具有最少可能性的下一个单元格。循环通过剩余的可能性和细胞,直到你解决了这个难题。
尝试解决难题意味着搜索每个列和行,收集每个单元格的可能值,然后只用一种可能性清除单元格。当所有细胞被淘汰后,你就解决了这个难题。
您可以使用逻辑/数学方法,在解决难题之前,您的代码会尝试不同的策略。使用“数独策略”搜索Google以查看不同的策略。使用逻辑/数学方法,您的代码可以“解释”拼图是如何解决的。
答案 1 :(得分:1)
当我创造我的时候,我想我可以使用一套规则来解决每一块板子而不进行任何回溯。这被证明是不可能的,因为即使针对人类玩家的谜题也可能需要做出一些假设。
所以我开始实现解决难题的基本“规则”,试图找到下一个要实现的规则,以便解决上次停止的位置。最后,我被迫添加了一个强制递归算法,但大多数谜题实际上是在不使用它的情况下解决的。
我写了一篇关于我的数独求解器的博文。只需阅读“算法”部分,您就可以了解我是如何进行的。
答案 2 :(得分:1)
如果有人需要参考Android实现,我写了一个使用上面帖子中的算法的解决方案。
完整的开源代码:https://github.com/bizz84/SudokuSolver
此外,此解决方案从Web服务器加载JSON格式的Sudoku Puzzles并回发结果。
答案 3 :(得分:0)
您应该考虑将数独问题减少到SATisfiability problem。
这种方法可以避免您对AI进行mathematically
但更多logically
的考虑。
目标一步一步基本上是:
* Find all the constraints that a Sudoku has. (line, column, box).
* Write these constraints as boolean constraints.
* Put all these constraints in a Boolean Satisfiability Problem.
* Run a SAT solver (or write your own ;) ) on this problem.
* Transform the SAT solution into the solution of the initial Sudoku.
使用Ivor Spence由SAT4J完成,你可以在这里找到他工作的Java Applet:http://www.cs.qub.ac.uk/~I.Spence/SuDoku/SuDoku.html。
您也可以直接从SAT4J网站下载Java代码,看看它的样子:http://sat4j.org/products.php#sudoku。
最后,这种方法的最大优点是:你可以解决N*N Sudokus
,而不仅仅是典型的9*9
,我认为这对AI来说更具挑战性:)。