You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:51:10