【发布时间】:2016-06-26 13:07:23
【问题描述】:
我一直在尝试实现回溯算法来解决 Java 控制台应用程序中的数独问题。我以前从未实现过该算法,可能只看几个 youtube 视频还不够,因为它似乎没有按我认为的那样工作。
我已经用我在网上找到的一个实际的数独手动填充了棋盘。但是,它不会越过第一个方格。最初我尝试将整个内容嵌套在一个双 for 循环中,但这似乎也不起作用。
我已经正确测试了有效移动方法,所以问题显然不存在。 感谢任何帮助。
public class Sudoku {
public static int[][] createBoard(int n)
{
int[][] board = new int[n][n];
for (int i=0; i<board.length; i++)
for (int j=0; j<board[i].length; j++)
board[i][j]=0;
return board;
}
public static void printBoard(int[][] b)
{
int buffer=(int)Math.sqrt(b.length);
String btm=new String(new char[buffer*buffer*3+buffer+1]).replace("\0", "_"); // fitting for all board size
for (int i=0; i<b.length; i++)
{
if (i%buffer==0)
System.out.println(btm);
for (int j=0; j<b[i].length; j++)
{
if (j%buffer==0)
System.out.print("|");
if (b[i][j]==0)
System.out.print(" _ ");
else
System.out.print(" " + b[i][j] + " ");
}
System.out.println("|");
}
System.out.println(btm);
}
// returns true if a number can be inserted in a row.
public static boolean checkLegalRow(int[][] b, int row, int num)
{
for (int i=0; i<b.length; i++)
{
if (b[row][i]==num)
return false;
}
return true;
}
// returns true if a number can be inserted in a column.
public static boolean checkLegalCol(int[][] b, int col, int num)
{
for (int i=0; i<b.length; i++)
{
if (b[i][col]==num)
return false;
}
return true;
}
//returns true if number can be inserted in its NxN box
public static boolean checkLegalBox(int[][] b, int row, int col, int num)
{
int buffer=(int)Math.sqrt(b.length);
for (int i=0, adjRow=row-(row%buffer); i<buffer; i++, adjRow++)
{
for (int j=0, adjCol=col-(col%buffer); j<buffer; j++, adjCol++)
{
if (b[adjRow][adjCol]==num)
return false;
}
}
return true;
}
public static boolean legalMove(int[][] b, int row, int col, int num)
{
return checkLegalRow(b,row,num) && checkLegalCol(b,col,num) && checkLegalBox(b,row,col,num) && b[row][col]==0;
}
public static void solveBacktrack(int[][] b, int row, int col)
{
for (int k=1; k<=b.length; k++)
{
if (legalMove(b,row,col,k))
{
b[row][col]=k;
if (row==b.length-1 && col==b.length-1)
printBoard(b);
else
{
//printBoard(b);
if (col==b.length-1)
solveBacktrack(b,row+1,0);
else
solveBacktrack(b,row,col+1);
}
}
}
}
public static void main(String[] args)
{
int[][] board=createBoard(9);
board[0][1]=4; board[1][0]=6; board[2][1]=8; board[2][2]=9; board[0][3]=6; board[2][5]=3; board[1][7]=3;
board[1][8]=1; board[3][3]=4;
board[3][0]=2; board[3][2]=1; board[3][4]=5; board[3][7]=7; board[3][8]=8; board[4][1]=5;
board[4][3]=3; board[4][5]=7; board[5][0]=3; board[5][1]=6; board[5][4]=2; board[5][5]=8; board[5][8]=5;
board[6][3]=1; board[6][6]=6; board[6][7]=4; board[7][0]=4; board[7][1]=3; board[7][8]=9; board[8][2]=6;
board[8][5]=9;
printBoard(board);
solveBacktrack(board,0,0);
}
}
【问题讨论】:
-
告诉我你的逻辑。我认为您只是通过迭代并检查该数字是否已经存在来检查一个盒子的数字的有效性,这是错误的。这样想。最初在第一行、第一列和第一块中没有数字 9。所以你的逻辑说这个块应该有数字 9。但可能会有第一行、第二列和第一个块没有 9 的情况。
-
这是一个复杂的算法,需要大量的计算
-
@Shubham Jain 我不确定我是否在关注你。我正在检查这个数字是否可以出现,如果可以,我去下一个广场检查它。如果在某个阶段没有可能的选项,它将回溯并在原始循环中尝试另一个数字。至少这是我对这个概念的理解,基于少数 youtube 视频。
-
在 legalMove 中你需要测试方块是否为 0,否则你将覆盖已经填充的方块。