首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >无法读取未定义的属性(读取“”classList“”)

无法读取未定义的属性(读取“”classList“”)
EN

Stack Overflow用户
提问于 2021-09-09 17:34:44
回答 1查看 4.8K关注 0票数 1

我遵循了一个用javascript和html制作BattleShip的教程,但是我得到一个错误:

代码语言:javascript
运行
复制
    Uncaught TypeError: Cannot read properties of undefined (reading 'classList')
at Script.js:82
at Array.some (<anonymous>)
at generate (Script.js:82)
at HTMLDocument.<anonymous> (Script.js:94)

这是教程:https://youtu.be/U64vIhh0TyM这个错误有时是随机发生的,自从这个错误发生已经5天了,我不明白如何修复这个错误。我希望有人能尽快找到解决方案。

代码语言:javascript
运行
复制
document.addEventListener("DOMContentLoaded", () =>{
    const userGrid = document.querySelector(".user-grid")
    const AIGrid = document.querySelector(".AI-grid")
    const displayGrid = document.querySelector(".grid-display")
    const ships = document.querySelectorAll(".ship")
    const destroyer = document.querySelector(".destroyer-container")
    const submarine = document.querySelector(".submarine-container")
    const battleship = document.querySelector(".battleship-container")
    const carrier = document.querySelector(".carrier-container")
    const startButton = document.querySelector("#start")
    const rotateButton = document.querySelector("#rotate")
    const turnDisplay = document.querySelector("#whose-go")
    const infoDisplay = document.querySelector("#info")
    let isHorizontal = true
    
    const userSquares = []
    const AISquares = []
    const widthl = 10;

    function createBoard(grid, squares, width) {
        for (let i = 0; i < width*width; i++) {
            const square = document.createElement("div")
            square.dataset.id = i
            grid.appendChild(square)
            squares.push(square)
        }
    }

    createBoard(userGrid, userSquares, widthl)
    createBoard(AIGrid, AISquares, widthl)

    const shipArray = [
        {
            name: "destroyer",
            directions: [
                [0, 1],
                [0, widthl]
            ]
        },
        {
            name: "submarine",
            directions: [
                [0, 1, 2],
                [0, widthl, widthl*2]
            ]
        },
        {
            name: "cruiser",
            directions: [
                [0, 1, 2],
                [0, widthl, widthl*2]
            ]
        },
        {
            name: "battleship",
            directions: [
                [0, 1, 2, 3],
                [0, widthl, widthl*2, widthl*3]
            ]
        },
        {
            name: "carrier",
            directions: [
                [0, 1, 2, 3, 4],
                [0, widthl, widthl*2, widthl*3, widthl*4]
            ]
        }
    ];

    function generate(ship) {
        let randomDirection = Math.abs(Math.floor(Math.random() * ship.directions.length));
        let current = ship.directions[randomDirection];
        if (current === 0) {
            direction = 1
        }
        if (current === 1) {
            direction = 10
        }
        let randomStart = Math.abs(Math.floor(Math.random() * AISquares.length - ship.directions[0].length));

        
        const isTaken = current.some(index => AISquares[randomStart + index].classList.contains("taken"))
        const isAtRightEdge = current.some(index => (randomStart + index) % widthl === widthl - 1 )
        const 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)

    }

    generate(shipArray[0])
    generate(shipArray[1])
    generate(shipArray[2])
    generate(shipArray[3])
    generate(shipArray[4])

    function rotate() {
        if (isHorizontal) {
            destroyer.classList.toggle("destroyer-container-vertical")
            isHorizontal = false
        }
    }
    rotateButton.addEventListener("click", rotate)
})
代码语言:javascript
运行
复制
.container{
    display: flex;
}


.user-grid{
    width: 400px;
    height: 400px;
    display: flex;
    flex-wrap: wrap;
    background-color: blue;
    margin: 20px;
}

.grid div{
    width: 40px;
    height: 40px;
}

.AI-grid{
    width: 400px;
    height: 400px;
    display: flex;
    flex-wrap: wrap;
    background-color:green;
    margin: 20px;
}

.grid-display{
    width: 400px;
    height: 400px;
    margin: 20px;
    background-color:yellow;
}

.destroyer-container{
    width: 80px;
    height: 40px;
    background-color: orange;
    margin: 10px;
    display: flex;
}

.destroyer-container-vertical{
    width: 40px;
    height: 80px;
    background-color: orange;
    margin: 10px;
    display: flex;
    flex-wrap: wrap;
}

.submarine-container{
    width: 120px;
    height: 40px;
    background-color: pink;
    margin: 10px;
    display: flex;
}

.submarine-container-vertical{
    width: 40px;
    height: 120px;
    background-color: pink;
    margin: 10px;
    display: flex;
    flex-wrap: wrap;
}

.cruiser-container{
    width: 120px;
    height: 40px;
    background-color: purple;
    margin: 10px;
    display: flex;
}

.cruiser-container-vertical{
    width: 40px;
    height: 120px;
    background-color: purple;
    margin: 10px;
    display: flex;
    flex-wrap: wrap;
}

.battleship-container{
    width: 160px;
    height: 40px;
    background-color: aqua;
    margin: 10px;
    display: flex;
}

.battleship-container-vertical{
    width: 40px;
    height: 160px;
    background-color: aqua;
    margin: 10px;
    display: flex;
    flex-wrap: wrap;
}

.carrier-container{
    width: 200px;
    height: 40px;
    background-color: springgreen;
    margin: 10px;
    display: flex;
}

.carrier-container-vertical{
    width: 40px;
    height: 200px;
    background-color: springgreen;
    margin: 10px;
    display: flex;
    flex-wrap: wrap;
}

.ship div{
    width: 40px;
    height: 40px;
}

.destroyer{
    background-color: orange;
}

.submarine{
    background-color: pink;
}

.cruiser{
    background-color: purple;
}

.battleship{
    background-color:aqua;
}

.carrier{
    background-color:springgreen;
}
代码语言:javascript
运行
复制
<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="utf-8">
        <title> Battle Ships </title>
        <link rel="stylesheet" href="Style.css">
        <script src="Script.js" charset="utf-8"></script>
    </head>

    <body>

        <div class="container">
            <div class="grid user-grid"></div>
            <div class="grid AI-grid"></div>
        </div>

        <div class="hidden-info">
            <button id="start">Start Game</button>
            <button id="rotate">Rotate Your Ships</button>
            <h3 id="whose-go">Your go</h3>
            <h3 id="info"></h3>
        </div>
        
        <div class="grid-display">
            <div class="ship destroyer-container" draggable="true">
                <div class="destroyer-0"></div>
                <div class="destroyer-1"></div>
            </div>
            <div class="ship submarine-container" draggable="true">
                <div class="submarine-0"></div>
                <div class="submarine-1"></div>
                <div class="submarine-2"></div>
            </div>
            <div class="ship cruiser-container" draggable="true">
                <div class="cruiser-0"></div>
                <div class="cruiser-1"></div>
                <div class="cruiser-2"></div>
            </div>
            <div class="ship battleship-container" draggable="true">
                <div class="battleship-0"></div>
                <div class="battleship-1"></div>
                <div class="battleship-2"></div>
                <div class="battleship-3"></div>
            </div>
            <div class="ship carrier-container" draggable="true">
                <div class="carrier-0"></div>
                <div class="carrier-1"></div>
                <div class="carrier-2"></div>
                <div class="carrier-3"></div>
                <div class="carrier-4"></div>
            </div>
        </div>

    </body>

</html>

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-09-19 12:31:56

问题是,在isTaken中,来自random start + index的数字太大了,超出了AISquares的处理能力,因为它只包含100个值/索引,您可能会传入一个> 100的数字,因此它会返回未定义的值并崩溃。由于它是一个随机数生成器,它有时不会超过100,并且它可以工作,反之亦然。

代码语言:javascript
运行
复制
function generate(ship) {
    let randomDirection = Math.abs(Math.floor(Math.random() * ship.directions.length));
    let current = ship.directions[randomDirection];
    if (current === 0) {
        direction = 1
    }
    if (current === 1) {
        direction = 10
    }
    let randomStart = Math.abs(Math.floor(Math.random() * AISquares.length - ship.directions[0].length));

    
    const isTaken = current.some(index => AISquares[randomStart + index].classList.contains("taken"))
    const isAtRightEdge = current.some(index => (randomStart + index) % widthl === widthl - 1 )
    const 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)

}

此外,我还注意到了其他一些事情-- direction变量从未在任何地方声明过,所以如果它通过了这些条件,就会提升它,但是如果它从未通过这些条件,那么它就永远不会存在。然而,我没有看到direction在其他地方使用,所以我怀疑这是一个问题吗?还有一个问题是:

代码语言:javascript
运行
复制
//both of the below conditions will never evaluate, so direction will never be
//hoisted, thus never exist
if (current === 0) {
    direction = 1
}
if (current === 1) {
    direction = 10
}

上述情况成立的原因:

代码语言:javascript
运行
复制
const shipArray = [
    {
        name: "destroyer",
        directions: [
            [0, 1],
            [0, widthl]
        ]
    },
    {
        name: "submarine",
        directions: [
            [0, 1, 2],
            [0, widthl, widthl*2]
        ]
    },
    {
        name: "cruiser",
        directions: [
            [0, 1, 2],
            [0, widthl, widthl*2]
        ]
    },
    {
        name: "battleship",
        directions: [
            [0, 1, 2, 3],
            [0, widthl, widthl*2, widthl*3]
        ]
    },
    {
        name: "carrier",
        directions: [
            [0, 1, 2, 3, 4],
            [0, widthl, widthl*2, widthl*3, widthl*4]
        ]
    }
];
let current = ship.directions[randomDirection];

Current的计算结果为数组,因为ship.directions =

代码语言:javascript
运行
复制
directions: [
                [0, 1, 2, 3, 4],
                [0, widthl, widthl*2, widthl*3, widthl*4]
            ]

random direction不是1就是0,所以它总是访问ship.directions[0]ship.directions[1]

也许你的意思是在条件检查中使用randomDirection而不是current,因为逻辑检查0或1,所以应该使用randomDirection,因为它总是设置为01

最后:

代码语言:javascript
运行
复制
//this needs to be limited
let randomStart = Math.abs(Math.floor(Math.random() * AISquares.length - ship.directions[0].length));

const isTaken = current.some(index => AISquares[randomStart + index].classList.contains("taken"))

平方的条件将是随机的,所以它可能是一个相当高的索引,所以您经常会添加像这样的数字,从而尝试访问AISquares数组中不存在的索引,并导致脚本出错,因为(67 + 66)试图访问不存在的属性。也许我还遗漏了一些东西,但解决这些问题会让你的程序正常工作。

按如下方式编辑generate()

代码语言:javascript
运行
复制
  function generate(ship) {
    let randomDirection = Math.abs(Math.floor(Math.random() * ship.directions.length));
    let current = ship.directions[randomDirection];

    if (randomDirection === 0) {
        direction = 1
    }
    if (randomDirection === 1) {
        direction = 10
    }

    let randomStart = Math.abs(Math.floor(Math.random() * AISquares.length - (ship.directions[0].length * direction)));
    
    const isTaken = current.some(index => AISquares[randomStart + index].classList.contains("taken"))
    const isAtRightEdge = current.some(index => (randomStart + index) % widthl === widthl - 1 )
    const 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)
 }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69122540

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档