【问题标题】:Code explanation of Sudoku SolverSudoku Solver代码解释
【发布时间】:2013-03-03 04:47:00
【问题描述】:

我对以下代码 sn-p 有疑问: 它是一个数独求解器,通过填充空单元格来解决数独难题。 我无法真正了解求解器方法背后的逻辑。为什么在尝试 k=1-9 后返回 false 并在遍历所有单元格后返回 true。我认为我们递归地进入solver()方法,一旦数独完成,它将作为调用顺序返回true,最后第一个调用的solver()将返回true。我想我必须省略一些上述两个“回归”发生的场景。有人可以向我解释为什么那些“回归”应该存在吗?

public class Solution {

public static void main(String[] args) {
    Solution s = new Solution();
    char[][] board = {{'.', '2', '6', '5', '.', '.', '.', '9', '.'},
                      {'5', '.', '.', '.', '7', '9', '.', '.', '4'},
                      {'3', '.', '.', '.', '1', '.', '.', '.', '.'},
                      {'6', '.', '.', '.', '.', '.', '8', '.', '7'},
                      {'.', '7', '5', '.', '2', '.', '.', '1', '.'},
                      {'.', '1', '.', '.', '.', '.', '4', '.', '.'},
                      {'.', '.', '.', '3', '.', '8', '9', '.', '2'},
                      {'7', '.', '.', '.', '6', '.', '.', '4', '.'},
                      {'.', '3', '.', '2', '.', '.', '1', '.', '.'}};

    s.solver(board);
}
public boolean solver(char[][] board) {
    for (int r = 0; r < board.length; r++) {
        for (int c = 0; c < board[0].length; c++) {
            if (board[r][c] == '.') {
                for (int k = 1; k <= 9; k++) {
                    board[r][c] = (char) ('0' + k);
                    if (isValid(board, r, c) && solver(board)) {
                        return true;
                    } else {
                        board[r][c] = '.';
                    }
                 }
                return false;
             }
         }
     }
    return true;
}

public boolean isValid(char[][] board, int r, int c) {
    //check row
    boolean[] row = new boolean[9];
    for (int i = 0; i < 9; i++) {
        if (board[r][i] >= '1' && board[r][i] <= '9') {
            if (row[board[r][i] - '1'] == false) {
                row[board[r][i] - '1'] = true;
            } else {
                return false;
            }
        }
    }

    //check column
    boolean[] col = new boolean[9];
    for (int i = 0; i < 9; i++) {
        if (board[i][c] >= '1' && board[i][c] <= '9') {
            if (col[board[i][c] - '1'] == false) {
                col[board[i][c] - '1'] = true;
            } else {
                return false;
            }
        }
    }

    //check the 3*3 grid
    boolean[] grid = new boolean[9];
    for (int i = (r / 3) * 3; i < (r / 3) * 3 + 3; i++) {
        for (int j = (c / 3) * 3; j < (c / 3) * 3 + 3; j++) {
            if (board[i][j] >= '1' && board[i][j] <= '9') {
                if (grid[board[i][j] - '1'] == false) {
                    grid[board[i][j] - '1'] = true;
                } else {
                    return false;
                }
            }
         }
    }

    return true;
}
}

【问题讨论】:

    标签: java sudoku


    【解决方案1】:

    每个递归调用都会处理第一个'.'仍有待处理。这将暂时用一个数字代替。如果更改成功(不会使板无效),则进行递归(将尝试下一个'.')。如果这将失败,请撤消本地所做的更改并返回 false,因为在此搜索分支上尝试的任何数字都是无效的。这意味着强制调用者(直到root)尝试下一个选择。

    【讨论】:

    • 您能否解释一下最终的“回归真实”何时会发生? solver() 方法的最后一行。谢谢。
    • 只有在数独 完全 解决时才能达到,即第一个没有找到任何'.'的调用
    【解决方案2】:

    这是一个简单的蛮力求解器。它只是尝试每个开放空间中的每个数字。如果在用数字填充给定空间后棋盘是“有效的”(遵循游戏规则),那么它会递归调用相同的求解器函数来填充另一个空白点并测试棋盘是否仍然有效等开。

    它是一个非常低效的求解器,但易于编码。

    【讨论】:

      【解决方案3】:

      此代码检查数独。如果正确,则 check_sudoku() 方法返回 true,如果错误则显示具有重复元素的行号和列号。

        public static void main(String[] args) {
          int array[][]={{9,6,3,1,7,4,2,5,8},
                         {1,7,8,3,2,5,6,4,9},
                         {2,5,4,6,8,9,7,3,1},
                         {8,2,1,4,3,7,5,9,6},
                         {4,9,6,8,5,2,3,1,7},
                         {7,3,5,9,6,1,8,2,4},
                         {5,8,9,7,1,3,4,6,2},
                         {3,1,7,2,4,6,9,8,5},
                         {6,4,2,5,9,8,1,7,3}};
      
          Sudoku sudoku=new Sudoku();
          if(sudoku.check_sudoku(array))
          {
              System.out.println("You won the game :)");
          }
      
      
      }
      
      
      public class Sudoku {
      
      private int temp1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}, temp2[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
      private int data1, data2;
      
      public boolean check_sudoku(int array[][]) {
          for (int i = 0; i < 9; i++) {
              for (int j = 0; j < 9; j++) {
                  data1 = array[i][j];
                  data2 = array[j][i];
                  if (data1 >= 10 || data2 >=10 || data1 <= 0 || data2 <= 0) {
                      System.out.println("Invalid Solution because value must be in between 1 to 9");
                      return false;
                  } else if (temp1[data1 - 1] == 0 || temp2[data2 - 1] == 0) {
                      System.out.println("Invalid Solution please check " + (i + 1) + " row " + (j + 1) + " column or " + (j + 1) + " row " + (i + 1) + " column");
                      return false;
                  } else {
                      temp1[data1 - 1] = 0;
                      temp2[data2 - 1] = 0;
                  }
              }
              int check1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
              int check2[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
              temp1 = check1;
              temp2 = check2;
          }
          return true;
      }
      

      }

      【讨论】:

        猜你喜欢
        • 2021-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-23
        • 2022-01-10
        • 2012-07-20
        • 2010-10-11
        • 2011-09-25
        相关资源
        最近更新 更多