我遵循了一个用javascript和html制作BattleShip的教程,但是我得到一个错误:
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天了,我不明白如何修复这个错误。我希望有人能尽快找到解决方案。
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)
})
.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;
}
<!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>
发布于 2021-09-19 12:31:56
问题是,在isTaken
中,来自random start + index
的数字太大了,超出了AISquares
的处理能力,因为它只包含100个值/索引,您可能会传入一个> 100的数字,因此它会返回未定义的值并崩溃。由于它是一个随机数生成器,它有时不会超过100,并且它可以工作,反之亦然。
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
在其他地方使用,所以我怀疑这是一个问题吗?还有一个问题是:
//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
}
上述情况成立的原因:
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
=
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
,因为它总是设置为0
或1
。
最后:
//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()
:
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)
}
https://stackoverflow.com/questions/69122540
复制相似问题