package Demo01;
import java.util.Random;
public class ShuDu2 {
/** 存储数字的数组 */
private static int[][] outcome = new int[9][9];// 公共数据
public static void main(String[] args) throws InterruptedException {
int success = getShuDuArray(1, getArr(), 0);
if (success == 1) {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
System.out.print(outcome[i][j] + " ");
}
System.out.println();
// System.out.println("第"+i+"行运行正常");
// Thread.sleep(1000);
}
System.out.println("81个数字符合数独要求,本次运行正常");
}
}
/**
*
* @param count:当前棋盘位置数,总共81个格子,从左往右,从上往下数
* @param nums:每次给定一个随机生成数的数组。
* @param time:每个空格更新数的次数。
* @return:当前格子是否成功
*/
public static int getShuDuArray(int count, int nums[], int time) {
// 通过count计算出row and col
int row = getRow(count);
int col = getCol(count);
if (count == 82) {
return 1;// 表示成功啦!!!
}
while (true)// 等于9表示第10次取数。
{
outcome[row][col] = generateNum(time, nums);// 开始填充该空格数字
// 如何所有数用完了,向下递归,接力赛
if (outcome[row][col] == 0) {
break;
}
if (isCorret(row, col)) {// 此时填充成功。向下递归。
int k = getShuDuArray(count + 1, getArr(), 0);
if (k == -1) {// 表示下层挂了,下层回溯,本层换数。
time++;
} else {// 肯定会返回1的,表示成功完成任务了。81层全部各司其职,尽责尽职。
return 1;// 成功
}
} else {// 本层与前面的数字矛盾
time++;
}
}
return -1;// 本层所有数要完了。卡住,向上层汇报
}
public static int[] getArr() {
int[] arr = new int[9];
for (int i = 0; i < arr.length; i++) {
arr[i] = i + 1;
}
return arr;
}
public static int getRow(int count) {
int row;
if (count % 9 == 0) {
row = (count / 9) - 1;
} else {
row = (count / 9);
}
return row;
}
public static int getCol(int count) {
int col;
if (count % 9 == 0) {
col = (count - 1) % 9;
} else {
col = count % 9 - 1;
}
return col;
}
private static Random r = new Random();
private static int generateNum(int time, int[] arr) {
// 第10次填充,表明该位置已经卡住,则返回0,由主程序处理退回
if (time == 9) {
return 0;
}
// 不是第一次填充
// 生成随机数字,该数字是数组的下标,取数组num中该下标对应的数字为随机数字
// int ranNum = (int) (Math.random() * (9 - time));//j2se
int ranNum = r.nextInt(9 - time);// j2me
// 把数字放置在数组倒数第time个位置,
int temp = arr[8 - time];
arr[8 - time] = arr[ranNum];
arr[ranNum] = temp;
// 返回数字
return arr[8 - time];
}
private static boolean checkNine(int row, int col) {
// 获得左上角的坐标
int j = row / 3 * 3;
int k = col / 3 * 3;
int l = j;// 遍历行
int m = k;// 遍历列
// 遍历所有目标数outcome[row][col]之前的所有数是否和该目标数重复
while (l != row || m != col) {// 进行遍历
if (outcome[l][m] == outcome[row][col]) {
return false;
} else {
m++;// 向前进
if ((m / 3 * 3) > k) {// 超出范围
m = k;
l++;
}
}
}
return true;
}
/**
* 检查列是否符合要求
*
* @param col
* 检查的列号
* @return true代表符合要求
*/
private static boolean checkLine(int col) {
for (int j = 0; j < 8; j++) {
if (outcome[j][col] == 0) {
continue;
}
for (int k = j + 1; k < 9; k++) {
if (outcome[j][col] == outcome[k][col]) {
return false;
}
}
}
return true;
}
/**
* 检查行是否符合要求
*
* @param row
* 检查的行号
* @return true代表符合要求
*/
private static boolean checkRow(int row) {
for (int j = 0; j < 8; j++) {
if (outcome[row][j] == 0) {
continue;
}
for (int k = j + 1; k < 9; k++) {
if (outcome[row][j] == outcome[row][k]) {
return false;
}
}
}
return true;
}
/**
* 是否满足行、列和3X3区域不重复的要求
*
* @param row
* 行号
* @param col
* 列号
* @return true代表符合要求
*/
private static boolean isCorret(int row, int col) {
return (checkRow(row) & checkLine(col) & checkNine(row, col));
}
}