使用Java的回溯算法解决数独

我正在尝试使用Java编写一个数独解题程序。我使用了一个常见的回溯算法,但程序运行不正常(返回null值)

这是代码

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(",");            }        }    }    }

我根据NetBeans的建议添加了返回null的语句,但它应该永远不会返回null。我找不到错误。提前感谢您的帮助。


回答:

我将专注于你的Solve(int[][])方法:

public int[][] Solve(int[][] board){

根据Java命名 conventions,方法名应该使用驼峰命名法:solve(int[][] board)

    int i, j, k,l,val;

除非必要,你不应该在方法开始时定义迭代器。这会给它们一种“虚假的目的感”,使代码更难理解。

    int empty=1;

这应该是一个布尔值,因为它只会持有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++)        outerLoop:        for(j=0;j<9;j++){            if(board[i][j]>0)continue;            for(val=1;val<10;val++){                                                        for(k=0;k<9;k++){                    if(board[i][k]==val)break;                                                   if(board[k][j]==val)break;                                                  }                for(k=(i/3)*3;k<(i/3+1)*3;k++)                                                  for(l=(j/3)*3;l<((j/3+1)*3);l++)                        if(board[k][l]==val)break;                                      temp[i][j]=val;                                                             Solve(temp);                                                            }    }    return null;                                                            }

你的代码有两个返回语句,一个用于完成的棋盘,另一个用于捕获逻辑错误。错误在于你的递归调用。仅仅调用Solve(temp);不会保留你对数据所做的任何更改。递归函数只有在使用递归调用生成的新信息时才有效。因此,为了修复你的错误,返回你的递归调用:

return Solve(temp);

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注