ArithmeticGame.java

📅 2026/7/20 16:10:32
ArithmeticGame.java
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负责绘制与事件转发GameStateDTO 对象实现 Serializable 用于存档MinesweeperApp程序入口2.3 程序界面屏幕截图 2026-07-02 225535屏幕截图 2026-07-02 2256072.4 完整代码MinesweeperGame.javaimport 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.javaimport 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(左键揭开 | 右键标记 | CtrlN 新游戏 | CtrlS 保存 | CtrlO 读取); 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();}}