admin管理员组文章数量:1389812
I'm following a tutorial for making BattleShip in javascript and html but i get an error :
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)
This is the tutorial: The error happens randomly sometimes, it's been 5 days since this error occured and I can't understand how to fix this. I hope that someone can find a solution soon.
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>
I'm following a tutorial for making BattleShip in javascript and html but i get an error :
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)
This is the tutorial: https://youtu.be/U64vIhh0TyM The error happens randomly sometimes, it's been 5 days since this error occured and I can't understand how to fix this. I hope that someone can find a solution soon.
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>
Share
Improve this question
edited Sep 19, 2021 at 10:24
FedFer
asked Sep 9, 2021 at 17:34
FedFerFedFer
131 gold badge1 silver badge4 bronze badges
6
- I'd love to help out. Is this all this right here all the code I need? – Machine Herald Commented Sep 10, 2021 at 22:02
- this is all the code i've wrote for now, i'm trying to go on with the tutorial but this bug keep occuring sometimes and it's really annoying because then all the rest of the code stop working and i can't figure out how to fix this. I hope you can help me fix this bug – FedFer Commented Sep 12, 2021 at 17:53
- OK, I'll take a look at it. – Machine Herald Commented Sep 13, 2021 at 7:39
- So sorry mate, I was a bit busy with some personal work. Is that all the code? I'm missing a css file. If I could just get all the updated code, I could tinker with it and see what's wrong a lot faster. – Machine Herald Commented Sep 18, 2021 at 11:47
- 1 I've uploaded the css code, I hope you will find an answer to my problem. – FedFer Commented Sep 19, 2021 at 10:25
1 Answer
Reset to default 2The issue is that within isTaken
the number from random start + index
is simply too high of a number than what AISquares
can handle since it only contains 100 values/indexes, you're potentially passing in a number > 100 and therefore it's returning undefined and crashing. Since it's a random number generator, it'll sometimes not go over 100 and it works, vice versa.
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)
}
Also, I noticed some other things-- direction
variable is never declared anywhere, so you're hoisting it IF it passes those conditions, but if it never passes those conditions it just never exists. However, I don't see direction
used anywhere else, so I doubt this is an issue? There's also the issue of:
//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
}
Reason why the above is true:
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
evaluates to an array because ship.directions
=
directions: [
[0, 1, 2, 3, 4],
[0, widthl, widthl*2, widthl*3, widthl*4]
]
And random direction
is either 1 or 0, so it's always accessing either ship.directions[0]
or ship.directions[1]
.
Perhaps you meant to use randomDirection
not current
in the conditional check, since the logic checks for 0 or 1, it would make sense randomDirection
should be used it since it's the one always set to 0
or 1
.
Lastly:
//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"))
The condition of the square having taken will be random so it could be an index that's fairly high so more often than not you'll be adding numbers like this (67 + 66)
and thereby attemping to access an index that doesn't exist in the AISquares
array and causing the script to err because classlist attempts to access a property that doesn't exist. Maybe there's something else I'm missing, but resolving these issues will make your program work.
edit generate()
like this:
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)
}
本文标签: javascriptCannot read properties of undefined (reading 39classList39)Stack Overflow
版权声明:本文标题:javascript - Cannot read properties of undefined (reading 'classList') - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744740069a2622555.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论