数独解题方法

7
我有一个数独解题方法的问题。程序的运行方式是这样的:当程序开始时,棋盘是空的,用户向棋盘中添加一些数字,然后通过点击“解决”按钮,程序会尝试解决它。除了将相同的数字放在同一行之外,一切都运作良好。因此,如果用户添加1,1,0,0 ... 0,那么在谜题中它就无法解决,因为它有两个相邻的1,并且会一直尝试找到解决方案,即使它是一个不可解的谜题。但是,如果它们都是0(空),它会立即解决,就像我把1和2放在左上角一样。如果我只是随便放一些数字,它会检测出它是不可解的(或者如果它是一个有效的谜题,则会解决它)。
我想说的是,当 theNumber == (row,col) equals thenNumber == (row+1,col)时,应该返回false,因为这是重复的数字。
这是我尝试在解决方法中添加的代码,显然没有成功。
if ((puzzle.getNum(row, col) == a) == (puzzle.getNum(row + 1, col) == a)) {
   return false;
}

非常感谢您的帮助


3
你是否尝试在“解决”之前添加某种验证?如果你能立即知道谜题无法解决(例如有两个相邻的1),那么你就不需要陷入无限循环中试图解决。 - Walls
1
将变量名从a、i、j更改为有意义的名称可以使代码更易读。或者添加一些注释也会非常有帮助。我尽量使用有意义的变量名,这样可以简化故障排除过程。 - Chris.Stover
是的,那些变量应该被更改。 - Michael
我非常喜欢Java,但在某些问题上使用其他编程语言会更好。例如,数独求解器是一个人工智能问题,对于这个问题,Prolog比Java更好。可以查看此代码片段https://gist.github.com/ademar111190/3224223,它可以帮助您从不同的角度看待数独问题。请注意,Prolog可以在Java内部运行 ;) - ademar111190
我相信他知道求解器是什么。只是不知道如何实际编写它。 - Michael
显示剩余2条评论
1个回答

4

按照以下方式验证谜题:

  1. 创建一个包含9个元素的布尔数组。
  2. 循环遍历每一行、列和9x9的盒子。
    • 如果读取到一个数字,则将数组中对应的值设置为true。
    • 如果已经是true,则抛出错误(不可能的迷题)。
    • 在读取完一行、列或9x9盒子后,重置布尔数组。
  3. 然后,如果验证成功,请调用解决方法。

编辑:源代码

public boolean checkPuzzle() {
    boolean[] nums = new boolean[9];
    for (int row = 0; row < panel.puzzleSize; row++) {
        for (int cell = 0; cell < panel.puzzleSize; cell++) {
            if (nums[puzzle[row][cell]]) return false;
            nums[puzzle[row][cell]] = true;
        }
        nums = new boolean[9];
    }
    for (int col = 0; col < panel.puzzleSize; col++) {
        for (int cell = 0; cell < panel.puzzleSize; cell++) {
            if (nums[puzzle[cell][col]]) return false;
            nums[puzzle[cell][col]] = true;
        }
        nums = new boolean[9];
    }
    for (int square = 0; square < panel.puzzleSize; square++) {
        int squareCol = panel.squareSize * (square % panel.squareSize);
        int squareRow = panel.squareSize * Math.floor(square / panel.squareSize);
        for (int cell = 0; cell < panel.puzzleSize; cell++) {
            int col = cell % panel.squareSize;
            int row = Math.floor(cell / panel.squareSize);
            if (nums[puzzle[squareCol + col][squareRow + row]]) return false;
            nums[puzzle[squareCol + col][squareRow + row]] = true;
        }
        nums = new boolean[9];
    }
    return true;
}

没有太多时间测试,但它可能有效(?)行 / 列变量命名可能不正确,因为我没有时间在你的代码中查找,但这对其是否起作用并不重要。


我的方法中的代码会是什么样子?因为我很难实现某种验证方法。我知道我需要循环遍历我的行、列,但我不太确定如何执行第二步。 - Rob
在调用解决方法(反复调用check()的方法)之前,您必须这样做。我建议您使用三个循环来循环遍历行、列和9x9块。然后在它们内部实现更新布尔数组的代码并检查相同数字的代码。我无法提供代码,因为我不知道您的解决代码是什么,除了check()方法。您应该这样做:if (boolean_array[found_number]) { /* fail */ } boolean_array[found_number] = true; - PurkkaKoodari
我会尝试您的建议,同时我编辑了我的主贴并添加了我的源代码。 - Rob
我会查看源代码并尝试编写一些代码,但是不要期望太高,因为我对Java还很陌生。 - Michael
@Rob 是的。我得走了,请在评论中告诉我是否正确,我明天会回来(因为要上学,大约20小时后)。 - PurkkaKoodari
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接