求助:实现吞噬彩色移动小球的黑色小球Java程序问题
Java小球吞噬程序问题修复
需求说明
- 随机生成100个彩色移动小球,同时生成一个尺寸更大、速度更快的黑色小球
- 黑色小球完全覆盖彩色小球时将其吞噬:吞噬后黑球半径增大、速度降低,被吞噬的彩球消失
- 彩色小球撞击区域边界时,生成新的彩色小球
- 黑球吞噬所有彩球后,程序停止
现有问题
- 黑色小球颜色显示异常
- 吞噬与删除小球的核心逻辑未正确触发
- 未实现彩球撞边界生成新球的逻辑
- 程序无终止条件
修复方案与代码实现
关键修复点
颜色渲染顺序修正
原代码先绘制圆形再设置画笔颜色,导致颜色不生效。需先设置颜色,再绘制图形。同时删除冗余的drawBlackOne()方法,统一使用draw()方法。吞噬逻辑修正
- 替换数组为
ArrayList存储彩球,避免空指针问题,方便动态删除元素 - 用两球中心距离 ≤ 黑球半径 - 彩球半径作为完全覆盖的判断条件,代替原有的坐标完全相等判断
- 替换数组为
边界逻辑补充
当彩球撞击边界时,移除该球并生成新的随机彩球,而非仅反弹。添加程序终止条件
当彩球列表为空时,退出循环,结束程序。
完整修复代码
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
相关产品推荐
相关产品推荐

