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

求助:实现吞噬彩色移动小球的黑色小球Java程序问题

Java小球吞噬程序问题修复

需求说明

  • 随机生成100个彩色移动小球,同时生成一个尺寸更大、速度更快的黑色小球
  • 黑色小球完全覆盖彩色小球时将其吞噬:吞噬后黑球半径增大、速度降低,被吞噬的彩球消失
  • 彩色小球撞击区域边界时,生成新的彩色小球
  • 黑球吞噬所有彩球后,程序停止

现有问题

  • 黑色小球颜色显示异常
  • 吞噬与删除小球的核心逻辑未正确触发
  • 未实现彩球撞边界生成新球的逻辑
  • 程序无终止条件

修复方案与代码实现

关键修复点

  1. 颜色渲染顺序修正
    原代码先绘制圆形再设置画笔颜色,导致颜色不生效。需先设置颜色,再绘制图形。同时删除冗余的drawBlackOne()方法,统一使用draw()方法。

  2. 吞噬逻辑修正

    • 替换数组为ArrayList存储彩球,避免空指针问题,方便动态删除元素
    • 用两球中心距离 ≤ 黑球半径 - 彩球半径作为完全覆盖的判断条件,代替原有的坐标完全相等判断
  3. 边界逻辑补充
    当彩球撞击边界时,移除该球并生成新的随机彩球,而非仅反弹。

  4. 添加程序终止条件
    当彩球列表为空时,退出循环,结束程序。

完整修复代码

import java.util.ArrayList;
import java.util.Random;
import java.awt.Color;

public class BallEating {
    private double x, y, vx, vy, r;
    private Color c;
    private static final Color[] BALL_COLORS = {StdDraw.GREEN, StdDraw.RED, StdDraw.BLUE};
    private static ArrayList<BallEating> balls;
    private static BallEating eatingBall;
    private static Random random = new Random();

    public BallEating(double x, double y, double vx, double vy, double r, Color c) {
        this.x = x;
        this.y = y;
        this.vx = vx;
        this.vy = vy;
        this.r = r;
        this.c = c;
    }

    public void move() {
        x += vx;
        y += vy;
    }

    public void draw() {
        StdDraw.setPenColor(c);
        StdDraw.filledCircle(x, y, r);
    }

    // Getters and Setters
    public double getX() { return x; }
    public double getY() { return y; }
    public double getVx() { return vx; }
    public double getVy() { return vy; }
    public double getR() { return r; }
    public void setVx(double vx) { this.vx = vx; }
    public void setVy(double vy) { this.vy = vy; }
    public void setR(double r) { this.r = r; }

    private static void initWindow() {
        StdDraw.enableDoubleBuffering();
        StdDraw.setCanvasSize(500, 500);
        StdDraw.setXscale(-1.0, 1.0);
        StdDraw.setYscale(-1.0, 1.0);
    }

    private static BallEating createRandomBall() {
        double vx = random.nextDouble() * 0.04 - 0.02;
        double vy = random.nextDouble() * 0.04 - 0.02;
        double r = random.nextDouble() * 0.08 + 0.02;
        Color color = BALL_COLORS[random.nextInt(BALL_COLORS.length)];

        double x;
        do {
            x = random.nextDouble() * 2 - 1;
        } while (Math.abs(x) > 1 - r);

        double y;
        do {
            y = random.nextDouble() * 2 - 1;
        } while (Math.abs(y) > 1 - r);

        return new BallEating(x, y, vx, vy, r, color);
    }

    private static void initialize() {
        initWindow();
        balls = new ArrayList<>();
        // 生成100个彩球
        for (int i = 0; i < 100; i++) {
            balls.add(createRandomBall());
        }
        // 初始化黑球:尺寸更大、速度更快
        eatingBall = new BallEating(0.5, 0.5, 0.03, 0.06, 0.2, StdDraw.BLACK);
    }

    private static void handleBlackBallCollision() {
        // 黑球边界反弹
        if (Math.abs(eatingBall.getX() + eatingBall.getVx()) > 1.0 - eatingBall.getR()) {
            eatingBall.setVx(-eatingBall.getVx());
        }
        if (Math.abs(eatingBall.getY() + eatingBall.getVy()) > 1.0 - eatingBall.getR()) {
            eatingBall.setVy(-eatingBall.getVy());
        }
    }

    private static void handleBallEating() {
        for (int i = balls.size() - 1; i >= 0; i--) {
            BallEating ball = balls.get(i);
            double dx = eatingBall.getX() - ball.getX();
            double dy = eatingBall.getY() - ball.getY();
            double distance = Math.sqrt(dx * dx + dy * dy);

            // 判断黑球完全覆盖彩球
            if (distance <= eatingBall.getR() - ball.getR()) {
                // 黑球增大半径、降低速度
                eatingBall.setR(eatingBall.getR() + ball.getR() / 2);
                eatingBall.setVx(eatingBall.getVx() / 1.2);
                eatingBall.setVy(eatingBall.getVy() / 1.2);
                // 移除被吞噬的彩球
                balls.remove(i);
            }
        }
    }

    private static void handleColorBallBorders() {
        for (int i = balls.size() - 1; i >= 0; i--) {
            BallEating ball = balls.get(i);
            boolean hitBorder = false;

            if (Math.abs(ball.getX() + ball.getVx()) > 1.0 - ball.getR()) {
                hitBorder = true;
            }
            if (Math.abs(ball.getY() + ball.getVy()) > 1.0 - ball.getR()) {
                hitBorder = true;
            }

            if (hitBorder) {
                // 移除撞边界的彩球,生成新的
                balls.remove(i);
                balls.add(createRandomBall());
            } else {
                // 正常移动
                ball.move();
            }
        }
    }

    private static void render() {
        StdDraw.clear(StdDraw.BOOK_LIGHT_BLUE);
        // 绘制黑球
        eatingBall.draw();
        // 绘制所有彩球
        for (BallEating ball : balls) {
            ball.draw();
        }
        StdDraw.show();
        StdDraw.pause(20);
    }

    public static void main(String[] args) {
        initialize();

        while (!balls.isEmpty()) {
            eatingBall.move();
            handleBlackBallCollision();
            handleBallEating();
            handleColorBallBorders();
            render();
        }
        // 所有彩球被吞噬,程序结束
        System.out.println("所有彩球已被吞噬,程序结束");
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 16:25:53