【小DEMO】回溯法破解數獨

import java.util.*;

public class Sudoku {
    // 方案數量
    public static int caseCount;
    // sudoku 二位數組
    public static int[][] chessboard=new int[9][9];
    // 初始化二位數組
    public static void init(){
        chessboard = new int[][]{
                {7,0,0,0,0,4,0,2,0},
                {0,9,0,0,0,0,3,0,0},
                {0,0,0,0,0,6,0,0,8},

                {0,8,0,9,0,0,0,0,0},
                {0,3,5,0,0,0,0,0,9},
                {0,0,0,0,7,2,0,4,0},

                {0,0,9,5,2,0,0,0,0},
                {0,0,0,0,0,0,8,6,7},
                {1,0,0,3,0,0,0,0,0}
        };
        // 靜態Int型數據默認是0,這裏初始化方便邏輯書寫
        caseCount = 0;
    }
    // 查找可用集合
    public static Set<Integer> canUse(int row, int col){
        Set<Integer> set = new HashSet<>(Arrays.asList(1,2,3,4,5,6,7,8,9));
        // 排除行上數據
        for (int index = 0;index <=8; index++){
            set.remove(chessboard[row][index]);
        }
        // 排除列上數據
        for (int index = 0;index <=8; index++){
            set.remove(chessboard[index][col]);
        }
        // 排除方格內的數據
        int xxx = row/3;
        int yyy = col/3;
        for (int y = yyy*3; y<(yyy+1)*3; y++){
            for (int x = xxx*3; x<(xxx+1)*3; x++){
                set.remove(chessboard[x][y]);
            }
        }
        return set;
    }

    // 查找下一個
    public static int[] next(int row, int col){
        // 某行還沒走到盡頭
        if (col<8){
            return new int[]{row,++col};
        }
        // 如果某行走到盡頭
        if (col == 8 && row<8){
            return new int[]{++row,0};
        }
        // 如果行和列都走到盡頭,返回null
        return null;
    }

    // 打印結果
    public static void printResult(){
        for (int row = 0; row<=8; row++){
            for (int col = 0; col<=8; col++){
                System.out.print(chessboard[row][col] + " ");
                if ((col+1)%3==0){
                    System.out.print("  ");
                }
            }
            System.out.println();
            if ((row+1)%3==0){
                System.out.println();
            }
        }
    }

    // 添加數字
    public static void fillNumber(int row, int col){
        // 當前值爲空位的時候
        if (chessboard[row][col] == 0){
            // 先查找所有可能
            Set<Integer> canUseSet = canUse(row,col);
            List<Integer> list = new ArrayList<>(canUseSet);
            for (Integer integer:list){
                    chessboard[row][col] = integer;
                    // 查找下一個
                    int[] nextPosition = next(row, col);
                    if (Objects.isNull(nextPosition) || nextPosition.length == 0){
                        //可以輸出一個結果
                        System.out.println("結果"+(++caseCount)+":");
                        printResult();
                    }else {
                        //查找下一個
                        int newRow = nextPosition[0];
                        int newCol = nextPosition[1];
                        fillNumber(newRow,newCol);
                    }
                    chessboard[row][col] = 0;
            }
        }else {
            int[] nextPosition = next(row, col);
            if (Objects.isNull(nextPosition) || nextPosition.length == 0){
                //可以輸出一個結果
                System.out.println("結果"+(++caseCount)+":");
                printResult();
            }else {
                //查找下一個
                int newRow = nextPosition[0];
                int newCol = nextPosition[1];
                fillNumber(newRow,newCol);
            }
        }
    }

    public static void main(String[] args) {
        // 初始化
        init();
        System.out.println("原始數據:");
        printResult();
        System.out.println("結果集:");
        fillNumber(0,0);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章