【问题标题】:Sudoku algorithm not backtracking properly数独算法没有正确回溯
【发布时间】:2016-10-01 16:54:18
【问题描述】:

我正在制作一个数独求解器,它会尝试一个正方形中的所有可能值,如果没有找到解决方案,则回溯。我相信我有一个几乎可以工作的算法,但到目前为止它只在一个 16 单元拼图的第 0、2 和 3 行上工作。

public boolean fillBoard(int[][] board, int row, int col){
    int index = 1;              //Next value to try when an empty is found
    boolean solved = false;

    for(int i = row; i < width; i++){       //For each row
        for(int j = col; j < height; j++){  //For each column
            if(board[i][j]==0){             //0 represents empty
                while(!solved){
                    board[i][j] = index;
                    if(checker.checkRow(board[i]) 
                            && checker.checkColumn(columnToArray(board, j))
                            //&& checker.checkBox(<input>)
                            ){
                            solved = fillBoard(board, i, 0);
                    }else{
                        if(index < width){
                            index++;
                        }else{
                            return false;
                        }
                    }
                }
            }
        }
    }
    puzzle = copyPuzzle(board);
    return true;
}

现在它不检查第三条数独规则,它只检查列和行。但是,它仍然应该返回一个遵循行和列规则的谜题,对吧?而checkBox方法一旦写好,应该就可以解谜了。我在哪里搞砸了?

编辑几个例子:

对于

的输入
        {1, 2, 0, 0},
        {0, 4, 0, 0},
        {0, 0, 1, 0},
        {0, 0, 3, 2}

程序返回

1 2 4 3 4 4 4 4 2 3 1 4 4 1 3 2

对于一个输入

        {1, 0},
        {2, 0}

它正确地解决了它。

对于

的输入
        { 1, 0, 3, 4, 0, 0 },
        { 4, 0, 6, 0, 0, 3 },
        { 2, 0, 1, 0, 6, 0 },
        { 5, 0, 4, 2, 0, 0 },
        { 3, 0, 2, 0, 4, 0 },
        { 6, 0, 5, 0, 0, 2 }

它返回未解决的难题

编辑:checkRow 询问的人

public boolean checkRow(int[]row){
    HashSet<Integer> set = new HashSet<Integer>();
    for(int i = 0; i < row.length;i++){
        if(!set.add(row[i]) && row[i]>0){//Duplicate?
            return false;
                    }
                }
    return true;
}

【问题讨论】:

  • 请提供它不起作用的具体示例。
  • @ScottHunter 我加了几个例子
  • checkRowcheckColumn 是否只是验证当前行/列不包含 0?递归的退化情况似乎定义不明确,这可以解释算法在最后一个实例中返回一个未解决的难题。我认为您的return true 需要为return solved,并且solved 的值需要针对您的基本情况进行更新。
  • @nbrooks checkRowcheckColumn 将行或列的值添加到集合中,除非值为 0,如果添加失败,则返回 false。他们正在检查以确保到目前为止,添加到行或列的所有值都在那里有效
  • @realmature 你可能想发布checkRowcheckColumn 的实现。另外,一个不相关的提示:尽量保持你的方法干净,没有太多的嵌套语句。有时整洁会导致问题突然出现。

标签: java


【解决方案1】:

问题在于,当值不正确时,它没有将空间重置为 0,所以如果它达到最大索引并且不正确,它就会离开它。下面的代码有效。只是在等待我小组中的另一个人提供复选框检查方法,但我可能最终不得不自己这样做。

public boolean fillBoard(int[][] board, int row, int col){
    int index = 1;              //Next value to try when an empty is found
    boolean solved = false;

    for(int i = row; i < width; i++){       //For each row
        for(int j = col; j < height; j++){  //For each column
            if(board[i][j]==0){             //0 represents empty
                while(!solved){             //While the puzzle is unsolved
                    board[i][j] = index;    //Try to fill with index
                    if(checker.checkRow(board[i]) 
                            && checker.checkColumn(columnToArray(board, j))
                            //&& checker.checkBox(<input>)
                            ){
                            solved = fillBoard(board, i, 0); //Next space
                    }
                    if(!solved) board[i][j] = 0;
                    if(index < width){
                        index++;
                    }else{
                        return false;
                    }                        
                }
            }
        }
    }
    puzzle = copyPuzzle(board);
    return true;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-21
    • 2010-12-03
    • 1970-01-01
    相关资源
    最近更新 更多