当我在代码中遇到一个错误时,我正在制作我的第一个 HTML/CSS/JS 项目,该错误涉及重置游戏后重新使用玩家输入的功能。
const greenO = "https://www.freeiconspng.com/uploads/green-circle-png-10.png"
const redX = "https://pnghq.com/wp-content/uploads/pnghq.com-download-red-cross-mark-download-png-hq-png-image.png"
const slots = document.getElementsByClassName("slots")
const slotImages = document.getElementsByClassName("slot-images")
let playerClickAvailable = true
let computerMoveAvailable = false
for (let i = 0; i <= 8; i++) {
slots[i].addEventListener("click", function() {
playerClick(i)
})
}
function playerClick(i) {
console.log("playerClick fired with (" + i + ")")
console.log("player move available: " + playerClickAvailable)
console.log("computer move available: " + computerMoveAvailable)
console.log("playerClick fired in slot with img.src " + slotImages[i].src)
console.log("playerClick fired in slot with img.style.display " + slotImages[i].style.display)
if (playerClickAvailable) {
const img = slotImages[i]
if (img.src === "") {
img.src = greenO
img.style.display = "block"
playerClickAvailable = false
computerMoveAvailable = true
if (checkWin() === undefined) {
setTimeout(computerMove, 750);
}
}
}
}
function computerMove() {
console.log("player move available: " + playerClickAvailable)
console.log("computer move available: " + computerMoveAvailable)
if (computerMoveAvailable) {
let img = undefined
let occupiedCount = 0
for (let i = 0; i <= 8; i++) {
if (slotImages[i].src === "") {
console.log("breaked after " + (i + 1) + " iteration(s)")
break
} else {
occupiedCount += 1
}
}
if (occupiedCount === 9) {
console.log("tie")
document.getElementById("reset").style.display = "block"
return
}
while (true) {
const i = Math.floor(Math.random() * 9)
img = slotImages[i]
if (img.src == "") {
break
}
}
img.src = redX
img.style.display = "block"
playerClickAvailable = true
computerMoveAvailable = false
checkWin()
}
}
function giveWin(slot) {
function blockMoves() {
playerClickAvailable = false
computerMoveAvailable = false
}
const reset = document.getElementById("reset")
if (slot === greenO) {
console.log("player won")
reset.style.display = "block"
blockMoves()
return "player"
} else if (slot === redX) {
console.log("computer won")
reset.style.display = "block"
blockMoves()
return "computer"
}
}
function checkWin() {
const first = slotImages[0].src
const second = slotImages[1].src
const third = slotImages[2].src
const fourth = slotImages[3].src
const fifth = slotImages[4].src
const sixth = slotImages[5].src
const seventh = slotImages[6].src
const eighth = slotImages[7].src
const ninth = slotImages[8].src
if (
(first === second && first === third) ||
(first === fourth && first === seventh) ||
(first === fifth && first === ninth)
) {
giveWin(first)
} else if (
second === fifth && second === eighth
) {
giveWin(second)
} else if (
(third === sixth && third === ninth) ||
(third === fifth && third === seventh)
) {
giveWin(third)
} else if (
fourth === fifth && fourth === sixth
) {
giveWin(fourth)
} else if (
seventh === eighth && seventh === ninth
) {
giveWin(seventh)
}
}
function reset() {
for (let i = 0; i <= 8; i++) {
const img = slotImages[i]
img.src = ""
img.style.display = "none"
}
document.getElementById("reset").style.display = "none"
playerClickAvailable = true
computerMoveAvailable = false
console.log("reseted")
}
body {
min-height: 800;
min-width: 800;
}
.center-flex {
display: flex;
justify-content: center;
}
#main-container {
width: 600px;
height: 600px;
display: grid;
grid-template: repeat(3, 1fr) / repeat(3, 1fr);
gap: 15px;
margin-bottom: 100px;
}
.slots {
display: flex;
justify-content: center;
align-items: center;
border-radius: 10%;
padding: 15px;
border: 10px solid rgb(71, 71, 71);
background-color: cadetblue;
}
.slot-images {
width: 100%;
height: 100%;
display: none;
}
#reset {
width: 200px;
height: 75px;
display: none;
border: 3px solid black;
font-size: 50px;
border-radius: 15px;
}
#reset-container {
display: flex;
justify-content: center;
}
#game-container {
display: flex;
justify-content: center;
align-items: center;
}
<div id="game-container">
<div id="main-container">
<button class="slots"><img class="slot-images"></button>
<button class="slots"><img class="slot-images"></button>
<button class="slots"><img class="slot-images"></button>
<button class="slots"><img class="slot-images"></button>
<button class="slots"><img class="slot-images"></button>
<button class="slots"><img class="slot-images"></button>
<button class="slots"><img class="slot-images"></button>
<button class="slots"><img class="slot-images"></button>
<button class="slots"><img class="slot-images"></button>
</div>
</div>
<div id="reset-container">
<button id="reset" onclick="reset()">Reset!</button>
</div>
我已经放置了许多console.log()语句来调试,一切似乎都是正确的,但是在reset()函数运行之后,当玩家点击时,img.src和img.style.display不会更新,并且所有过去的东西都会中断。
我尝试更新和预设值以查看是否有任何更改,但它不起作用,我可以修复它的唯一方法是这样做:
location.reload()
在reset()函数的末尾。 但我知道这是一个糟糕的方法,将来我想制作一个记分板等等......
游戏重置后失败:
if (img.src === "")
因为这有一个你意想不到的副作用:
img.src = ""
当设置为这样的空字符串时,生成的 DOM 元素是:
<img src class="slot-images">
或者也许:
<img src="" class="slot-images">
浏览器会尽其所能悄悄地“更正”HTML,如果某个属性需要 URL,则“更正”会尝试推断有关该 URL 的信息。 例如,这允许存在相对路径。 它对 blank URL 的推断是使用 当前页面的 URL。
因此,重置后,任何时候您将空
src
与""
进行比较都会失败,因为“空src
”实际上是当前页面的URL,而不是空字符串。
按照与图像文件相同的模式,将另一个图像添加到某些默认图像中。 例如:
const empty = "https://i.sstatic.net/mwFzF.png";
将所有图像初始化为:
<img src="https://i.sstatic.net/mwFzF.png" class="slot-images">
并在整个逻辑中使用该值。 比如重置游戏时:
img.src = empty
并且在比较确定移动的值时:
if (img.src === empty)