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");
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章