Java程序解數獨

https://github.com/sophie2805/SolveSoduku

喜歡解數獨,不過老爺們解數獨似乎更勝一籌,iPad上的最高分一直都是他的。於是,寫了一段解數獨的代碼,不到一秒就解出來了,然後把答案照搬到iPad上,拼的是手速啊。終於揚眉吐氣了!

基本思路就是把當前空白單元格的所有可能解羅列出來(基於橫,豎,小九宮格羅列可能解,也就是getCandidates(…)方法),填入第一個可能解,往下走,羅列下一個單元格可能解,一直到某個單元格,它沒有合法的解了,回溯至上個單元格,嘗試它的第二個解(也就是遞歸方法sodukuSolver(…))。對,就是暴力嘗試。用程序來做這種簡單重複性的事情,可高效了!!

輸入棋盤的時候,爲了方便,將棋盤設置爲int數組,輸入9個數字就代表了棋盤,空白就用0表示,前面的0(也就是棋盤左邊開頭的0)可以省略。

一個字,爽。兩個字,爽快。

    int[] soduku = {
            5004,
            90200,
            900300005,
            4700001,
            307629000,
            0,
            702053060,
            6000000,
            40030
    };
package com.sophiesuyutian;

import java.util.*;

public class SodukuEnder {

    private int[][] sodukuGrid = new int[9][9];
    private List<Index> footPrint = new ArrayList<>();

    private List<List<Index>> sodukuCube = new ArrayList<>();

    private SodukuEnder(int[] soduku) {
        for(int i = 0; i < 9; i ++){
            for(int j = 8; j >= 0; j --){
                this.sodukuGrid[i][j] = soduku[i]%10;
                soduku[i] /= 10;
            }
        }
        for (int i = 0; i < 9;) {
            for (int j = 0; j < 9;) {
                List<Index> cube = new ArrayList<>();
                for (int m = i; m < i + 3; m++) {
                    for (int n = j; n < j + 3; n++)
                        cube.add(new Index(m, n));
                }
                sodukuCube.add(cube);
                j += 3;
            }
            i += 3;
        }
        for (int row = 0; row < 9; row++)
            for (int col = 0; col < 9; col++)
                if (sodukuGrid[row][col] == 0)
                    footPrint.add(new Index(row, col));
    }

    private List<Integer> getCandidates(int row, int col) {
        Set<Integer> occupiedCells = new HashSet<>();
        for (int i = 0; i < 9; i++) {
            occupiedCells.add(sodukuGrid[row][i]);
            occupiedCells.add(sodukuGrid[i][col]);
        }
        int cubeIndex = 0;
        boolean found = false;
        for (; cubeIndex < 9;) {
            for (Index index : sodukuCube.get(cubeIndex)) {
                if (index.toString().equals(row + "," + col)) {
                    found = true;
                    break;
                }
            }
            if (found)
                break;
            cubeIndex++;
        }
        for (Index index : sodukuCube.get(cubeIndex))
            occupiedCells.add(sodukuGrid[index.getRow()][index.getCol()]);
        List<Integer> sodukuNumbers = new ArrayList<>();
        for(int i = 1; i <= 9; i ++){
            sodukuNumbers.add(i);
        }
        HashSet<Integer> candidates = new HashSet<>(sodukuNumbers);
        candidates.removeAll(occupiedCells);
        return new ArrayList<>(candidates);
    }

    private boolean sodukuSolver(int pointer) {
        if (pointer >= footPrint.size())
            return true;
        List<Integer> tryOut = getCandidates(footPrint.get(pointer).row, footPrint.get(pointer).col);
        if (tryOut.isEmpty()) { // no candidates, return false
            return false;
        }
        boolean flag;
        for (int tryNum : tryOut) {
            sodukuGrid[footPrint.get(pointer).row][footPrint.get(pointer).col] = tryNum;
            flag = sodukuSolver(pointer + 1);
            if(!flag){ // current candidate try out failed, erease it, try next candidate
                sodukuGrid[footPrint.get(pointer).row][footPrint.get(pointer).col] = 0;
            }
            else
                return true;
        }
        return false;
    }

    private void printSodukuGrid() {
        for (int row = 0; row < 9; row++) {
            for (int col = 0; col < 9; col++) {
                System.out.print(sodukuGrid[row][col]==0 ? " " : sodukuGrid[row][col]);
            }
            System.out.print(System.lineSeparator());
        }
        System.out.println("-------------");
    }

    class Index {
        private int row, col;

        private int getRow() {
            return row;
        }

        private int getCol() {
            return col;
        }

        private Index(int row, int col) {
            this.row = row;
            this.col = col;
        }

        public String toString() {
            return (row + "," + col);
        }
    }

    @SuppressWarnings("unused")
    public static void main(String[] args) {

        int[] soduku = {
                5004,
                90200,
                900300005,
                4700001,
                307629000,
                0,
                702053060,
                6000000,
                40030
        };

        long startTime = System.currentTimeMillis();
        SodukuEnder sodukuEnder = new SodukuEnder(soduku);
        sodukuEnder.sodukuSolver(0);
        sodukuEnder.printSodukuGrid();
        long endTime = System.currentTimeMillis();
        System.out.println("Total time cost: " + (endTime - startTime) + " ms");
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章