用窮舉法來求解數獨問題。大概思路就是:
1、先挑出以及存在的數字,不作處理。
2、未知數從上到下,從左到右開始枚舉,假如第一個數字是[0][0],先假設是1,判斷它所在行是否有重複,再判斷它所在的列是否有重複,最後判斷它所在的9宮格是否有重複。要是都沒有重複,就到下一個未知數。如果有重複,就自增。
3、要是自增到10,說明之前的數字有誤,就回溯到上一個未知數。
4、要是一行的第一個數字自增到10,就回溯到上一行的最後一個數字。
ps.這種做法感覺好弱智,一些高大上的算法又看不懂。。。
package com.zttech.demo.sudoku;
import static org.hamcrest.CoreMatchers.instanceOf;
import java.io.File;
import java.io.IOException;
import org.junit.Test;
import com.zttech.demo.excel.ExcelOperate;
/**
* 數據求解
* @author guoqicheng
* @date 2018年4月20日
*/
public class Sudoku {
@Test
public void test() throws IOException {
String filePath = "E:\\項目相關\\demo\\sudoku.xlsx";
boolean isExcel2003 = true;
if (ExcelOperate.isExcel2007(filePath)) {
isExcel2003 = false;
}
File file = new File(filePath);
String[][] result = ExcelOperate.getData(file, 0, isExcel2003);
int rowLength = result.length;
for (int i = 0; i < rowLength; i++) {
for (int j = 0; j < result[i].length; j++) {
System.out.print(result[i][j] + "|");
}
System.out.println("\t\t");
}
/** 把從excel讀取出來的二維數組轉換成int形式的二維數據,未知數用0來表示 */
int[][] arrays = new int[9][9];
for (int i = 0; i < 9; i ++) {
for (int j = 0; j < 9; j++) {
if (result[i][j] == null || "".equals(result[i][j])) {
arrays[i][j] = 0;
} else {
arrays[i][j] = Integer.parseInt(result[i][j]);
}
}
}
System.out.println("-----------------------------------------------");
arrays = calculate(arrays);
for (int i = 0; i < arrays.length; i++) {
for (int j = 0; j < arrays[i].length; j++) {
System.out.print(arrays[i][j] + "|");
}
System.out.println("\t\t");
}
System.out.println("success");
}
/**
* 求解過程
* @param arrays
* @return
*/
public static int[][] calculate(int[][] arrays) {
int count = 0; //步數
//獲取已經存在的數字位置
int[][] indexs = getIndex(arrays);
for (int i = 0; i < 9; i ++) {
for (int j = 0; j < 9; j ++) { //遍歷整個數組
if (indexs[i][j] != -1) { //如果是未知數
//判斷
do {
arrays[i][j] ++;
count++;
} while (!(compareRow(arrays, i, j) && compareCol(arrays, i, j) && compareLattice(arrays, i, j)));
if (arrays[i][j] > 9) {
if (indexs[i][j] != -1) {
arrays[i][j] = 0;
while (j != 0 && indexs[i][j-1] == -1) {
j = j - 1;
}
}
j = j - 2; //回退一步
}
} else {
continue;
}
if (j < -1) {
i = i - 1;
j = 8;
while (indexs[i][j] == -1) {
j = j - 1;
}
j --;
}
}
}
System.out.println(count);
return arrays;
}
/**
* 比較是否和這一行的數字重複
* @param arrays 數組
* @param row 所在的行
* @param col 所在的列
* @return false有重複,true沒重複
*/
public static boolean compareRow(int[][] arrays, int row, int col) {
for (int i = col + 1; i < 9; i ++) {
if (arrays[row][col] == arrays[row][i]) {
return false;
}
}
for (int i = col - 1; i >= 0; i --) {
if (arrays[row][col] == arrays[row][i]) {
return false;
}
}
return true;
}
/**
* 比較是否和這一列的數字重複
* @param arrays 數組
* @param row 所在的行
* @param col 所在的列
* @return false有重複,true沒重複
*/
public static boolean compareCol(int[][] arrays, int row, int col) {
for (int i = row + 1; i < 9; i ++) {
if (arrays[row][col] == arrays[i][col]) {
return false;
}
}
for (int i = row - 1; i >= 0; i --) {
if (arrays[row][col] == arrays[i][col]) {
return false;
}
}
return true;
}
/**
* 比較是否和九宮格里面的數字重複
* @param arrays 數組
* @param row 所在的行
* @param col 所在的列
* @return false有重複,true沒重複
*/
public static boolean compareLattice(int[][] arrays, int row, int col) {
int temp = 0;
for (int k = 0; k <= 8; k += 3) {
for (int l = 0; l <= 8; l += 3) {
if (row >= k && row <= k + 2 && col >= l && col <= l + 2) {
for (int i = k; i <= k + 2; i ++) {
for (int j = l; j <= l + 2; j ++) {
if (arrays[row][col] == arrays[i][j]) {
temp ++; //只能有一次重複(和自己)
}
}
}
}
}
}
if (temp == 1) {
return true;
}else {
return false;
}
}
/**
* 獲取以及存在數字的位置
* @param arrays
* @return 如果哪位位置上的值是-1,就代表他是原才存在的
*/
public static int[][] getIndex(int[][] arrays) {
int[][] temp = new int[9][9];
for (int i = 0; i < 9; i ++) {
for (int j = 0; j < 9; j ++) {
if (arrays[i][j] != 0) {
temp[i][j] = -1;
}
}
}
return temp;
}
}