Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/400.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用回溯法在java中求解数独_Java_Algorithm_Artificial Intelligence - Fatal编程技术网

用回溯法在java中求解数独

用回溯法在java中求解数独,java,algorithm,artificial-intelligence,Java,Algorithm,Artificial Intelligence,我正在尝试使用java编写一个数独解算器。我使用了一个通用的回溯算法。但是程序工作不正常(返回null) for(i=0;i<9;i++) for(j=0;j<9;j++){ if(board[i][j]==0){ empty=true; break;

我正在尝试使用java编写一个数独解算器。我使用了一个通用的回溯算法。但是程序工作不正常(返回null)

    for(i=0;i<9;i++)                                                        
        for(j=0;j<9;j++){
            if(board[i][j]==0){
                empty=true;
                break;
            }
        }
    if(!empty)return board;
这是密码

public class Sudoku {

    int[][] board;                                                              //Sudoku board


    public Sudoku() {                                                           //constructor
        this.board = new int[9][9];             
        for(int i=0;i<9;i++)
            for(int j=0;j<9;j++)
                board[i][j]=0;
    }

    public Sudoku(int[][] board){                                               //constructor
        this.board=board;
    }


    public int[][] Solve(int[][] board){
        int i, j, k,l,val;                                                      //iterators 
        int empty=1;                                                            //empty flag
        int[][] temp=new int[9][9];                                             //temporary array for backtracking
        temp=board;
        for(i=0;i<9;i++)                                                        //check if any empty space available
            for(j=0;j<9;j++){
                if(board[i][j]==0){
                    empty=0;
                    break;
                }
            }
        if(empty==1)return board;
        for(i=0;i<9;i++)
            outerLoop:
            for(j=0;j<9;j++){
                if(board[i][j]>0)continue;
                for(val=1;val<10;val++){                                        //try values
                    for(k=0;k<9;k++){
                        if(board[i][k]==val)break;                              //check row consistancy 
                        if(board[k][j]==val)break;                              //check column consistancy     
                    }
                    for(k=(i/3)*3;k<(i/3+1)*3;k++)                              //check latin square consistancy
                        for(l=(j/3)*3;l<((j/3+1)*3);l++)
                            if(board[k][l]==val)break;                      
                    temp[i][j]=val;                                             //put consistant value
                    Solve(temp);                                                //recursive call for backtrack
                }
        }
        return null;                                                            
    }


    public static void main(String[] args) {
        // TODO code application logic here
        int[][] board={ {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}};
        Sudoku s=new Sudoku(board);
        int[][] temp=new int[9][9];
        temp=s.Solve(board);
        for(int i=0;i<9;i++){
            System.out.println("");
            for(int j=0;j<9;j++){
                System.out.print(temp[i][j]);
                System.out.print(",");
            }
        }
    }    
}
    for(i=0;i<9;i++)                                                        
        for(j=0;j<9;j++){
            if(board[i][j]==0){
                empty=true;
                break;
            }
        }
    if(!empty)return board;
公共级数独{
int[][]板;//数独板
公共数独(){//构造函数
this.board=新整数[9][9];

对于(int i=0;i我将重点介绍您的
Solve(int[]])
方法:

public int[][] Solve(int[][] board){
    for(i=0;i<9;i++)                                                        
        for(j=0;j<9;j++){
            if(board[i][j]==0){
                empty=true;
                break;
            }
        }
    if(!empty)return board;
在Java命名约定下,方法应该是camelCase:
solve(int[][]board)

    for(i=0;i<9;i++)                                                        
        for(j=0;j<9;j++){
            if(board[i][j]==0){
                empty=true;
                break;
            }
        }
    if(!empty)return board;
除非必要,否则不应该在方法的开头定义迭代器。这会给迭代器一种“错误的目的感”,使代码更难解释

    int empty=1;
    for(i=0;i<9;i++)                                                        
        for(j=0;j<9;j++){
            if(board[i][j]==0){
                empty=true;
                break;
            }
        }
    if(!empty)return board;
这应该是一个布尔值,因为它只保存1或0的值。布尔值在这里更易于阅读:
boolean empty=false;

    int[][] temp=new int[9][9];                                             
    temp=board;
    for(i=0;i<9;i++)                                                        
        for(j=0;j<9;j++){
            if(board[i][j]==0){
                empty=true;
                break;
            }
        }
    if(!empty)return board;
此外,我建议将代码分解为“段落”或相关操作。当您从定义转移到一些初始逻辑时,这将是一个新段落的好位置

    for(i=0;i<9;i++)                                                        
        for(j=0;j<9;j++){
            if(board[i][j]==0){
                empty=true;
                break;
            }
        }
    if(!empty)return board;

我将重点介绍您的
Solve(int[][])
方法:

public int[][] Solve(int[][] board){
    for(i=0;i<9;i++)                                                        
        for(j=0;j<9;j++){
            if(board[i][j]==0){
                empty=true;
                break;
            }
        }
    if(!empty)return board;
在Java命名约定下,方法应该是camelCase:
solve(int[][]board)

    for(i=0;i<9;i++)                                                        
        for(j=0;j<9;j++){
            if(board[i][j]==0){
                empty=true;
                break;
            }
        }
    if(!empty)return board;
除非必要,否则不应该在方法的开头定义迭代器。这会给迭代器一种“错误的目的感”,使代码更难解释

    int empty=1;
    for(i=0;i<9;i++)                                                        
        for(j=0;j<9;j++){
            if(board[i][j]==0){
                empty=true;
                break;
            }
        }
    if(!empty)return board;
这应该是一个布尔值,因为它只保存1或0的值。布尔值在这里更易于阅读:
boolean empty=false;

    int[][] temp=new int[9][9];                                             
    temp=board;
    for(i=0;i<9;i++)                                                        
        for(j=0;j<9;j++){
            if(board[i][j]==0){
                empty=true;
                break;
            }
        }
    if(!empty)return board;
此外,我建议将代码分解为“段落”或相关操作。当您从定义转移到一些初始逻辑时,这将是一个新段落的好位置

    for(i=0;i<9;i++)                                                        
        for(j=0;j<9;j++){
            if(board[i][j]==0){
                empty=true;
                break;
            }
        }
    if(!empty)return board;

您的解决方案(int[][]板)函数不是真正可读的。也许您应该首先尝试正确缩进它。您还应该记住,您的Solve函数返回电路板,最好保留递归调用。最终,您的函数返回null,因为递归求解电路板后没有其他返回指令。它需要在继续之前进行一点返工。您的解决方案(int[][]板)函数不是真正可读的。也许您应该首先尝试正确缩进它。您还应该记住,您的Solve函数返回电路板,最好保留递归调用。最终,您的函数返回null,因为递归求解电路板后没有其他返回指令。它需要在继续之前做一点修改。感谢您的详细回复。我对编程有点陌生,对java没有太多经验。如果我返回Solve(temp)代替我的是StackOverflowerError。这意味着要解决的步骤太多了。这里有一个特例叫做尾部调用递归,这意味着您只进行一次递归调用,它就在最后。幸运的是,有一个简单的解决溢出的方法。与其使用递归函数,不如包含while循环中中断的逻辑:
if(!empty)break;
基本上,每次在函数中进行函数调用时,计算机都必须跟踪您所在的位置。因此,当函数调用完成时,您将继续您停止的位置。这称为调用堆栈,它有一个限制。Java在许多方面都是一种很好的语言,但类似的数学算法非常适合f像F#这样的函数语言(自动将尾部调用递归转换为迭代)坚持使用Java学习,但如果你打算做大量数学编程,请记住这一点。感谢你的详细回答。我是编程新手,对Java没有太多经验。如果我返回Solve(temp)代替我的是StackOverflowerError。这意味着要解决的步骤太多了。这里有一个特例叫做尾部调用递归,这意味着您只进行一次递归调用,它就在最后。幸运的是,有一个简单的解决溢出的方法。与其使用递归函数,不如包含while循环中中断的逻辑:
if(!empty)break;
基本上,每次在函数中进行函数调用时,计算机都必须跟踪您所在的位置。因此,当函数调用完成时,您将继续您停止的位置。这称为调用堆栈,它有一个限制。Java在许多方面都是一种很好的语言,但类似的数学算法非常适合f像F#这样的函数式语言(它会自动将尾部调用递归转换为迭代)坚持使用Java进行学习,但如果您打算进行大量数学编程,请记住这一点。