下面是一个完整的扫雷游戏实现,包含图形界面和游戏逻辑。这个程序使用了Java Swing来创建用户界面,实现了经典扫雷游戏的所有核心功能。

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;

public class Minesweeper extends JFrame {
    // 游戏常量
    private static final int ROWS = 16;
    private static final int COLS = 16;
    private static final int MINES = 40;
    private static final int CELL_SIZE = 30;
    
    // 游戏状态
    private JButton[][] buttons;
    private int[][] board;
    private boolean[][] revealed;
    private boolean[][] flagged;
    private int minesLeft;
    private boolean gameOver;
    private boolean firstClick;
    
    // UI组件
    private JPanel gamePanel;
    private JLabel statusLabel;
    private JButton resetButton;
    private Timer gameTimer;
    private int secondsElapsed;
    
    public Minesweeper() {
        super("扫雷游戏");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(COLS * CELL_SIZE + 20, ROWS * CELL_SIZE + 100);
        setLayout(new BorderLayout());
        setResizable(false);
        
        // 初始化游戏状态
        initializeGame();
        
        // 创建顶部面板
        JPanel topPanel = new JPanel();
        topPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 20, 10));
        topPanel.setBackground(new Color(230, 230, 230));
        
        // 状态标签
        statusLabel = new JLabel("扫雷游戏 - 剩余地雷: " + minesLeft);
        statusLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
        topPanel.add(statusLabel);
        
        // 重置按钮
        resetButton = new JButton("重新开始");
        resetButton.setFont(new Font("微软雅黑", Font.PLAIN, 14));
        resetButton.addActionListener(e -> resetGame());
        topPanel.add(resetButton);
        
        add(topPanel, BorderLayout.NORTH);
        
        // 创建游戏面板
        gamePanel = new JPanel();
        gamePanel.setLayout(new GridLayout(ROWS, COLS));
        gamePanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        
        // 创建按钮网格
        buttons = new JButton[ROWS][COLS];
        for (int row = 0; row < ROWS; row++) {
            for (int col = 0; col < COLS; col++) {
                JButton button = new JButton();
                button.setFont(new Font("Arial", Font.BOLD, 14));
                button.setFocusPainted(false);
                button.setMargin(new Insets(0, 0, 0, 0));
                button.setPreferredSize(new Dimension(CELL_SIZE, CELL_SIZE));
                
                // 添加鼠标监听器
                button.addMouseListener(new MouseAdapter() {
                    @Override
                    public void mousePressed(MouseEvent e) {
                        if (gameOver) return;
                        
                        int r = -1, c = -1;
                        // 找到点击的按钮位置
                        for (int i = 0; i < ROWS; i++) {
                            for (int j = 0; j < COLS; j++) {
                                if (buttons[i][j] == e.getSource()) {
                                    r = i;
                                    c = j;
                                    break;
                                }
                            }
                        }
                        
                        if (r != -1 && c != -1) {
                            if (SwingUtilities.isRightMouseButton(e)) {
                                // 右键:标记/取消标记旗帜
                                if (!revealed[r][c]) {
                                    flagged[r][c] = !flagged[r][c];
                                    minesLeft += flagged[r][c] ? -1 : 1;
                                    updateStatus();
                                    buttons[r][c].setText(flagged[r][c] ? "🚩" : "");
                                    buttons[r][c].setBackground(flagged[r][c] ? new Color(255, 200, 200) : new Color(200, 200, 255));
                                }
                            } else {
                                // 左键:揭示格子
                                if (!flagged[r][c]) {
                                    revealCell(r, c);
                                }
                            }
                        }
                    }
                });
                
                buttons[row][col] = button;
                gamePanel.add(button);
            }
        }
        
        add(gamePanel, BorderLayout.CENTER);
        
        // 初始化计时器
        gameTimer = new Timer(1000, e -> {
            secondsElapsed++;
            updateStatus();
        });
        
        // 显示窗口
        setLocationRelativeTo(null);
        setVisible(true);
    }
    
    private void initializeGame() {
        board = new int[ROWS][COLS];
        revealed = new boolean[ROWS][COLS];
        flagged = new boolean[ROWS][COLS];
        minesLeft = MINES;
        gameOver = false;
        firstClick = true;
        secondsElapsed = 0;
    }
    
    private void resetGame() {
        initializeGame();
        
        // 重置UI
        for (int row = 0; row < ROWS; row++) {
            for (int col = 0; col < COLS; col++) {
                buttons[row][col].setText("");
                buttons[row][col].setEnabled(true);
                buttons[row][col].setBackground(new Color(200, 200, 255));
            }
        }
        
        gameTimer.stop();
        updateStatus();
    }
    
    private void placeMines(int firstRow, int firstCol) {
        Random random = new Random();
        int minesPlaced = 0;
        
        while (minesPlaced < MINES) {
            int row = random.nextInt(ROWS);
            int col = random.nextInt(COLS);
            
            // 确保第一个点击的位置不是地雷
            if ((row != firstRow || col != firstCol) && board[row][col] != -1) {
                board[row][col] = -1; // -1表示地雷
                minesPlaced++;
                
                // 更新周围格子的计数
                for (int r = Math.max(0, row - 1); r <= Math.min(ROWS - 1, row + 1); r++) {
                    for (int c = Math.max(0, col - 1); c <= Math.min(COLS - 1, col + 1); c++) {
                        if (board[r][c] != -1) {
                            board[r][c]++;
                        }
                    }
                }
            }
        }
    }
    
    private void revealCell(int row, int col) {
        if (revealed[row][col] || flagged[row][col] || gameOver) {
            return;
        }
        
        // 第一次点击时放置地雷(确保第一次点击不是地雷)
        if (firstClick) {
            placeMines(row, col);
            firstClick = false;
            gameTimer.start();
        }
        
        revealed[row][col] = true;
        buttons[row][col].setEnabled(false);
        
        if (board[row][col] == -1) {
            // 踩到地雷,游戏结束
            gameOver(row, col);
            return;
        }
        
        // 更新按钮文本
        if (board[row][col] > 0) {
            buttons[row][col].setText(String.valueOf(board[row][col]));
            setNumberColor(buttons[row][col], board[row][col]);
        } else {
            buttons[row][col].setText("");
            buttons[row][col].setBackground(new Color(220, 220, 220));
            
            // 如果是空白格子,递归揭示周围的格子
            for (int r = Math.max(0, row - 1); r <= Math.min(ROWS - 1, row + 1); r++) {
                for (int c = Math.max(0, col - 1); c <= Math.min(COLS - 1, col + 1); c++) {
                    if (!revealed[r][c]) {
                        revealCell(r, c);
                    }
                }
            }
        }
        
        // 检查胜利条件
        checkWin();
    }
    
    private void setNumberColor(JButton button, int number) {
        switch (number) {
            case 1: button.setForeground(Color.BLUE); break;
            case 2: button.setForeground(new Color(0, 150, 0)); break; // 深绿色
            case 3: button.setForeground(Color.RED); break;
            case 4: button.setForeground(new Color(0, 0, 128)); break; // 深蓝色
            case 5: button.setForeground(new Color(128, 0, 0)); break; // 深红色
            case 6: button.setForeground(new Color(0, 128, 128)); break; // 青色
            case 7: button.setForeground(Color.BLACK); break;
            case 8: button.setForeground(Color.GRAY); break;
        }
    }
    
    private void gameOver(int row, int col) {
        gameOver = true;
        gameTimer.stop();
        
        // 显示所有地雷
        for (int r = 0; r < ROWS; r++) {
            for (int c = 0; c < COLS; c++) {
                if (board[r][c] == -1) {
                    buttons[r][c].setText("💣");
                    buttons[r][c].setBackground(Color.RED);
                }
            }
        }
        
        // 标记踩中的地雷
        buttons[row][col].setText("💥");
        buttons[row][col].setBackground(Color.ORANGE);
        
        statusLabel.setText("游戏结束!点击重新开始按钮再试一次");
    }
    
    private void checkWin() {
        int unrevealedCount = 0;
        
        for (int row = 0; row < ROWS; row++) {
            for (int col = 0; col < COLS; col++) {
                if (!revealed[row][col] && board[row][col] != -1) {
                    unrevealedCount++;
                }
            }
        }
        
        if (unrevealedCount == 0) {
            gameOver = true;
            gameTimer.stop();
            
            // 标记所有地雷
            for (int row = 0; row < ROWS; row++) {
                for (int col = 0; col < COLS; col++) {
                    if (board[row][col] == -1 && !flagged[row][col]) {
                        buttons[row][col].setText("🚩");
                    }
                }
            }
            
            statusLabel.setText("恭喜你赢了!用时: " + secondsElapsed + "秒");
        }
    }
    
    private void updateStatus() {
        statusLabel.setText("扫雷游戏 - 剩余地雷: " + minesLeft + " - 用时: " + secondsElapsed + "秒");
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            new Minesweeper();
        });
    }
}

如何运行

1. 将代码复制到名为 Minesweeper.java 的文件中
2. 编译程序:javac Minesweeper.java
3. 运行程序:java Minesweeper

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐