【问题标题】:Sudoku solving algorithm isn't working as expected数独求解算法未按预期工作
【发布时间】:2014-04-04 02:46:52
【问题描述】:

我正在尝试编写一个解决数独的程序。 我正在使用回溯来解决这个难题。

据我所知,我的代码应该可以工作,但显然不能。 我在代码的不同阶段查看了这个谜题,它根本没有改变。 我不知道该怎么办。

代码如下:

public class main {

    public static int[][] originalGrid;

    public static void main(String[] args){
        int[][] grid = {{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}};
        originalGrid = grid;
        solveSudoku(grid, 0, 0);
        System.out.println("Done!");
    }

    public static boolean solveSudoku(int[][] grid, int row, int col) {

        //base case
        if (noUnassignedLocation(grid)){
            printGrid(grid);
            return true;
        }

        for (int i = 0; i < 9; i++) {
            if (noConflict(grid)) {

                if (originalGrid[row][col] == 0)
                    grid[row][col] = i;

                printGrid(grid);

                col++;
                if (col == 9) {
                    col = 0;
                    if (row != 8)
                        row++;
                }
                if (solveSudoku(grid, row, col))
                    return true;
                grid[row][col] = 0;
                col--;
                if (col == 0) {
                    col = 9;
                    row--;
                }
            }
        }
        printGrid(grid);
        return false;
    }

    public static boolean noConflict(int[][] grid) {
        for (int i = 0; i < 9; i++) {
            for (int j = 0 ; j < 9; j++) {
                int current = grid[i][j];

                //System.out.println("i: " + i + " j: " + j);

                for (int k = 0; k < 9; k++) {
                    if (current == grid[k][j] && k != i && current != 0 && grid[k][j] != 0) {
                        return false;
                    }
                }
                for (int k = 0; k < 9; k++) {
                    if (current == grid[i][k] && k != j && current != 0 && grid[i][k] != 0) {
                        return false;
                    }
                }
                //check block
            }
        }
        return true;
    }

    public static boolean noUnassignedLocation(int[][] grid) {
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                if (grid[i][j] == 0) {
                    return false;
                }
            }
        }
        return true;
    }

    private static void printGrid(int[][] grid) {
        System.out.println("###########");
        for (int i = 0; i < 9; i++) {
            String line = new String();
            for (int j = 0; j < 9; j++) {
                line = line + grid[i][j];
            }
            System.out.println("#" + line + "#");
        }
        System.out.println("###########");
    }
}

【问题讨论】:

  • 提示:使用调试器...
  • 哇,我什至不知道有这样的东西存在。谢谢斯蒂芬(PS:这不是讽刺)

标签: java algorithm sudoku backtracking


【解决方案1】:

希望这对您或将来的任何人有所帮助!

程序中有很多错误。重写了solveSudoku(),完成了noConflict()方法。

public class Sudoku {
public static void main(String[] args) {
    int[][] grid = { 
            { 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 } 
        };

    //originalGrid = grid;
    solveSudoku(grid);
    System.out.println("Done!");
    printGrid(grid);
}

public static boolean solveSudoku(int[][] grid) {

    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            if (grid[i][j] != 0) {
                continue;
            }
            for (int num = 1; num <= 9; num++) {
                if (noConflict(grid)) {
                    grid[i][j] = num;
                    if (solveSudoku(grid)) {
                        return true;
                    } else {
                        grid[i][j] = 0;
                    }
                }
            }
            return false;
        }
    }
    return true;
}

/** 
 * Checks row, column and box have unique values.
 * 
 * @param grid
 * @return
 */
public static boolean noConflict(int[][] grid) {
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            //int current = grid[i][j];

            // check row unique
            for (int k = 0; k < 9; k++) {
                if (grid[i][j] == grid[k][j] && k != i && grid[i][j] != 0
                        && grid[k][j] != 0) {
                    return false;
                }
            }

            //check column unique
            for (int k = 0; k < 9; k++) {
                if (grid[i][j] == grid[i][k] && k != j && grid[i][j] != 0
                        && grid[i][k] != 0) {
                    return false;
                }
            }

            // check block
            for (int row = (i/3)*3; row < (i/3)*3+3; row++) {
                for (int col = (j/3)*3; col < (j/3)*3+3; col++) {
                    if(row != i && col!=j && grid[row][col]==grid[i][j] && grid[i][j] != 0) {
                        return false;
                    }
                }
            }

        }
    }
    return true;
}

public static boolean noUnassignedLocation(int[][] grid) {
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            if (grid[i][j] == 0) {
                return false;
            }
        }
    }
    return true;
}

private static void printGrid(int[][] grid) {
    System.out.println();
    for (int i = 0; i < 9; i++) {
        String line = new String();
        for (int j = 0; j < 9; j++) {
            line = line + grid[i][j];
        }
        System.out.println(line);
    }
    System.out.println();
}
}

【讨论】:

  • 哇,谢谢。我会修复我自己的代码,看看你改变了什么。我希望我能从中吸取教训。
【解决方案2】:

我可以看到的一个问题是这里

if (originalGrid[row][col] == 0)
    grid[row][col] = i;

您似乎假设gridoriginalGrid 是不同的二维数组。事实上,由于您初始化它们的方式,它们是同一个数组。这个:

originalGrid = grid;

是一个简单的引用赋值。它不会复制grid 数组。

【讨论】:

  • 是的,虽然我认为这不会真正影响解决方案,因为代码从未从“originalGrid”中为“grid”赋值。不过,这是一个很好的收获。
  • originalGrid 背后的想法是,我不会在给出数字的位置放置数字。
  • @diveshpremdeep - 这种合理化是站不住脚的。由于只有一个数组(真的!),分配给grid 更改originalGrid。我确定这不是本意...
猜你喜欢
  • 2016-08-13
  • 1970-01-01
  • 2016-01-02
  • 2022-11-04
  • 2023-03-20
  • 2023-03-16
  • 1970-01-01
  • 2015-05-25
  • 1970-01-01
相关资源
最近更新 更多