Java - 生成一个独特的数独

时间:2017-04-20 21:10:01

标签: java unique sudoku

我正在用Java制作数独游戏,我需要一些帮助。

我有两个用于生成数独谜题的课程: SudokuSolver SudokuGenerator

SudokuSolver 为空表创建一个完整的有效数独谜题, SudokuGenerator 从表中删除一个随机值,然后检查(使用 SudokuSolver )如果数独谜题是唯一

我发现数独谜题不是唯一的,所以我认为我检查数独谜题的算法是不好的。

例如:我有这个数独谜题

497816532
132000000
000000000
910600080
086009000
000084963
021063059
743050020
600278304

这个解决方案:

497816532
132**745**698
568392471
914**637**285
386529147
275184963
821463759
743951826
659278314

我去了https://www.sudoku-solutions.com/,我添加了我的数独模式,他们给了我另一个解决方案:

497816532
132**547**698
568392471
914**635**287
386729145
275184963
821463759
743951826
659278314

有趣的想法是他们说这个谜题是有效的并且有一个独特的解决方案。

有些意见?谢谢

SudokuSolver

public class SudokuSolver {

    public static final int GRID_SIZE = 9;
    public static final int SUBGRID_SIZE = 3;
    private static int validRow = 0;
    private static int validCol = 0;

    private int[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9};

    public boolean solveSudoku(int[][] values, int forbiddenNum) {

        if(!findUnassignedLocation(values)) return true;

        //suffle the nums array - for having a different valid sudoku
        shuffleNums();

        for (int i = 0; i < GRID_SIZE; i++) {

            int num = nums[i];

            if(num == forbiddenNum) continue; //

            if(isSafe(values,validRow, validCol, num)) {
                values[validRow][validCol] = num;

                if(solveSudoku(values, forbiddenNum)) return true;

                if(validCol == 0) {
                    validRow--;
                    validCol = 8;
                }else{
                    validCol--;
                }

                values[validRow][validCol] = 0;
            }

        }


        return false;

    }

    public boolean createValidSudoku(int[][] values) {

        if(!findUnassignedLocation(values)) return true;

        shuffleNums();

        for (int i = 0; i < GRID_SIZE; i++) {

            int num = nums[i];

            if(isSafe(values,validRow, validCol, num)) {
                values[validRow][validCol] = num;

                if(createValidSudoku(values)) return true;

                if(validCol == 0) {
                    validRow--;
                    validCol = 8;
                }else{
                    validCol--;
                }

                values[validRow][validCol] = 0;
            }

        }


        return false;
    }

    private void shuffleNums() {

        Random random = new Random();
        for(int i = nums.length - 1; i > 0; i--) {
            int index = random.nextInt(i + 1);

            int a = nums[index];
            nums[index] = nums[i];
            nums[i] = a;
        } 

}

    private boolean findUnassignedLocation(int[][] values) {
        for(int row = 0; row < GRID_SIZE; row++) {
            for(int col = 0; col < GRID_SIZE; col++) {
                if (values[row][col] == 0) {
                    validRow = row;
                    validCol = col;
                    return true;
                }
            }
        }

        return false;
    }

    private boolean usedInRow(int[][] values, int row, int num) {
        for (int col = 0; col < GRID_SIZE; col++) {
            if(values[row][col] == num) return true;
        }

        return false;
    }

    private boolean usedInCol(int[][] values, int col, int num) {
        for (int row = 0; row < GRID_SIZE; row++) {
            if(values[row][col] == num) return true;
        }

        return false;
    }

    private boolean usedInBox(int[][] values, int boxStartRow, int boxStartCol, int num) {
        for(int row = 0; row < SUBGRID_SIZE; row++) {
            for (int col = 0; col < SUBGRID_SIZE; col++) {
                if (values[row + boxStartRow][col + boxStartCol] == num) return true;
            }
        }

        return false;
    }

    private boolean isSafe(int[][] values,int row, int col, int num) {
        return !usedInRow(values, row, num) &&
               !usedInCol(values, col, num) &&
               !usedInBox(values, row - row % 3, col - col % 3, num);
    }

    public void printGrid(int[][] values) {
        for (int row = 0; row < GRID_SIZE; row++) {
            for (int col = 0; col < GRID_SIZE; col++) {
                System.out.print(values[row][col]);
            }
            System.out.println();
        }
    }
}

SudokuGenerator

public class SudokuGenerator {

    private int[][] generatorValues = new int[9][9];


    public void generateSudoku() {
        SudokuSolver sudokuSolver = new SudokuSolver();
        //generate a random valid sudoku for an empty table
        sudokuSolver.createValidSudoku(generatorValues);

        int count = 0;
        printNums(generatorValues);

        while(count < 40){
            Random random = new Random();

            int row = 0;
            int col = 0;

            if(count < 15){
                row = random.nextInt(3);
                col = random.nextInt(9);    
            } else if (count >= 15 && count < 30) {
                row = random.nextInt(3) + 3;
                col = random.nextInt(9);    
            }else {
                row = random.nextInt(3) + 6;
                col = random.nextInt(9);    
            }


            int num = generatorValues[row][col];
            int tempValues[][] = Arrays.copyOf(generatorValues, generatorValues.length);

            //System.out.println("Row:" + row + "Col: " + col + "Num: " + num);

            //Set the cell to 0;
            if(generatorValues[row][col] != 0){
                generatorValues[row][col] = 0;
            } else{
                continue;
            }

            //If found a solution, set cell back to original num
            if(sudokuSolver.solveSudoku(tempValues, num)) {
                generatorValues[row][col] = num;
                continue;
            }

            count++;

        }   
        System.out.println("------------------");
        printNums(generatorValues);


    }

    private void printNums(int[][] values) {
        for (int row = 0; row < 9; row++) {
            for(int col = 0; col < 9; col++) {
                System.out.print(values[row][col]);
            }
            System.out.println();
        }
    }

    public int[][] getGeneratorValues () {
        return generatorValues;
    }
}

0 个答案:

没有答案