回溯:在Java中创建数独求解器

时间:2018-12-05 13:58:22

标签: java

我的代码的目的类似于迷宫的回溯算法,目的是计算9×9数独的解决方案。 Sudoku及其解决方案像迷宫一样存储在二维int数组中。 我知道:backtracking算法尝试从第1段开始的自由字段(值然后为0)开始,从单元格[0.0]输入1 ... 9的值。测试这是否是一个有效值有点迷宫比迷宫要复杂得多,在迷宫中,只需要检查一下牢房是否空闲即可。我认为使用这些方法是一个好主意 isRowOk isColOk isBlockOk 要利用检查是否完全允许该值,即该块中尚未包含该值。 然后这三个函数必须全部通过OK,然后回溯算法尝试递归在下一个空闲单元格中输入值1 ... 9。否则,如果尝试了所有数字1 ... 9,则搜索将被取消(回溯),并且将在呼叫搜索中尝试下一个可能的号码。 有没有人有一个更好的主意,因为我的代码无法正常工作?

包装测试;

数独类数独{

private final int BLOCK_SIZE = 3;

private final int ROW_SIZE = BLOCK_SIZE * BLOCK_SIZE;

private int nrOfSolutions, nrOfTests;

private int[][] board;

private int[][][] testBoard = {
        /* |---------|---------|---------| */
        { { 5, 3, 0, 0, 7, 0, 0, 0, 0 }, { 6, 0, 0, 1, 9, 5, 0, 0, 0 }, { 0, 9, 8, 0, 0, 0, 0, 6, 0 },
                /* |---------|---------|---------| */
                { 8, 0, 0, 0, 6, 0, 0, 0, 3 }, { 4, 0, 0, 8, 0, 3, 0, 0, 1 }, { 7, 0, 0, 0, 2, 0, 0, 0, 6 },
                /* |---------|---------|---------| */
                { 0, 6, 0, 0, 0, 0, 2, 8, 0 }, { 0, 0, 0, 4, 1, 9, 0, 0, 5 }, { 0, 0, 0, 0, 8, 0, 0, 7, 9 } },
        /* |---------|---------|---------| */

        /* |---------|---------|---------| */
        { { 5, 3, 4, 6, 7, 8, 9, 1, 2 }, { 6, 7, 2, 1, 9, 5, 3, 4, 8 }, { 1, 9, 8, 3, 4, 2, 5, 6, 7 },
                /* |---------|---------|---------| */
                { 8, 5, 9, 7, 6, 1, 4, 2, 3 }, { 4, 2, 6, 8, 5, 3, 7, 9, 1 }, { 7, 1, 3, 9, 2, 4, 8, 5, 6 },
                /* |---------|---------|---------| */
                { 9, 6, 1, 5, 3, 7, 2, 8, 4 }, { 2, 8, 7, 4, 1, 9, 6, 3, 5 }, { 3, 4, 5, 2, 8, 6, 1, 7, 0 } },
        /* |---------|---------|---------| */

        /* |---------|---------|---------| */
        { { 0, 0, 0, 5, 4, 2, 0, 0, 0 }, { 9, 6, 7, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 3, 1, 8 },
                /* |---------|---------|---------| */
                { 0, 0, 0, 0, 7, 0, 8, 6, 4 }, { 0, 2, 0, 6, 0, 4, 0, 9, 0 }, { 6, 4, 5, 0, 1, 0, 0, 0, 0 },
                /* |---------|---------|---------| */
                { 8, 9, 1, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 5, 4, 7 }, { 0, 0, 0, 3, 2, 6, 0, 0, 0 } },
        /* |---------|---------|---------| */

};

public void testSudokuSolver() {
    for (int[][] s : this.testBoard) {
        this.board = s;
        this.print();

        nrOfSolutions = 0;
        nrOfTests = 0;
        this.solve(0, 0);
    }
}

private boolean isBlockOk(int row, int col, int num) {

    int iRowStart = (row / BLOCK_SIZE) * BLOCK_SIZE;
    int iColStart = (col / BLOCK_SIZE) * BLOCK_SIZE;

    for ( int irow = iRowStart; irow < iRowStart + BLOCK_SIZE; irow++) {
        for ( int icol = iColStart; icol < iColStart + BLOCK_SIZE; icol++) {

            if (num == board[irow][icol]) {
                return false;
            }
        }
    }
    return true;
}

private boolean isRowOk(int row, int num) {
    for (int i = 0; i < ROW_SIZE; i++) {
        if (num == board[row][i]) {
            return false;
        }
    }
    return true;
}

private boolean isColOK(int col, int num) {
    for (int i = 0; i < ROW_SIZE; i++) {
        if (num == board[i][col]) {
            return false;
        }
    }
    return true;
}

public void print() {
    final String horizBorder = " ┼────────┼────────┼────────┼";

    System.out.println();

    for (int i = 0; i < ROW_SIZE; i++) {
        if (0 == i % 3) {
            System.out.println(horizBorder);
        }

        for (int j = 0; j < ROW_SIZE; j++) {
            if (0 == j % 3) {
                System.out.print(" │ ");
            }

            int num = board[i][j];
            if (num == 0) {
                System.out.print("_ ");
            } else {
                System.out.print(num + " ");
            }

        }
        System.out.println(" │");
    }
    System.out.println(horizBorder);
}

private boolean isValid(int num, int row, int col) {
    return (isBlockOk(row, col, num) && isColOK(col, num) && isRowOk(row, num));
}

public boolean solve(int row, int col) {

    for (int i = 1; i < BLOCK_SIZE; i++) {
        for (int j = 1; j < BLOCK_SIZE; j++) {
            if (board[i][j] == 0) {
                for (int k = 1; k <= 9; k++) {
                    board[i][j] = k;
                    if (isValid(i, j, k) && solve(i, col)) {
                        return true;
                    }
                    board[i][j] = 0;
                }
                return false;
            }
        }
    }
    return true;
}

public static void main(String[] args) {
    new Sudoku().testSudokuSolver();
}

}

0 个答案:

没有答案