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

Pang游戏箭支异常生成致崩溃问题排查求助

问题分析与解决方案

你遇到的程序崩溃问题,核心是遍历集合时直接修改集合(添加/删除元素)导致的索引错乱,再加上气泡数量无限制指数级增长,最终引发内存耗尽或循环异常。咱们一步步拆解问题并解决:

核心问题点

  • 遍历集合时的索引错乱:
    不管是bubblesArray还是arrowArray,你在普通正序for循环里直接调用remove(),会让集合大小动态变化——比如删除bubblesArray.get(i)后,后面的元素会前移到i的位置,但循环的i还会自增,直接跳过这个元素;箭数组的遍历也存在同样的越界或跳元素问题。

  • 气泡数量爆炸式增长:
    每次击中气泡时numberOfBubble *=2,几次击中后气泡数量会指数级飙升,很快耗尽内存或者让循环执行时间过长,直接导致程序崩溃。

  • 箭支移除的逻辑冗余:
    if(arrowArray.size()>=0)这个判断完全多余(集合大小不可能小于0),而且移除箭后没有处理索引偏移,容易引发后续遍历异常。

修正后的代码示例

1. 修复集合遍历与修改逻辑

遍历需要修改的集合时,推荐用倒序遍历,这样删除元素后不会影响未遍历到的元素索引:

// 倒序遍历气泡数组,避免删除元素后索引错乱
for (int i = bubblesArray.size() - 1; i >= 0; i--) {
    Bubbles currentBubble = bubblesArray.get(i);
    currentBubble.move();
    currentBubble.checkBorders();
    currentBubble.display();

    // 倒序遍历箭数组
    for (int j = arrowArray.size() - 1; j >= 0; j--) {
        Arrow currentArrow = arrowArray.get(j);
        currentArrow.shoot();
        currentArrow.display();

        // 移除超出屏幕的箭
        if (currentArrow.getPosYArrow() + currentArrow.getHeightArrow() < 0) {
            arrowArray.remove(j);
            continue; // 跳过后续判断,处理下一支箭
        }

        // 检查箭是否击中气泡
        if (currentBubble.checkHitArrow(currentArrow)) {
            timesHit += 1;
            // 限制新气泡数量,避免指数爆炸(比如最多生成2个)
            int newBubbleCount = Math.min(2, numberOfBubble);
            numberOfBubble = newBubbleCount;

            // 移除击中的箭
            arrowArray.remove(j);

            // 生成带随机偏移的小气泡,避免重叠
            bubbleWidth = bubble.width / 2;
            bubbleHeight = bubble.height / 2;
            bubble.resize(bubbleWidth, bubbleHeight);
            for (int k = 0; k < newBubbleCount; k++) {
                float offsetX = (float) Math.random() * 50 - 25;
                float offsetY = (float) Math.random() * 50 - 25;
                bubblesArray.add(new Bubbles(
                    currentBubble.getPosXBubbles() + offsetX,
                    currentBubble.getPosYBubbles() + offsetY,
                    bubble
                ));
            }

            // 移除被击中的气泡
            bubblesArray.remove(i);
            break; // 跳出箭循环,处理下一个气泡
        }
    }
}

2. 按键发射箭的代码(无需修改)

void keyPressed() {
    if (key == ' ') {
        arrowArray.add(new Arrow(arrow, p.getPosXPlayer() + p.getWidthPlayer()/2, p.getPosYPlayer()));
        printArray(arrowArray);
    }
}

额外优化建议

  • 限制气泡最小尺寸:当气泡缩小到一定程度后,击中不再生成新气泡,避免无限分裂。
  • 添加调试打印:可以在循环中偶尔打印bubblesArray.size()和arrowArray.size(),观察数量变化,方便排查问题。
  • 使用迭代器遍历:如果倒序遍历不习惯,也可以用Iterator进行安全遍历删除,比如:
    Iterator<Bubbles> bubbleIter = bubblesArray.iterator();
    while (bubbleIter.hasNext()) {
        Bubbles b = bubbleIter.next();
        // ... 处理逻辑
        if (需要删除) {
            bubbleIter.remove(); // 安全删除,不会导致索引问题
        }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:18:15