import java.util.Scanner;
public class Shudu_sy {
// shanshan是存储上次
static int[] shanshan = new int[81];
static int[][] num_aa = new int[9][9];
static int[][] num_bb = new int[9][9];
static int[] num_all = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
public static void main(String[] args) {
scan_num(); // 输入数组
change_shan();// 初始化我们的统计数组shanshan
change(0, 0); // 这个0,0 (这里不是表情)是对应数组的第0行0列,这个功能主要是方便大家可以在这个代码的基础上修改
}
// 初始化该计数数组
public static void change_shan() {
for (int i = 0; i < shanshan.length; i++) {
shanshan[i] = 0;
}
}
// 这里面的shanshan数组是用来记录上次该为存储的是第几个数据,shanshan的下边对应该9*9数组中
// 的行x*9+列y,即x*9+y
// 采用递归调用,如果失败则返回上一步
public static void change(int x, int y) {
int yy = y; // 这里的yy是因为我采用递归调用,改变这个双层for循环的i和j的值
a: for (int i = 0; i < 9; i++) {
// 标签a也是为了返回上一步的跳转做准备的
for (int j = yy; j < 9; j++) {
if (j == 8) {
yy = 0;
}
// yy默认为0,跳转后指定位置后j每次开始的位置会发生改变,所以我选择把他手动置0(从0开始)
if (num_bb[i][j] == 0) {
// num_bb是备份数组,用来测试这个位置是否本来是空
int num = sy(i, j, i * 9 + j);
if (num != -1) {// 有正确数据的时候
num_aa[i][j] = num;// 我们在该位置填充该数据(num_aa中更新数据)
} else if (num == -1) {// 如果没有正确数据,我们执行返回上一步操作
String[] aa = sys(num_bb, i, j).split(",");
i = Integer.parseInt(aa[0]) - 1;// 对应i的位置,但是因为i++,所以我们提前先-1
yy = Integer.parseInt(aa[1]);// 直接对应j的位置,不需要-1
continue a;
}
}
}
}
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
System.out.print(num_aa[i][j] + ",");
}
System.out.println();
}
// 如果该数独已经计算完毕,我们把该数独输出出来,大家也可以把这个输出给美化一下
}
// 清空错误数据的缓存
// 当然这一步和这一步后num_aa中的数据和shanshan中的缓存必须要被清空
public static void clean(int x, int y) {
int num = x * 9 + y;
for (int i = num; i < 81; i++) {
shanshan[i] = 0;
}
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (i * 9 + j >= num) {
num_aa[i][j] = num_bb[i][j];
}
}
}
}
// 进行返回上一步操作,同时把这一步后面的shanshan里的数据清空。
public static String sys(int[][] aa, int x, int y) {
clean(x, y);
for (int i = 8; i >= 0; i--) {
for (int j = 8; j >= 0; j--) {
if (num_bb[i][j] != num_aa[i][j] && i * 9 + j < x * 9 + y) {
return i + "," + j;
}
}
}
return null;
// 再清空数据之后,我们获得上一个num_bb中为0的数据的位置,以i,j的形式返回
}
// 输出一个可能是正确的答案,如果不存在则输出-1,同时更新shanshan里面的数据
public static int sy(int x, int y, int a) {
if (shanshan[a] == 9) {
return -1;
}// 如果该位置的缓存为9,表明该位置没有正确数据
for (int i = shanshan[a]; i < 9; i++) {// 从上一次正确位置之后开始
if (testOne(num_all[i], x, y) == 0) { // 如果有一个正确的数据,即返回0的时候
shanshan[a] = num_all[i];// 我们先把缓存更新
return num_all[i];// 同时返回这个正确的数据
}
}
return -1; // 如果没有正确的数据我们就返回-1
}
// 这个sy函数是对该位置进行测试,看该位置是否存在一个正确的数据
// 传入要测试的数据,和该数据所在的行和列,看是否存在数据重复,无冲突输出0,有冲突输出-1
public static int testOne(int num, int x, int y) {
// 检测该行该列是否有重复数字出现
for (int i = 0; i < 9; i++) {
if (num_aa[x][i] == num || num_aa[i][y] == num) {
return -1;
}
}
// num_aa是我们用来修改的数据数组
// 检测3*3的正方块中是否有重复数字出现
for (int i = x / 3 * 3; i < x / 3 * 3 + 3; i++) {
for (int j = y / 3 * 3; j < y / 3 * 3 + 3; j++) {
if (i == x && j == y) {
break;
// 如果是该空格自身则不用比较
} else if (num_aa[i][j] == num) {
return -1;
// 如果该方格已存在该数据则返回-1
}
}
}
// 这里x/3*3,y/3*3后会自定确定该该数据所对应的3*3小方格的左上角那个数据,然后再对该数据i和j进行++操作
return 0;
// 如果该方格不存在这个数据则返回0
}
// 输入该9*9九宫格,用英文下的逗号隔开,如果为空则输入0
public static void scan_num() {
System.out.println("please input information");// 提示代码
Scanner scanner = new Scanner(System.in);
for (int i = 0; i < 9; i++) {
String a[] = scanner.nextLine().split(",");
for (int j = 0; j < a.length; j++) {
num_aa[i][j] = Integer.parseInt(a[j]);
num_bb[i][j] = Integer.parseInt(a[j]);
// 这里采用两个相同的数组,是因为等会要对第一个数组num_aa进行操作,操作的时候和数组num_bb进行对比,来区分
// 这个方格对应的数字是后来自己写的,还是原本系统就有的
}
}
// 直接两个for循环输入
scanner.close();
System.out.println("input end");
}
// 这是一段简单的输入程序
}
这个小程序采用的简单的模块处理机制,没事写着玩玩。