一、问题简介
你一定听说过“数独”游戏。
如【图1.png】,玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个同色九宫内的数字均含1-9,不重复。
数独的答案都是唯一的,所以,多个解也称为无解。
本图的数字据说是芬兰数学家花了3个月的时间设计出来的较难的题目。但对会使用计算机编程的你来说,恐怕易如反掌了。
本题的要求就是输入数独题目,程序输出数独的唯一解。我们保证所有已知数据的格式都是合法的,并且题目有唯一的解。
格式要求,输入9行,每行9个字符,0代表未知,其它数字为已知。
输出9行,每行9个数字表示数独的解。
例如:
输入(即图中题目):
005300000
800000020
070010500
400005300
010070006
003200080
060500009
004000030
000009700
程序应该输出:
145327698
839654127
672918543
496185372
218473956
753296481
367542819
984761235
521839764
二、思路分析
题目中有四个筛选条件即
1、每行不能含有重复的数字
2、每列不能含有重复的数字
3、每个小的九宫格不能有重复的数字。
4、每个格子的值在1-9之间
为此先创建四个二维数组
1、s数组用于存储刚开始时从控制台出入的矩阵
2、rol[i][x]==1代表第i行已存在数字x,那么rol[i][x]==0代表第i行不存在数字x
3、col[j][x]==1代表第j行已存在数字x,那么col[j][x]==0代表第j行不存在数字x
4、small[j/3+i/3*3][x]=1代表第(j/3+i/3*3)个九宫格(从左到右,从上到下)已存在数字x,small[j/3+i/3*3][x]=0代表第(j/3+i/3*3)个九宫格(从左到右,从上到下)不已存在数字x
(PS:j/3+i/3*3是为了判断i行,j列是属于哪个九宫格,找几个位置代入就知道为何如此写。)
创建这些数组是为了在向s数组的某位置插入数字时,根据另外三个数组来判断是否可以在此位置插入该数字,
因此在对s数组进行初始化,即接受控制台上的矩阵时,就要对另外三个数组进行初始化,它们起标志作用。
从棋盘的左上角开始,判断此处是否可以插入数字,如果可以就插入一个数字,然后跳到下一列,如果到了最后一列,便跳到下一行,每到一个位置便插入一个数字,如果该数字不满足条件,便换一个数字,然后向下,若所有数字都试过了还不行,便回退到上一个位置,更换上一个位置的数字,然后再向下运行,如此反复,最终只有是满足条件的数字才能走到最后,也就是说走到最后的便是正确答案。
三、解决代码
public class Demo6 {
static int s[][] = new int[9][9];
static int rol[][] = new int[9][10];
static int col[][] = new int[9][10];
static int small[][] = new int[9][10];
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String[] line = new String[9];
for (int i = 0; i < 9; i++) {
line[i] = scanner.nextLine();
}
char[][] c = new char[9][9];
for (int i = 0; i < 9; i++) {
c[i] = line[i].toCharArray();
}
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
s[i][j] = Integer.parseInt(c[i][j] + "");
if (s[i][j] != 0) {//在接受控制台上的矩阵时,就对另外三个数组进行初始化
rol[i][s[i][j]] = 1;
col[j][s[i][j]] = 1;
small[j / 3 + i / 3 * 3][s[i][j]] = 1;
}
}
}
getResult(0, 0);//从0行0列开始
}
public static void getResult(int rolIndex, int colIndex) {
if (rolIndex == 9 && colIndex == 0) {//找到答案
// 输出答案
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
System.out.print(s[i][j]);
}
System.out.println();
}
}
if (rolIndex < 9) {//未找到答案
if (s[rolIndex][colIndex] != 0) {
if (colIndex == 8) {// 到最后一列,另起一行
getResult(rolIndex + 1, 0);
} else {// 到下一列
getResult(rolIndex, colIndex + 1);
}
} else {
for (int x = 1; x <= 9; x++) {
//筛选条件
if (col[colIndex][x] != 0 || rol[rolIndex][x] != 0
|| small[colIndex / 3 + rolIndex / 3 * 3][x] != 0) {
continue;//说明不能插入当前数x,结束本次循环
}
s[rolIndex][colIndex] = x;
rol[rolIndex][x] = 1;
col[colIndex][x] = 1;
small[colIndex / 3 + rolIndex / 3 * 3][x] = 1;
if (colIndex == 8) {
getResult(rolIndex + 1, 0);//进入下一行
} else {
getResult(rolIndex, colIndex + 1);//进入下一列
}
//----------------------------------------
//到这一步说明这个x不能满足需要,back
s[rolIndex][colIndex] = 0;
rol[rolIndex][x] = 0;
col[colIndex][x] = 0;//前面进行了赋值,这里撤回
small[colIndex / 3 + rolIndex / 3 * 3][x] = 0;
}
}
}
}
}
Rome is not built in a day.