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

基于Java Swing实现小球触同色网格反弹及反转网格颜色的问题

解决方案与代码示例

核心问题分析

  1. 索引越界原因:原代码在Core构造方法中直接调用getHeight()/getWidth()时,JPanel尚未完成布局,返回值为0,导致网格状态数组初始化失败。
  2. 缺失逻辑:未实现小球与同色网格的碰撞检测、反弹及颜色反转逻辑。

修改后的完整代码

Interface.java(无需修改)

import javax.swing.*;
import java.awt.*;

public class Interface extends JFrame{
    
    private int frameHeight = 637;
    private int frameWidth = 1214;
    
    public Interface() {
        setSize(frameWidth, frameHeight);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new BorderLayout());
        setTitle("Bouncing Ball");
        add(new Core());
        setVisible(true);
    }

    public static void main(String[] args){
        new Interface();
    }
}

Core.java(修改后)

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Core extends JPanel{
    int xw = 10, yw = 10, xb = 1000, yb = 400;
    int bounds = 20, gridSize = 20;
    int vxw = 5, vyw = 5, vxb = 5, vyb = 5;
    int rows, columns;
    int[][] gridState; // 0=黑色网格,1=白色网格

    public Core() {
        Timer timer = new Timer(10, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 移动小球
                xw += vxw;
                yw += vyw;
                xb -= vxb;
                yb -= vyb;

                // 窗口边界反弹
                if (xw > getWidth() - bounds || xw < 0) vxw = -vxw;
                if (yw > getHeight() - bounds || yw < 0) vyw = -vyw;
                if (xb > getWidth() - bounds || xb < 0) vxb = -vxb;
                if (yb > getHeight() - bounds || yb < 0) vyb = -vyb;

                // 处理白球与网格的碰撞
                handleBallCollision(xw + bounds/2, yw + bounds/2, true);
                // 处理黑球与网格的碰撞
                handleBallCollision(xb + bounds/2, yb + bounds/2, false);

                repaint();
            }
        });
        timer.start();
    }

    // 处理小球碰撞逻辑:isWhiteBall为true表示白球,false表示黑球
    private void handleBallCollision(int centerX, int centerY, boolean isWhiteBall) {
        if (gridState == null) return; // 网格未初始化时跳过

        // 计算小球中心所在的网格坐标
        int gridX = centerX / gridSize;
        int gridY = centerY / gridSize;

        // 避免索引越界
        if (gridX < 0 || gridX >= columns || gridY < 0 || gridY >= rows) return;

        // 判断网格颜色是否与小球颜色匹配
        boolean isMatch = isWhiteBall ? (gridState[gridY][gridX] == 1) : (gridState[gridY][gridX] == 0);
        if (isMatch) {
            // 反弹:根据小球移动方向反转速度(这里简化为反转x和y方向,可根据碰撞面调整)
            if (isWhiteBall) {
                vxw = -vxw;
                vyw = -vyw;
            } else {
                vxb = -vxb;
                vyb = -vyb;
            }
            // 反转网格颜色
            gridState[gridY][gridX] = gridState[gridY][gridX] == 0 ? 1 : 0;
        }
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;

        // 初始化网格状态数组(仅第一次绘制时执行)
        if (gridState == null) {
            rows = getHeight() / gridSize;
            columns = getWidth() / gridSize;
            gridState = new int[rows][columns];
            // 初始半黑半白布局
            for (int y = 0; y < rows; y++) {
                for (int x = 0; x < columns; x++) {
                    gridState[y][x] = x < columns / 2 ? 0 : 1;
                }
            }
        }

        // 绘制网格
        for (int y = 0; y < rows; y++) {
            for (int x = 0; x < columns; x++) {
                int posX = x * gridSize;
                int posY = y * gridSize;
                // 根据网格状态设置颜色
                g2d.setColor(gridState[y][x] == 0 ? Color.BLACK : Color.WHITE);
                g2d.fillRect(posX, posY, gridSize, gridSize);
                // 绘制网格线
                g2d.setColor(Color.GRAY);
                g2d.drawRect(posX, posY, gridSize, gridSize);
            }
        }

        // 绘制白球
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(Color.WHITE);
        g2d.fillOval(xw, yw, bounds, bounds);

        // 绘制黑球
        g2d.setColor(Color.BLACK);
        g2d.fillOval(xb, yb, bounds, bounds);
    }
}

关键修改说明

  1. 网格状态数组初始化:移至paintComponent方法中,确保组件布局完成后获取正确的宽高,避免索引越界。
  2. 碰撞检测逻辑:
    • 以小球中心坐标计算所在网格,提升判断准确性。
    • 先判断网格坐标是否在数组范围内,避免索引越界。
    • 匹配小球颜色与网格颜色时,执行反弹(反转速度)和网格颜色反转操作。
  3. 网格绘制优化:根据gridState数组动态绘制颜色,不再依赖固定的半屏判断,支持颜色反转后的状态更新。

内容的提问来源于stack exchange,提问作者garwy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 03:43:27