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

开发JS海战游戏时报Cannot read 'classList' of undefined错误如何解决

错误原因
  • 核心是generate函数中随机起始位置randomStart的计算逻辑错误,会导致索引超出AISquares数组的合法范围(0~99),取到undefined后访问classList属性就抛出了对应错误。具体问题点有2个:
    1. 计算randomStart时错误添加了Math.abs,且没有根据船的当前摆放方向(水平/垂直)限制最大起始值:垂直摆放的船长是船长*10,原代码只减去了水平方向的船长,导致垂直摆放时起始位置过大,randomStart + index超过数组最大索引99。
    2. 方向判断逻辑完全失效:if (current === 0)、if (current === 1)的判断对象current是数组,永远不可能等于数字0/1,这段代码不会生效,后续用到direction变量时会出问题。
修复代码

将原generate函数替换为如下代码即可解决偶发报错问题:

function generate(ship) {
    let randomDirection = Math.floor(Math.random() * ship.directions.length);
    let current = ship.directions[randomDirection];
    const shipLength = ship.directions[0].length;
    // 根据方向计算最大合法起始位置
    let maxStart = randomDirection === 0 ? AISquares.length - shipLength : AISquares.length - shipLength * widthl;
    // 修正随机起始位置计算逻辑,移除多余的Math.abs
    let randomStart = Math.floor(Math.random() * maxStart);

    const isTaken = current.some(index => AISquares[randomStart + index].classList.contains("taken"))
    // 修正边缘判断逻辑:水平方向才需要判断左右边缘,垂直方向不需要
    let isAtRightEdge = false, isAtLeftEdge = false;
    if (randomDirection === 0) {
        isAtRightEdge = current.some(index => (randomStart + index) % widthl === widthl - 1 )
        isAtLeftEdge = current.some(index => (randomStart + index) % widthl === 0)
    }

    if (!isTaken && !isAtRightEdge && !isAtLeftEdge) {
        current.forEach(index => AISquares[randomStart + index].classList.add("taken", ship.name))
    } else {
        generate(ship)
    }
}
额外优化建议

可以把递归调用改成循环,避免极端情况下递归层数过多导致栈溢出:

function generate(ship) {
    while(true) {
        let randomDirection = Math.floor(Math.random() * ship.directions.length);
        let current = ship.directions[randomDirection];
        const shipLength = ship.directions[0].length;
        let maxStart = randomDirection === 0 ? AISquares.length - shipLength : AISquares.length - shipLength * widthl;
        let randomStart = Math.floor(Math.random() * maxStart);

        const isTaken = current.some(index => AISquares[randomStart + index].classList.contains("taken"))
        let isAtRightEdge = false, isAtLeftEdge = false;
        if (randomDirection === 0) {
            isAtRightEdge = current.some(index => (randomStart + index) % widthl === widthl - 1 )
            isAtLeftEdge = current.some(index => (randomStart + index) % widthl === 0)
        }

        if (!isTaken && !isAtRightEdge && !isAtLeftEdge) {
            current.forEach(index => AISquares[randomStart + index].classList.add("taken", ship.name))
            break;
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 02:39:04