欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

用 Java 实现数独游戏

最编程 2024-06-01 19:25:13
...

数独游戏:

窗体+逻辑实现类

public class SudokuGame extends JFrame {
    private final JTextField[][] cells;
    private int[][] solution;
    private int[][] puzzle;

    public SudokuGame() {
        setTitle("Sudoku Game");
        setSize(800, 800);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        JPanel sudokuPanel = new JPanel(new GridLayout(9, 9));
        cells = new JTextField[9][9];
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                cells[i][j] = new JTextField(1);
                cells[i][j].setFont(new Font("serilf", Font.BOLD, 40));
                cells[i][j].setHorizontalAlignment(JTextField.CENTER);
                int ii = i;
                int jj = j;
                cells[i][j].addKeyListener(new KeyListener() {
                    @Override
                    public void keyTyped(KeyEvent e) {
                        if (e.getKeyChar() - 48 != solution[ii][jj]) {
                            cells[ii][jj].setBackground(Color.red);
                        } else {
                            printCells(ii, jj);
                        }
                    }

                    @Override
                    public void keyPressed(KeyEvent e) {
                        int len = cells[ii][jj].getText().length();
                        if (len > 0) {
                            cells[ii][jj].setText("");
                        }
                    }

                    @Override
                    public void keyReleased(KeyEvent e) {
                        boolean flag = false;
                        for (int i = 0; i < 9; i++) {
                            for (int j = 0; j < 9; j++) {
                                if (!Integer.toString(solution[i][j]).equals(cells[i][j].getText())) {
                                    flag = true;
                                    break;
                                }
                            }
                            if (flag) break;
                        }
                        if (!flag) {
                            JLabel message = new JLabel("恭喜你挑战成功!!!");
                            ImageIcon icon = new ImageIcon();

                            JOptionPane.showMessageDialog(sudokuPanel, message, "挑战成功", 3, icon);
                        }
                    }
                });
                printCells(i, j);
                sudokuPanel.add(cells[i][j]);
            }
        }

        add(sudokuPanel, BorderLayout.CENTER);

        JPanel buttonPanel = getjPanel();
        add(buttonPanel, BorderLayout.SOUTH);

        generatePuzzle();

        while (!issolvable()) {
            generatePuzzle();
        }
        setPuzzle();

    }

    private JPanel getjPanel() {
        JPanel buttonPanel = new JPanel(new GridLayout(1, 2));
        JButton solveButton = new JButton("显示答案");
        solveButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                setSolution();
            }
        });
        JButton tryAgain = new JButton("换一个");
        tryAgain.addActionListener((e) -> {
            generatePuzzle();
            while (!issolvable()) {
                generatePuzzle();
            }
            setPuzzle();
        });
        buttonPanel.add(solveButton);
        buttonPanel.add(tryAgain);
        return buttonPanel;
    }

    private void printCells(int i, int j) {
        switch (i / 3) {
            case 0:
            case 2:
                switch (j / 3) {
                    case 0:
                    case 2:
                        cells[i][j].setBackground(Color.blue);
                        break;
                    case 1:
                        cells[i][j].setBackground(Color.green);
                        break;
                    default:
                        break;
                }
                break;
            case 1:
                switch (j / 3) {
                    case 0:
                    case 2:
                        cells[i][j].setBackground(Color.green);
                        break;
                    case 1:
                        cells[i][j].setBackground(Color.blue);
                        break;
                    default:
                        break;
                }
                break;
            default:
                break;
        }
    }

    private void generatePuzzle() {
        // 创建一个新的数独谜题
        SudokuGenerator generator = new SudokuGenerator();
        puzzle = generator.generateSudokuPuzzle();
    }

    private static class SudokuSolver {
        public boolean solveSudoku(int[][] board) {
            int row = -1;
            int col = -1;
            boolean isEmpty = true;
            // 找到未填充的位置
            for (int i = 0; i < 9; i++) {
                for (int j = 0; j < 9; j++) {
                    if (board[i][j] == 0) {
                        row = i;
                        col = j;
                        isEmpty = false;
                        break;
                    }
                }
                if (!isEmpty) {
                    break;
                }
            }
            // 如果没有未填充的位置,数独已解决
            if (isEmpty) {
                return true;
            }
            // 尝试填充数字
            for (int num = 1; num <= 9; num++) {
                if (isSafe(board, row, col, num)) {
                    board[row][col] = num;
                    if (solveSudoku(board)) {
                        return true;
                    }
                    board[row][col] = 0; // 回溯
                }
            }
            return false;
        }

        private boolean isSafe(int[][] board, int row, int col, int num) {
            // 检查行
            for (int i = 0; i < 9; i++) {
                if (board[row][i] == num) {
                    return false;
                }
            }

            // 检查列
            for (int i = 0; i < 9; i++) {
                if (board[i][col] == num) {
                    return false;
                }
            }

            // 检查小九宫格
            int startRow = row - row % 3;
            int startCol = col - col % 3;
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    if (board[i + startRow][j + startCol] == num) {
                        return false;
                    }
                }
            }
            return true;
        }
    }

    private void setPuzzle() {
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                if (puzzle[i][j] != 0) {
                    cells[i][j].setText(Integer.toString(solution[i][j]));
                    cells[i][j].setEditable(false);
                } else {
                    cells[i][j].setText("");
                }
            }
        }
    }

    private void setSolution() {
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                cells[i][j].setText(Integer.toString(solution[i][j]));
            }
        }
    }


    public boolean issolvable() {
        // 实现数独求解逻辑
        SudokuSolver solver = new SudokuSolver();
        solution = new int[9][9];
        for (int i = 0; i < 9; i++) {
            System.arraycopy(puzzle[i], 0, solution[i], 0, 9);
        }
        return solver.solveSudoku(solution);
    }

    public static void main(String[] args) {
        SudokuGame game = new SudokuGame();
        game.setVisible(true);
    }
}
View Code

随机生成数组类

import java.util.Random;

public class SudokuGenerator {
    private static final int SIZE = 9;
    private int[][] puzzle;

    public SudokuGenerator() {
        puzzle = new int[SIZE][SIZE];
    }

    public int[][] generateSudokuPuzzle() {
        fillDiagonal(); // 填充对角线的 3x3 子网格
        fillRemaining(0, 3); // 从左上角的 3x3 子网格开始填充
        puzzle = generatePuzzleWithHiddenNumbers(60);//参数是要掩盖的数字个数
        return puzzle;
    }

    private void fillDiagonal() {
        Random random = new Random();
        for (int i = 0; i < SIZE; i += 3) {
            fillSubGrid(i, i, random);
        }
    }

    private void fillSubGrid(int row, int col, Random random) {
        int[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9};
        shuffleArray(nums, random);
        int index = 0;
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                puzzle[row + i][col + j] = nums[index++];
            }
        }
    }

    private void shuffleArray(int[] array, Random random) {
        for (int i = array.length - 1; i > 0; i--) {
            int index = random.nextInt(i + 1);
            int temp = array[index];
            array[index] = array[i];
            array[i] = temp;
        }
    }

    private boolean isValid(int row, int col, int num) {
        for (int i = 0; i < SIZE; i++) {
            if (puzzle[row][i] == num || puzzle[i][col] == num) {
                return false;
            }
        }
        int subGridStartRow = row - row % 3;
        int subGridStartCol = col - col % 3;
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (puzzle[subGridStartRow + i][subGridStartCol + j] == num) {
                    return false;
                }
            }
        }
        return true;
    }

    private boolean fillRemaining(int row, int col) {
        if (col == SIZE) {
            col = 0;
            row++;
            if (row == SIZE) {
                return true;
            }
        }
        if (puzzle[row][col] != 0) {
            return fillRemaining(row, col + 1);
        }
        Random random = new Random();
        int[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9};
        shuffleArray(nums, random);
        for (int i = 0; i < SIZE; i++) {
            if (isValid(row, col, nums[i])) {
                puzzle[row][col] = nums[i];
                if (fillRemaining(row, col + 1)) {
                    return true;
                }
                puzzle[row][col] = 0;
            }
        }
        return false;
    }
    public int[][] generatePuzzleWithHiddenNumbers(int numToHide) {
        int[][] puzzleWithHiddenNumbers = deepCopy(puzzle);
        Random random = new Random();
        while (numToHide > 0) {
            int row = random.nextInt(SIZE);
            int col = random.nextInt(SIZE);
            if(puzzleWithHiddenNumbers[row][col] != 0) {
                puzzleWithHiddenNumbers[row][col] =0;
                numToHide--;
            }

        }
        return puzzleWithHiddenNumbers;
    }
    private int[][] deepCopy(int[][] original) {
        int[][] copy = new int[original.length][];
        for (int i = 0; i < original.length; i++) {
            copy[i] = original[i].clone();
        }
        return copy;
    }

}
View Code

改进:

通过调整掩盖数字的个数来实现调整难度的功能,

增加消耗时间的显示

提示单个数字的功能

推荐阅读