Java Swing扫雷游戏开发:ActionListener按钮点击与炸弹判断实现咨询
优化你的扫雷游戏点击逻辑
嘿,我懂你现在的困境——要是给8x8的棋盘每个按钮都写一个if(e.getSource()==tab[x][y]),那得写64个判断,不仅重复率拉满,以后改棋盘大小还得全部重写,太折腾了!咱们换个更聪明的方式来处理点击事件:
核心思路:给按钮绑定位置信息
初始化按钮的时候,把每个按钮对应的行和列存起来,这样点击时直接取出位置,就能对应到mine数组的对应位置,不用逐个判断。
步骤1:初始化按钮时绑定行/列
修改你的按钮初始化代码,给每个JButton添加行和列的属性:
// 初始化棋盘按钮 for (int row = 0; row < 8; row++) { for (int col = 0; col < 8; col++) { tab[row][col] = new JButton(); // 用putClientProperty给按钮绑定行和列 tab[row][col].putClientProperty("row", row); tab[row][col].putClientProperty("col", col); tab[row][col].addActionListener(this); // 这里可以添加按钮的布局、样式等设置 } }
步骤2:简化ActionListener逻辑
现在点击事件里只需要获取点击的按钮,取出绑定的行和列,就能直接操作对应的mine数组了:
@Override public void actionPerformed(ActionEvent e) { JButton clickedBtn = (JButton) e.getSource(); // 取出绑定的行和列 int row = (int) clickedBtn.getClientProperty("row"); int col = (int) clickedBtn.getClientProperty("col"); // 判断是否点击到炸弹 if (mine[row][col] == 9) { clickedBtn.setText("B"); clickedBtn.setEnabled(false); // 这里可以加游戏结束的逻辑,比如弹出提示、禁用所有按钮 JOptionPane.showMessageDialog(null, "游戏结束!你踩到炸弹了"); disableAllButtons(); } else { // 计算周围炸弹数量并显示 int surroundingMines = countSurroundingMines(row, col); clickedBtn.setText(String.valueOf(surroundingMines)); clickedBtn.setEnabled(false); // 如果周围没有炸弹,递归翻开相邻的所有无炸弹按钮(扫雷核心逻辑) if (surroundingMines == 0) { revealAdjacentButtons(row, col); } } }
步骤3:实现辅助方法
计算周围炸弹数量
写个工具方法来统计当前位置周围8个格子里的炸弹数:
private int countSurroundingMines(int row, int col) { int mineCount = 0; // 遍历周围8个方向 for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { // 跳过当前点击的格子 if (i == 0 && j == 0) continue; // 检查是否在棋盘范围内 int checkRow = row + i; int checkCol = col + j; if (checkRow >= 0 && checkRow < 8 && checkCol >= 0 && checkCol < 8) { if (mine[checkRow][checkCol] == 9) { mineCount++; } } } } return mineCount; }
递归翻开相邻无炸弹按钮
当点击的格子周围没有炸弹时,自动翻开所有相邻的格子,循环这个过程:
private void revealAdjacentButtons(int row, int col) { for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { if (i == 0 && j == 0) continue; int checkRow = row + i; int checkCol = col + j; if (checkRow >= 0 && checkRow < 8 && checkCol >= 0 && checkCol < 8) { JButton btn = tab[checkRow][checkCol]; // 只处理未被点击过的按钮 if (btn.isEnabled()) { int mines = countSurroundingMines(checkRow, checkCol); btn.setText(String.valueOf(mines)); btn.setEnabled(false); // 如果这个格子周围也没炸弹,继续递归翻开它的相邻格子 if (mines == 0) { revealAdjacentButtons(checkRow, checkCol); } } } } } }
游戏结束时禁用所有按钮
可选的辅助方法,游戏结束后把所有按钮禁用:
private void disableAllButtons() { for (int row = 0; row < 8; row++) { for (int col = 0; col < 8; col++) { tab[row][col].setEnabled(false); // 可以顺便把所有炸弹显示出来 if (mine[row][col] == 9) { tab[row][col].setText("B"); } } } }
为什么这样更好?
- 可扩展性强:以后要改成10x10或者更大的棋盘,只需要修改数组的大小参数,不用动点击逻辑
- 代码更简洁:不用写几十重复的if判断,逻辑清晰易维护
- 符合扫雷的核心玩法:自动翻开无炸弹区域的逻辑是扫雷的灵魂,这个实现直接帮你搞定了
内容的提问来源于stack exchange,提问作者Demon4i
相关产品推荐
相关产品推荐

