求助:检查并修复5x5按钮拼图游戏的颜色切换逻辑问题
修复25格拼图游戏的按钮颜色切换逻辑
你当前的拼图游戏实现中,点击按钮时自身会在浅灰色和红色间切换,但周围按钮只会被强制设为红色。需要优化的逻辑是:当周围按钮被被动触发(即被其他按钮的点击影响)时,如果当前已经是红色,就切换回浅灰色;如果是浅灰色,则切换为红色。
原代码问题分析
原代码处理周围按钮时,直接调用setForeground(Color.RED),没有判断按钮当前的颜色状态,导致被动触发时无法切换回原颜色。另外,每次点击都通过嵌套循环查找按钮的行列索引,效率较低。
修改方案
- 给每个按钮绑定对应的行列索引,避免每次点击都遍历数组查找
- 封装颜色切换逻辑,统一处理按钮颜色反转
- 修改周围按钮的触发逻辑,实现被动状态下的颜色切换
修改后的完整代码
import javax.swing.*; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; public class Frame extends JFrame { private static final long serialVersionUID = 1L; public JButton[][] Buttons = new JButton[5][5]; // 5x5 按钮数组 public static void main(String[] args) { new Frame(); } public Frame() { initGui(); } // 检查所有按钮是否为红色 public boolean allButtonsAreRed() { for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { if (!Buttons[i][j].getForeground().equals(Color.RED)) { return false; } } } return true; } public void initGui() { // 窗口设置 setTitle("25格拼图"); setSize(new Dimension(500, 500)); setResizable(false); setDefaultCloseOperation(EXIT_ON_CLOSE); setLocationRelativeTo(null); // 窗口布局 setLayout(new GridLayout(5, 5, 5, 5)); JOptionPane.showMessageDialog(null, "任务:点击按钮,直到所有圆圈都变成红色!"); for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { JButton button = new JButton(); // 按钮设置 button.setBorderPainted(true); button.setContentAreaFilled(false); button.setOpaque(true); button.setBorder(new RoundedBorder(200)); button.setForeground(Color.LIGHT_GRAY); // 给按钮绑定行列索引,避免点击时遍历查找 button.putClientProperty("row", i); button.putClientProperty("col", j); Buttons[i][j] = button; add(Buttons[i][j]); // 按钮点击事件监听 button.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { JButton clickedBtn = (JButton) e.getSource(); // 切换自身颜色 Color newColor = clickedBtn.getForeground().equals(Color.LIGHT_GRAY) ? Color.RED : Color.LIGHT_GRAY; clickedBtn.setForeground(newColor); // 从按钮属性中获取行列索引 int clickedRow = (int) clickedBtn.getClientProperty("row"); int clickedCol = (int) clickedBtn.getClientProperty("col"); // 处理上方按钮 if (clickedRow > 0) { toggleButtonColor(Buttons[clickedRow - 1][clickedCol]); } // 处理左侧按钮 if (clickedCol > 0) { toggleButtonColor(Buttons[clickedRow][clickedCol - 1]); } // 处理右侧按钮 if (clickedCol < 4) { toggleButtonColor(Buttons[clickedRow][clickedCol + 1]); } // 处理下方按钮 if (clickedRow < 4) { toggleButtonColor(Buttons[clickedRow + 1][clickedCol]); } // 检查是否全部变红,触发胜利提示 if (allButtonsAreRed()) { JOptionPane.showMessageDialog(clickedBtn, "恭喜你,通关了!"); System.exit(0); } } }); } } setVisible(true); } // 封装按钮颜色切换方法,复用逻辑 private void toggleButtonColor(JButton button) { Color currentColor = button.getForeground(); button.setForeground(currentColor.equals(Color.RED) ? Color.LIGHT_GRAY : Color.RED); } } // 圆角边框类(原代码引用但未实现,补充完整) class RoundedBorder implements javax.swing.border.Border { private int radius; RoundedBorder(int radius) { this.radius = radius; } public Insets getBorderInsets(Component c) { return new Insets(this.radius+1, this.radius+1, this.radius+2, this.radius); } public boolean isBorderOpaque() { return true; } public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { g.drawRoundRect(x, y, width-1, height-1, radius, radius); } }
关键修改说明
- 优化索引查找:通过
putClientProperty给每个按钮存储行列值,点击时直接读取,替代嵌套循环查找,提升运行效率。 - 统一切换逻辑:新增
toggleButtonColor方法,将颜色反转逻辑封装,代码更简洁易维护。 - 修复被动触发逻辑:周围按钮不再被强制设为红色,而是调用切换方法实现颜色反转,满足需求。
- 补充缺失实现:原代码引用的
RoundedBorder类未给出实现,这里补充完整,确保代码可直接运行。
内容的提问来源于stack exchange,提问作者Cxnim
相关产品推荐
相关产品推荐

