刚开始学习的时候,总是不知道对数组进行回溯的时候,怎么保证找到的是下一个空值, 所以写好一半的代码就放在一边,一个星期之后回过头再看回溯法解数独的时候,突然醒悟过来:
原来在构造数组的时候,以0值代替空值,当从1-9的某一个数填入该处的时候,该处就不是0值,回溯重新调用方法的时候,找到的0值就是下一处的0值了.
注意点:
(1).sudoku方法的返回值是布尔值,这样子"&&"两边才都是布尔值
(2)九宫格的获得iGrid和jGrid都是用i,j对3整除再乘以3(以前错误认识:九宫格是以i,j为中心的九宫)
(3)数独的表示,空值用0表示
今天还有其它事,把待解决的记录下来,以便以后参考:
待解决问题:
(1)输出多个相同的数独解
代码如下:
public class Sudodu {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[][] chess = {
{0,4,2,0,6,3,0,0,9},
{6,0,0,0,1,0,0,0,5},
{3,0,0,0,2,0,4,8,0},
{1,0,0,5,0,2,6,0,8},
{4,0,0,0,0,7,0,0,1},
{9,0,5,6,0,0,0,0,7},
{0,3,6,0,5,0,0,0,2},
{2,0,0,0,7,0,0,0,4},
{7,0,0,2,9,0,8,5,0}
} ;
sudoku(chess);
}
static boolean sudoku(int[][] chess) {
// TODO Auto-generated method stub
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
//过滤掉不为0的情况
if(chess[i][j] != 0)
continue;
for(int d=1;d<=9;d++)
{
chess[i][j]=d;
if(isValid(chess,i,j) && sudoku(chess) )
{
shuchushudu(chess);
return true;
}
chess[i][j]=0;
}
return false;
}
}
return true;
}
private static void shuchushudu(int[][] chess) {
// TODO Auto-generated method stub
for(int i=0;i<9;i++){
for(int j=0;j<9;j++)
{
System.out.print(chess[i][j]+" ");
}
System.out.println(" ");
}
System.out.println("--------------");
}
private static boolean isValid(int[][] chess, int i, int j) {
// TODO Auto-generated method stub
boolean flag=true;
int data=chess[i][j];
for(int k=0;k<9;k++)
{
//i行相等
if( (k!=j) && (chess[i][k]==data))
{
return false;
}
//j列相等
if( (k!=i) && (chess[k][j]==data))
{
return false;
}
}
//九宫相等
int iGrid=(i/3)*3;
int jGrid=(j/3)*3;
for(int k2=iGrid;k2<iGrid+3;k2++)
{
for(int k3=jGrid;k3<jGrid+3;k3++)
{
if((i==k2) && (j==k3))
{
continue;
}
if(chess[k2][k3]==data)
{
return false;
}
}
}
return true;
}
}
结果输出:
5 4 2 8 6 3 7 1 9
6 8 7 4 1 9 2 3 5
3 9 1 7 2 5 4 8 6
1 7 3 5 4 2 6 9 8
4 6 8 9 3 7 5 2 1
9 2 5 6 8 1 3 4 7
8 3 6 1 5 4 9 7 2
2 5 9 3 7 8 1 6 4
7 1 4 2 9 6 8 5 3