【问题标题】:Programming Design Help - How to Structure a Sudoku Solver program? [closed]编程设计帮助 - 如何构建数独求解器程序? [关闭]
【发布时间】:2012-05-15 20:08:53
【问题描述】:

我正在尝试用 Java(可能是 Python)创建一个数独求解程序。 我只是想知道我应该如何构建这个......

我是否创建一个类并使每个框都成为该类的对象(9x9=81 个对象)?如果是,我如何控制所有对象 - 换句话说,我如何让它们都调用类中的某个方法?

我是否只是创建函数来计算并使用多维数组之类的东西控制其中的所有数字?

实际上,即使我可以创建多个函数,如果我要让每个盒子成为一个对象,我将如何控制所有对象?

谢谢。

【问题讨论】:

  • 如果您遇到困难并且对解决方案的演练感兴趣,Peter Norvig 写了一篇关于用 Python 实现的Sudoku solver 的文章。
  • 您是在寻找用于存储/显示的数据结构还是作为求解器一部分的数据结构?

标签: python data-structures sudoku


【解决方案1】:

不要过度设计它。它是一个二维数组,或者可能是一个最多代表二维数组的 Board 类。具有计算给定行/列的函数以及可让您访问每个正方形的函数。可以使用其他方法来验证每个 sub-3x3 和行/列不违反所需的约束。

【讨论】:

  • 如果对象有利于隐藏复杂性,为什么不呢?它应该隐藏二维数组的选择并将其抽象出来。
  • 在需要之前不要增加复杂性——这里不需要。
  • 特别是因为您不应该在内部使用二维数组。一个一维数组足以与 Board 类一起隐藏 x*9+y 的东西。
【解决方案2】:

好吧,我会为数独本身使用一个类,它具有 9 x 9 数组以及添加数字和检测模式中的错误的所有功能。

另一个类将用于解决难题。

【讨论】:

    【解决方案3】:

    最简单的方法是用 2D 9x9 数组表示棋盘。您需要将每一行、每一列和 3x3 框的引用作为一个单独的对象,因此将每个单元格存储在 String 中(在 Java 中)比使用原语更有意义。使用字符串,您可以在多个容器中保留对同一对象的引用。

    【讨论】:

      【解决方案4】:

      你需要用 Python 还是 Java 来做?我在 Python 中进行了很多编程,但是使用 AMPL 或 GLPK 之类的语言使用整数程序可以更简洁地完成此操作,我发现此类问题更优雅(并且通常更有效)。

      这是在 AMPL 中,虽然我还没有验证它是如何工作的: http://taha.ineg.uark.edu/Sudoku.txt

      【讨论】:

        【解决方案5】:

        只是为了好玩,这应该是最短的程序,在 python 中,可以解决数独网格:

        def r(a):i=a.find('0') if i<0:print a [m in[(i-j)%9*(i/9^j/9)*(i/27^j/27|i%9/3^j%9/3)or a[j]for j in range(81)]or r(a[:i]+m+a[i+1:])for m in`14**7*9`]r(raw_input())
        

        嗯,好吧,这很神秘,我认为它与您的问题不符,所以我为这种噪音道歉:)

        无论如何,您会找到对这 173 个字符 here 的一些解释。 还有法语解释here

        【讨论】:

          【解决方案6】:

          也许一个设计中每个方格都有一个盒子,而另一个代表谜题本身的类将包含一组盒子,包含盒子交互的所有规则,并控制整个游戏,这将是一个不错的设计。

          【讨论】:

            【解决方案7】:

            首先,看起来有两种细胞。

            • 已知调用;有固定值的,别无选择。

            • 未知细胞;那些具有一组候选值的人,这些候选值减少到一个最终值。

            第二,有几组细胞。

            • 水平行和垂直列必须包含每个值的一个单元格。该约束用于从行或列中的各个单元格中删除值。

            • 3x3 块,每个值必须有一个单元格。该约束用于从块中的各个单元格中删除值。

            最后是整体网格。这有几个互补的观点。

            • 有 81 个单元格。

            • 细胞也被收集到一个由 3x3 块组成的 3x3 网格中。

            • 细胞也被收集到 9 列中。

            • 细胞也被收集成9行。

            你有一个求解器策略对象。

            1. 它设置为将set( range(1,10) ) 作为候选值的每个未知单元格。

            2. 对于每一行、每一列和 3x3 块(27 个不同的集合):

              一个。对于每个单元格:

              • 如果它具有确定的值(已知单元格和未知单元格的实现方式不同):从该分组中的所有其他单元格中删除该值。

            以上必须迭代,直到没有发现任何变化。

            此时,您要么解决了它(所有单元格都报告了一个确定的值),要么您有一些单元格具有多个值。现在,您必须使用复杂的回溯求解器来找到“有效”的剩余值的组合。

            【讨论】:

            • 一个“求解器策略对象”?你是说,搜索功能?
            • @Harlequin:也许只是搜索。但是,它会在搜索过程中更新单元格的状态。也许它并不是真正的 Strategy 设计模式。我想大声回答问题,而不是真正解决问题。
            【解决方案8】:

            包含 81 个整数的一维数组(0 为空)的类对于规则类来说就足够了。规则类强制执行规则(每行、每列或 3x3 方格中没有重复的数字)。它还有一个包含 81 个布尔值的数组,因此它知道哪些单元格是固定的,哪些需要解决。此类的公共接口具有操作板所需的所有方法:

            int getCell(int x, int y);
            bool setCell(int x, int y, int value);
            bool clearCell(int x, int y);
            int[] getRow(int x);
            int[] getCol(int y);
            int[] getSubBox(int x, int y);
            void resetPuzzle();
            void loadPuzzle(InputStream stream);
            

            然后你的求解器使用这个类的公共接口来解决这个难题。我认为求解器的类结构是编写第 5 百万个数独求解器的目的。如果您正在寻找提示,我稍后会编辑此帖子。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2017-02-02
              • 1970-01-01
              • 2011-03-25
              • 2014-06-18
              • 2011-05-19
              • 2013-05-04
              • 1970-01-01
              相关资源
              最近更新 更多