數獨求解的java實現

用窮舉法來求解數獨問題。大概思路就是:
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;
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章