ArithmeticGame.java
2026/7/24 7:07:50 网站建设 项目流程

import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.metal.MetalLookAndFeel;

/**

  • 程序入口:使用 Metal LookAndFeel 确保按钮颜色正常显示
    */
    public class ArithmeticGame {
    public static void main(String[] args) {
    try {
    UIManager.setLookAndFeel(new MetalLookAndFeel());
    UIManager.put(“Button.foreground”, java.awt.Color.WHITE);
    UIManager.put(“Button.background”, new java.awt.Color(50, 130, 220));
    UIManager.put(“Button.select”, new java.awt.Color(40, 110, 200));
    UIManager.put(“Button.focus”, new java.awt.Color(50, 130, 220));
    } catch (Exception e) {
    e.printStackTrace();
    }
    SwingUtilities.invokeLater(() -> new GameUI().setVisible(true));
    }
    }
    二、项目二:扫雷游戏
    2.1 需求分析
    复刻经典扫雷:左键揭开、右键标记(旗/问号)、笑脸重置、LED 计数器、难度分级、存档读档。

2.2 架构设计
MinesweeperGame:纯逻辑核心,不依赖 Swing,方便单元测试与序列化
MinesweeperUI:负责绘制与事件转发
GameState:DTO 对象,实现 Serializable 用于存档
MinesweeperApp:程序入口
2.3 程序界面
屏幕截图 2026-07-02 225535

屏幕截图 2026-07-02 225607

2.4 完整代码
MinesweeperGame.java
import java.io.Serializable;
import java.util.Random;

/**

  • 扫雷游戏核心类:管理雷区、揭开、标记、计时、胜负判断
    */
    public class MinesweeperGame implements Serializable {
    private static final long serialVersionUID = 1L;

    public enum CellState { COVERED, REVEALED, FLAGGED, QUESTIONED }

    public static class Cell implements Serializable {
    private static final long serialVersionUID = 1L;
    boolean isMine;
    int neighborMines;
    CellState state = CellState.COVERED;
    }

    private Cell[][] board;
    private int rows, cols, mineCount;
    private int revealedCount;
    private int flaggedCount;
    private boolean gameOver;
    private boolean win;
    private boolean started;
    private transient long startTimeMillis;
    private int elapsedTime;
    private int steps;
    private String difficultyName;

    public void init(int rows, int cols, int mineCount, String difficultyName) {
    this.rows = rows;
    this.cols = cols;
    this.mineCount = mineCount;
    this.difficultyName = difficultyName;
    board = new Cell[rows][cols];
    for (int r = 0; r < rows; r++) {
    for (int c = 0; c < cols; c++) {
    board[r][c] = new Cell();
    }
    }
    revealedCount = 0;
    flaggedCount = 0;
    gameOver = false;
    win = false;
    started = false;
    elapsedTime = 0;
    steps = 0;
    }

    private void placeMines(int firstRow, int firstCol) {
    Random rand = new Random();
    int placed = 0;
    while (placed < mineCount) {
    int r = rand.nextInt(rows);
    int c = rand.nextInt(cols);
    if (r == firstRow && c == firstCol) continue;
    if (!board[r][c].isMine) {
    board[r][c].isMine = true;
    placed++;
    }
    }
    for (int r = 0; r < rows; r++) {
    for (int c = 0; c < cols; c++) {
    if (board[r][c].isMine) continue;
    int count = 0;
    for (int dr = -1; dr <= 1; dr++) {
    for (int dc = -1; dc <= 1; dc++) {
    if (dr == 0 && dc == 0) continue;
    int nr = r + dr, nc = c + dc;
    if (nr >= 0 && nr < rows && nc >= 0 && nc < cols && board[nr][nc].isMine) {
    count++;
    }
    }
    }
    board[r][c].neighborMines = count;
    }
    }
    started = true;
    startTimeMillis = System.currentTimeMillis();
    }

    public boolean reveal(int r, int c) {
    return reveal(r, c, true);
    }

    private boolean reveal(int r, int c, boolean countStep) {
    if (gameOver || r < 0 || r >= rows || c < 0 || c >= cols) return false;
    Cell cell = board[r][c];
    if (cell.state != CellState.COVERED) return false;

    if (!started) placeMines(r, c); cell.state = CellState.REVEALED; revealedCount++; if (countStep) steps++; if (cell.isMine) { gameOver = true; win = false; return true; } if (cell.neighborMines == 0) { for (int dr = -1; dr <= 1; dr++) { for (int dc = -1; dc <= 1; dc++) { if (dr == 0 && dc == 0) continue; reveal(r + dr, c + dc, false); } } } if (revealedCount == rows * cols - mineCount) { gameOver = true; win = true; } return true;

    }

    public void toggleFlag(int r, int c) {
    if (gameOver || r < 0 || r >= rows || c < 0 || c >= cols) return;
    Cell cell = board[r][c];
    if (cell.state == CellState.REVEALED) return;

    steps++; switch (cell.state) { case COVERED: cell.state = CellState.FLAGGED; flaggedCount++; break; case FLAGGED: cell.state = CellState.QUESTIONED; flaggedCount--; break; case QUESTIONED: cell.state = CellState.COVERED; break; }

    }

    public int getElapsedTime() {
    if (started && !gameOver) {
    elapsedTime = (int) ((System.currentTimeMillis() - startTimeMillis) / 1000);
    }
    return elapsedTime;
    }

    public void setElapsedTime(int elapsedTime) {
    this.elapsedTime = elapsedTime;
    if (started && !gameOver) {
    this.startTimeMillis = System.currentTimeMillis() - elapsedTime * 1000L;
    }
    }

    public Cell[][] getBoard() { return board; }
    public int getRows() { return rows; }
    public int getCols() { return cols; }
    public int getMineCount() { return mineCount; }
    public int getRevealedCount() { return revealedCount; }
    public int getFlaggedCount() { return flaggedCount; }
    public boolean isGameOver() { return gameOver; }
    public boolean isWin() { return win; }
    public boolean isStarted() { return started; }
    public int getSteps() { return steps; }
    public String getDifficultyName() { return difficultyName; }

    public void setGameOver(boolean gameOver) { this.gameOver = gameOver; }
    public void setWin(boolean win) { this.win = win; }
    public void setStarted(boolean started) { this.started = started; }
    public void setRevealedCount(int revealedCount) { this.revealedCount = revealedCount; }
    public void setFlaggedCount(int flaggedCount) { this.flaggedCount = flaggedCount; }
    public void setSteps(int steps) { this.steps = steps; }
    public void setBoard(Cell[][] board) { this.board = board; }
    public void setRows(int rows) { this.rows = rows; }
    public void setCols(int cols) { this.cols = cols; }
    public void setMineCount(int mineCount) { this.mineCount = mineCount; }
    public void setDifficultyName(String difficultyName) { this.difficultyName = difficultyName; }
    }
    GameState.java(扫雷)
    import java.io.Serializable;

/**

  • 游戏状态封装:实现 Serializable,用于保存/读取进度
    */
    public class GameState implements Serializable {
    private static final long serialVersionUID = 1L;

    private MinesweeperGame.Cell[][] board;
    private int rows, cols, mineCount;
    private int revealedCount, flaggedCount;
    private boolean gameOver, win, started;
    private int elapsedTime, steps;
    private String difficultyName;

    public GameState(MinesweeperGame game) {
    this.board = game.getBoard();
    this.rows = game.getRows();
    this.cols = game.getCols();
    this.mineCount = game.getMineCount();
    this.revealedCount = game.getRevealedCount();
    this.flaggedCount = game.getFlaggedCount();
    this.gameOver = game.isGameOver();
    this.win = game.isWin();
    this.started = game.isStarted();
    this.elapsedTime = game.getElapsedTime();
    this.steps = game.getSteps();
    this.difficultyName = game.getDifficultyName();
    }

    public MinesweeperGame.Cell[][] getBoard() { return board; }
    public int getRows() { return rows; }
    public int getCols() { return cols; }
    public int getMineCount() { return mineCount; }
    public int getRevealedCount() { return revealedCount; }
    public int getFlaggedCount() { return flaggedCount; }
    public boolean isGameOver() { return gameOver; }
    public boolean isWin() { return win; }
    public boolean isStarted() { return started; }
    public int getElapsedTime() { return elapsedTime; }
    public int getSteps() { return steps; }
    public String getDifficultyName() { return difficultyName; }
    }
    MinesweeperUI.java
    import javax.swing.;
    import javax.swing.border.
    ;
    import java.awt.;
    import java.awt.event.
    ;
    import java.io.*;

/**

  • 优化版扫雷图形界面:解决 Emoji 显示问题,提升视觉体验
    */
    public class MinesweeperUI extends JFrame {
    private MinesweeperGame game;
    private JButton[][] buttons;
    private JPanel boardPanel;
    private JLabel mineLabel, timeLabel, stepLabel;
    private JButton faceButton;
    private Timer timer;
    private int currentRows = 9, currentCols = 9, currentMines = 10;
    private String currentDifficulty = “初级”;

    private final Color[] NUMBER_COLORS = {
    Color.BLACK, new Color(0, 0, 255), new Color(0, 128, 0),
    new Color(255, 0, 0), new Color(0, 0, 128), new Color(128, 0, 0),
    new Color(0, 128, 128), new Color(0, 0, 0), new Color(128, 128, 128)
    };

    private final Color BG_COLOR = new Color(192, 192, 192);
    private final Color BOARD_BG = new Color(128, 128, 128);
    private final Color CELL_COVERED = new Color(192, 192, 192);
    private final Color CELL_REVEALED = new Color(220, 220, 220);
    private final Color MINE_BG = new Color(255, 100, 100);
    private final Color FLAG_COLOR = new Color(220, 0, 0);
    private final Color QUESTION_COLOR = new Color(0, 0, 0);
    private final Color LED_BG = new Color(0, 0, 0);
    private final Color LED_FG = new Color(255, 50, 50);

    public MinesweeperUI() {
    setTitle(“扫雷游戏”);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setResizable(false);
    initMenu();
    initComponents();
    newGame(currentRows, currentCols, currentMines, currentDifficulty);
    }

    private void initMenu() {
    JMenuBar menuBar = new JMenuBar();
    menuBar.setBackground(new Color(220, 220, 220));

    JMenu gameMenu = new JMenu("游戏(G)"); gameMenu.setMnemonic(KeyEvent.VK_G); gameMenu.setFont(new Font("微软雅黑", Font.PLAIN, 13)); JMenuItem newItem = new JMenuItem("新游戏(N)", KeyEvent.VK_N); newItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_DOWN_MASK)); newItem.setFont(new Font("微软雅黑", Font.PLAIN, 13)); newItem.addActionListener(e -> newGame(currentRows, currentCols, currentMines, currentDifficulty)); JMenuItem saveItem = new JMenuItem("保存进度(S)", KeyEvent.VK_S); saveItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK)); saveItem.setFont(new Font("微软雅黑", Font.PLAIN, 13)); saveItem.addActionListener(e -> saveGame()); JMenuItem loadItem = new JMenuItem("读取进度(L)", KeyEvent.VK_L); loadItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK)); loadItem.setFont(new Font("微软雅黑", Font.PLAIN, 13)); loadItem.addActionListener(e -> loadGame()); JMenu diffMenu = new JMenu("难度"); diffMenu.setFont(new Font("微软雅黑", Font.PLAIN, 13)); JMenuItem begItem = new JMenuItem("初级 (9x9, 10雷)"); JMenuItem intItem = new JMenuItem("中级 (16x16, 40雷)"); JMenuItem expItem = new JMenuItem("高级 (16x30, 99雷)"); JMenuItem custItem = new JMenuItem("自定义..."); for (JMenuItem item : new JMenuItem[]{begItem, intItem, expItem, custItem}) { item.setFont(new Font("微软雅黑", Font.PLAIN, 13)); } begItem.addActionListener(e -> setDifficulty(9, 9, 10, "初级")); intItem.addActionListener(e -> setDifficulty(16, 16, 40, "中级")); expItem.addActionListener(e -> setDifficulty(16, 30, 99, "高级")); custItem.addActionListener(e -> showCustomDialog()); diffMenu.add(begItem); diffMenu.add(intItem); diffMenu.add(expItem); diffMenu.add(custItem); JMenuItem exitItem = new JMenuItem("退出(Q)"); exitItem.setFont(new Font("微软雅黑", Font.PLAIN, 13)); exitItem.addActionListener(e -> System.exit(0)); gameMenu.add(newItem); gameMenu.add(saveItem); gameMenu.add(loadItem); gameMenu.addSeparator(); gameMenu.add(diffMenu); gameMenu.addSeparator(); gameMenu.add(exitItem); JMenu helpMenu = new JMenu("帮助(H)"); helpMenu.setMnemonic(KeyEvent.VK_H); helpMenu.setFont(new Font("微软雅黑", Font.PLAIN, 13)); JMenuItem aboutItem = new JMenuItem("关于"); aboutItem.setFont(new Font("微软雅黑", Font.PLAIN, 13)); aboutItem.addActionListener(e -> JOptionPane.showMessageDialog(this, "Java Swing 扫雷游戏 v2.0\n\n" + "【操作说明】\n" + "• 左键单击:揭开格子\n" + "• 右键单击:标记/取消标记\n" + "• 笑脸按钮:重新开始\n\n" + "【功能特性】\n" + "• 四种难度(含自定义)\n" + "• 实时计时与计步\n" + "• 保存/读取游戏进度", "关于扫雷", JOptionPane.INFORMATION_MESSAGE)); helpMenu.add(aboutItem); menuBar.add(gameMenu); menuBar.add(helpMenu); setJMenuBar(menuBar);

    }

    private void initComponents() {
    setLayout(new BorderLayout());

    JPanel topPanel = new JPanel(new BorderLayout(10, 0)); topPanel.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createEmptyBorder(10, 12, 10, 12), BorderFactory.createLoweredBevelBorder() )); topPanel.setBackground(BG_COLOR); JPanel leftPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 8, 0)); leftPanel.setOpaque(false); mineLabel = createLedLabel("010"); stepLabel = createLedLabel("000"); JLabel mineText = new JLabel("剩余雷数"); mineText.setFont(new Font("微软雅黑", Font.PLAIN, 11)); mineText.setForeground(Color.DARK_GRAY); JLabel stepText = new JLabel("步数"); stepText.setFont(new Font("微软雅黑", Font.PLAIN, 11)); stepText.setForeground(Color.DARK_GRAY); JPanel minePanel = new JPanel(new GridLayout(2, 1, 0, 2)); minePanel.setOpaque(false); minePanel.add(mineLabel); minePanel.add(mineText); JPanel stepPanel = new JPanel(new GridLayout(2, 1, 0, 2)); stepPanel.setOpaque(false); stepPanel.add(stepLabel); stepPanel.add(stepText); leftPanel.add(minePanel); leftPanel.add(Box.createHorizontalStrut(10)); leftPanel.add(stepPanel); faceButton = createFaceButton(); JPanel rightPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 8, 0)); rightPanel.setOpaque(false); timeLabel = createLedLabel("000"); JLabel timeText = new JLabel("时间(秒)"); timeText.setFont(new Font("微软雅黑", Font.PLAIN, 11)); timeText.setForeground(Color.DARK_GRAY); JPanel timePanel = new JPanel(new GridLayout(2, 1, 0, 2)); timePanel.setOpaque(false); timePanel.add(timeLabel); timePanel.add(timeText); rightPanel.add(timePanel); topPanel.add(leftPanel, BorderLayout.WEST); topPanel.add(faceButton, BorderLayout.CENTER); topPanel.add(rightPanel, BorderLayout.EAST); add(topPanel, BorderLayout.NORTH); boardPanel = new JPanel(); boardPanel.setBackground(BOARD_BG); boardPanel.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createEmptyBorder(8, 8, 8, 8), BorderFactory.createLoweredBevelBorder() )); add(boardPanel, BorderLayout.CENTER); JPanel statusPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 5)); statusPanel.setBackground(BG_COLOR); statusPanel.setBorder(BorderFactory.createEmptyBorder(3, 0, 3, 0)); JLabel statusLabel = new JLabel("左键揭开 | 右键标记 | Ctrl+N 新游戏 | Ctrl+S 保存 | Ctrl+O 读取"); statusLabel.setFont(new Font("微软雅黑", Font.PLAIN, 11)); statusLabel.setForeground(Color.DARK_GRAY); statusPanel.add(statusLabel); add(statusPanel, BorderLayout.SOUTH); timer = new Timer(100, e -> updateTimer());

    }

    private JLabel createLedLabel(String text) {
    JLabel label = new JLabel(text, SwingConstants.CENTER);
    label.setFont(new Font(“Consolas”, Font.BOLD, 24));
    label.setForeground(LED_FG);
    label.setBackground(LED_BG);
    label.setOpaque(true);
    label.setBorder(BorderFactory.createCompoundBorder(
    BorderFactory.createLineBorder(Color.DARK_GRAY, 1),
    BorderFactory.createEmptyBorder(4, 8, 4, 8)
    ));
    label.setPreferredSize(new Dimension(70, 40));
    return label;
    }

    private JButton createFaceButton() {
    JButton btn = new JButton(“☺”);
    btn.setFont(new Font(“Segoe UI Symbol”, Font.BOLD, 28));
    btn.setFocusPainted(false);
    btn.setPreferredSize(new Dimension(55, 55));
    btn.setBackground(BG_COLOR);
    btn.setBorder(BorderFactory.createCompoundBorder(
    BorderFactory.createRaisedBevelBorder(),
    BorderFactory.createEmptyBorder(2, 2, 2, 2)
    ));
    btn.setCursor(new Cursor(Cursor.HAND_CURSOR));
    btn.addActionListener(e -> newGame(currentRows, currentCols, currentMines, currentDifficulty));
    return btn;
    }

    private void setDifficulty(int r, int c, int m, String name) {
    currentRows = r; currentCols = c; currentMines = m; currentDifficulty = name;
    newGame(r, c, m, name);
    }

    private void showCustomDialog() {
    JPanel panel = new JPanel(new GridBagLayout());
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.insets = new Insets(8, 10, 8, 10);
    gbc.anchor = GridBagConstraints.WEST;

    JTextField rowField = new JTextField("16", 8); JTextField colField = new JTextField("16", 8); JTextField mineField = new JTextField("40", 8); Font fieldFont = new Font("微软雅黑", Font.PLAIN, 14); for (JTextField f : new JTextField[]{rowField, colField, mineField}) { f.setFont(fieldFont); } gbc.gridx = 0; gbc.gridy = 0; panel.add(new JLabel("行数:"), gbc); gbc.gridx = 1; panel.add(rowField, gbc); gbc.gridx = 0; gbc.gridy = 1; panel.add(new JLabel("列数:"), gbc); gbc.gridx = 1; panel.add(colField, gbc); gbc.gridx = 0; gbc.gridy = 2; panel.add(new JLabel("雷数:"), gbc); gbc.gridx = 1; panel.add(mineField, gbc); int result = JOptionPane.showConfirmDialog(this, panel, "自定义难度", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); if (result == JOptionPane.OK_OPTION) { try { int r = Integer.parseInt(rowField.getText().trim()); int c = Integer.parseInt(colField.getText().trim()); int m = Integer.parseInt(mineField.getText().trim()); if (r < 5 || c < 5 || m < 1 || m >= r * c) { JOptionPane.showMessageDialog(this, "参数无效!\n行/列 ≥ 5,雷数 ≥ 1 且小于总格数", "错误", JOptionPane.ERROR_MESSAGE); return; } setDifficulty(r, c, m, "自定义"); } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(this, "请输入有效的数字!", "错误", JOptionPane.ERROR_MESSAGE); } }

    }

    private void newGame(int rows, int cols, int mines, String diffName) {
    if (timer != null) timer.stop();
    game = new MinesweeperGame();
    game.init(rows, cols, mines, diffName);

    boardPanel.removeAll(); boardPanel.setLayout(new GridLayout(rows, cols, 1, 1)); buttons = new JButton[rows][cols]; for (int r = 0; r < rows; r++) { for (int c = 0; c < cols; c++) { JButton btn = new JButton(); btn.setPreferredSize(new Dimension(30, 30)); btn.setFont(new Font("微软雅黑", Font.BOLD, 16)); btn.setFocusPainted(false); btn.setBackground(CELL_COVERED); btn.setBorder(BorderFactory.createRaisedBevelBorder()); btn.setCursor(new Cursor(Cursor.HAND_CURSOR)); final int rr = r, cc = c; btn.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { if (game.isGameOver()) return; if (SwingUtilities.isLeftMouseButton(e)) { handleLeftClick(rr, cc); } else if (SwingUtilities.isRightMouseButton(e)) { handleRightClick(rr, cc); } } }); buttons[r][c] = btn; boardPanel.add(btn); } } updateBoard(); updateInfo(); faceButton.setText("☺"); faceButton.setBackground(BG_COLOR); pack(); setLocationRelativeTo(null); boardPanel.revalidate(); boardPanel.repaint();

    }

    private void handleLeftClick(int r, int c) {
    if (game.reveal(r, c)) {
    updateBoard();
    updateInfo();
    if (game.isGameOver()) {
    timer.stop();
    if (game.isWin()) {
    faceButton.setText(“☻”);
    faceButton.setBackground(new Color(180, 255, 180));
    JOptionPane.showMessageDialog(this,
    “恭喜你赢了!\n\n”
    + "难度: " + game.getDifficultyName() +
    "\n用时: " + game.getElapsedTime() + " 秒\n步数: " + game.getSteps(),
    “胜利”, JOptionPane.INFORMATION_MESSAGE);
    } else {
    faceButton.setText(“☹”);
    faceButton.setBackground(new Color(255, 180, 180));
    revealAllMines();
    JOptionPane.showMessageDialog(this,
    “踩到地雷了!游戏结束。\n用时: " + game.getElapsedTime() + " 秒”,
    “失败”, JOptionPane.ERROR_MESSAGE);
    }
    } else if (!timer.isRunning() && game.isStarted()) {
    timer.start();
    }
    }
    }

    private void handleRightClick(int r, int c) {
    game.toggleFlag(r, c);
    updateBoard();
    updateInfo();
    }

    private void updateBoard() {
    MinesweeperGame.Cell[][] board = game.getBoard();
    for (int r = 0; r < game.getRows(); r++) {
    for (int c = 0; c < game.getCols(); c++) {
    JButton btn = buttons[r][c];
    MinesweeperGame.Cell cell = board[r][c];

    if (cell.state == MinesweeperGame.CellState.REVEALED) { btn.setBackground(CELL_REVEALED); btn.setBorder(BorderFactory.createLoweredBevelBorder()); if (cell.isMine) { btn.setText("✦"); btn.setFont(new Font("Segoe UI Symbol", Font.BOLD, 18)); btn.setForeground(Color.BLACK); btn.setBackground(MINE_BG); } else if (cell.neighborMines > 0) { btn.setText(String.valueOf(cell.neighborMines)); btn.setFont(new Font("微软雅黑", Font.BOLD, 16)); btn.setForeground(NUMBER_COLORS[cell.neighborMines]); } else { btn.setText(""); } } else if (cell.state == MinesweeperGame.CellState.FLAGGED) { btn.setText("▶"); btn.setFont(new Font("Segoe UI Symbol", Font.BOLD, 14)); btn.setForeground(FLAG_COLOR); btn.setBackground(CELL_COVERED); btn.setBorder(BorderFactory.createRaisedBevelBorder()); } else if (cell.state == MinesweeperGame.CellState.QUESTIONED) { btn.setText("?"); btn.setFont(new Font("微软雅黑", Font.BOLD, 16)); btn.setForeground(QUESTION_COLOR); btn.setBackground(CELL_COVERED); btn.setBorder(BorderFactory.createRaisedBevelBorder()); } else { btn.setText(""); btn.setBackground(CELL_COVERED); btn.setBorder(BorderFactory.createRaisedBevelBorder()); } } }

    }

    private void revealAllMines() {
    MinesweeperGame.Cell[][] board = game.getBoard();
    for (int r = 0; r < game.getRows(); r++) {
    for (int c = 0; c < game.getCols(); c++) {
    if (board[r][c].isMine) {
    buttons[r][c].setText(“✦”);
    buttons[r][c].setFont(new Font(“Segoe UI Symbol”, Font.BOLD, 18));
    buttons[r][c].setForeground(Color.BLACK);
    buttons[r][c].setBackground(MINE_BG);
    buttons[r][c].setBorder(BorderFactory.createLoweredBevelBorder());
    }
    }
    }
    }

    private void updateInfo() {
    int remaining = game.getMineCount() - game.getFlaggedCount();
    mineLabel.setText(String.format(“%03d”, Math.max(0, remaining)));
    timeLabel.setText(String.format(“%03d”, game.getElapsedTime()));
    stepLabel.setText(String.format(“%03d”, game.getSteps()));
    }

    private void updateTimer() {
    if (game != null && game.isStarted() && !game.isGameOver()) {
    timeLabel.setText(String.format(“%03d”, game.getElapsedTime()));
    }
    }

    private void saveGame() {
    if (game == null || !game.isStarted()) {
    JOptionPane.showMessageDialog(this, “游戏尚未开始,无法保存!”, “提示”, JOptionPane.WARNING_MESSAGE);
    return;
    }
    JFileChooser chooser = new JFileChooser();
    chooser.setSelectedFile(new File(“minesweeper.sav”));
    if (chooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
    File file = chooser.getSelectedFile();
    try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file))) {
    oos.writeObject(new GameState(game));
    JOptionPane.showMessageDialog(this, “保存成功!”, “提示”, JOptionPane.INFORMATION_MESSAGE);
    } catch (IOException ex) {
    JOptionPane.showMessageDialog(this, "保存失败: " + ex.getMessage(), “错误”, JOptionPane.ERROR_MESSAGE);
    }
    }
    }

    private void loadGame() {
    JFileChooser chooser = new JFileChooser();
    if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
    File file = chooser.getSelectedFile();
    try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
    GameState state = (GameState) ois.readObject();
    restoreGame(state);
    JOptionPane.showMessageDialog(this, “读取成功!”, “提示”, JOptionPane.INFORMATION_MESSAGE);
    } catch (IOException | ClassNotFoundException ex) {
    JOptionPane.showMessageDialog(this, "读取失败: " + ex.getMessage(), “错误”, JOptionPane.ERROR_MESSAGE);
    }
    }
    }

    private void restoreGame(GameState state) {
    if (timer != null) timer.stop();

    currentRows = state.getRows(); currentCols = state.getCols(); currentMines = state.getMineCount(); currentDifficulty = state.getDifficultyName(); game = new MinesweeperGame(); game.init(currentRows, currentCols, currentMines, currentDifficulty); game.setBoard(state.getBoard()); game.setRevealedCount(state.getRevealedCount()); game.setFlaggedCount(state.getFlaggedCount()); game.setGameOver(state.isGameOver()); game.setWin(state.isWin()); game.setStarted(state.isStarted()); game.setElapsedTime(state.getElapsedTime()); game.setSteps(state.getSteps()); boardPanel.removeAll(); boardPanel.setLayout(new GridLayout(currentRows, currentCols, 1, 1)); buttons = new JButton[currentRows][currentCols]; for (int r = 0; r < currentRows; r++) { for (int c = 0; c < currentCols; c++) { JButton btn = new JButton(); btn.setPreferredSize(new Dimension(30, 30)); btn.setFont(new Font("微软雅黑", Font.BOLD, 16)); btn.setFocusPainted(false); btn.setBackground(CELL_COVERED); btn.setBorder(BorderFactory.createRaisedBevelBorder()); btn.setCursor(new Cursor(Cursor.HAND_CURSOR)); final int rr = r, cc = c; btn.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { if (game.isGameOver()) return; if (SwingUtilities.isLeftMouseButton(e)) { handleLeftClick(rr, cc); } else if (SwingUtilities.isRightMouseButton(e)) { handleRightClick(rr, cc); } } }); buttons[r][c] = btn; boardPanel.add(btn); } } updateBoard(); updateInfo(); if (game.isStarted() && !game.isGameOver()) { timer.start(); faceButton.setText("☺"); faceButton.setBackground(BG_COLOR); } else if (game.isGameOver()) { if (game.isWin()) { faceButton.setText("☻"); faceButton.setBackground(new Color(180, 255, 180)); } else { faceButton.setText("☹"); faceButton.setBackground(new Color(255, 180, 180)); revealAllMines(); } } else { faceButton.setText("☺"); faceButton.setBackground(BG_COLOR); } pack(); setLocationRelativeTo(null); boardPanel.revalidate(); boardPanel.repaint();

    }
    }

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询