石头剪刀布游戏Event Listener问题:PlayerChoice始终返回NULL
石头剪刀布游戏按钮交互问题修复方案
问题核心
使用addEventListener绑定按钮点击事件时,playerChoice始终返回初始值"NULL",无法正确获取玩家选择;虽然HTML中用onclick能勉强运行,但希望通过event listener的方式修复逻辑。
问题原因分析
- 事件绑定时机错误:
getPlayerChoice函数每次被playRound调用时都会重复绑定事件,且绑定后立刻返回playerChoice——此时用户还未点击按钮,变量自然还是初始值"NULL"。 - 逻辑流程冲突:HTML按钮通过
onclick触发playRound,但playRound又调用getPlayerChoice绑定点击事件,导致事件触发逻辑混乱。 - 分数类型错误:从
innerHTML获取的分数是字符串类型,直接执行+1会变成字符串拼接(比如"0"+1变成"01"),而非数值累加。
修复步骤及代码实现
修改后的JavaScript代码
let playerScore = 0 let computerScore = 0 function getRandomInt(min, max) { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min + 1) + min); } function getComputerChoice() { let numChoice = getRandomInt(1,3); let computerChoice = "NULL" if (numChoice == 1) { computerChoice = "ROCK"; } else if (numChoice == 2) { computerChoice = "PAPER"; } else if (numChoice == 3){ computerChoice = "SCISSORS"; } return computerChoice } // 重构playRound,直接接收玩家选择作为参数 function playRound(playerChoice) { // 将分数转换为数字类型,避免字符串拼接错误 let scoreComputer = Number(document.getElementById("computerScore").innerHTML) let scorePlayer = Number(document.getElementById("playerScore").innerHTML) const computerChoice = getComputerChoice() // 胜负判断逻辑 if (computerChoice === "ROCK" && playerChoice === "PAPER") { scorePlayer += 1 } else if (computerChoice === "ROCK" && playerChoice === "SCISSORS") { scoreComputer += 1 } else if (computerChoice === "PAPER" && playerChoice === "SCISSORS") { scorePlayer += 1 } else if (computerChoice === "PAPER" && playerChoice === "ROCK") { scoreComputer += 1 } else if (computerChoice === "SCISSORS" && playerChoice === "PAPER") { scoreComputer += 1 } else if (computerChoice === "SCISSORS" && playerChoice === "ROCK") { scorePlayer += 1 } alert(`你的选择:${playerChoice},电脑选择:${computerChoice}`) // 更新页面分数 document.getElementById("playerScore").innerHTML = scorePlayer document.getElementById("computerScore").innerHTML = scoreComputer // 提前加入先赢5局的逻辑(可根据需求调整) if (scorePlayer === 5) { alert("你赢了整个游戏!") resetGame() } else if (scoreComputer === 5) { alert("电脑赢了整个游戏!") resetGame() } } // 游戏重置函数 function resetGame() { playerScore = 0 computerScore = 0 document.getElementById("playerScore").innerHTML = 0 document.getElementById("computerScore").innerHTML = 0 } // 页面加载完成后一次性绑定事件 document.addEventListener('DOMContentLoaded', function() { document.getElementById("rockButton").addEventListener("click", () => playRound("ROCK")) document.getElementById("scissorsButton").addEventListener("click", () => playRound("SCISSORS")) document.getElementById("paperButton").addEventListener("click", () => playRound("PAPER")) })
修改后的HTML代码(移除冗余属性)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Rock, Paper, Scissors</title> </head> <body> <div> <h1 style="display:flex; justify-content:center">Welcome To Rock, Paper Scissors.</h1> <h3 style="display:flex; justify-content: center;">The directions are simple. You will play against a computer in Rock, Paper, Scissors best out of 5. Choose a weapon from the menu, and hope that luck is on your side!</h3> <h2 style="display: flex; justify-content: center;font-weight: bold;"><br><br>Rock beats Scissors, Scissors beats Paper, Paper beats Rock</h2> </div> <br> <br> <br> <br> <div style="display: flex; justify-content: space-around;"> <button id="rockButton" style="display: flex; flex-direction: column; justify-content: center;"> <img src="./stone.png" alt="image of a rock" height="100px" width="auto"> <p style="margin-left: auto; margin-right: auto">Rock</p> </button> <button id="paperButton" style="display: flex; flex-direction: column; justify-content: center;"> <img src="./paper.png" alt="image of a Paper" height="100px" width="auto"> <p style="margin-left: auto; margin-right: auto">Paper</p> </button> <button id="scissorsButton" style="display: flex; flex-direction: column; justify-content: center;"> <img src="./scissors.png" alt="image of Scisors" height="100px" width="auto"> <p style="margin-left: auto; margin-right: auto">Scissors</p> </button> </div> <div style="display: flex; justify-content: center;"> <div style="display: flex; justify-content: space-around; white-space: nowrap; width: 70%;"> <div style="display: flex; white-space: nowrap;"> <h1><br><br><br>Your Score: <h1 id="playerScore" style="margin-left: 5%; margin-right: 5%;"><br><br><br>0</h1></h1> </div> <div style="display: flex; white-space: nowrap; justify-content: center;"> <h1><br><br><br>Computer's Score: <h1 id="computerScore" style="margin-left: 5%; margin-right: 5%;"><br><br><br>0</h1></h1> </div> </div> </div> <div style="display: flex; justify-content: center;"> <h1 style="font: 40px; display: flex;"><br>Game Result</h1> <h1 id="gameResult"></h1> </div> <script src="./script.js"></script> </body> </html>
关键修复点
- 事件绑定优化:将事件绑定移到
DOMContentLoaded回调中,确保DOM元素加载完成后只绑定一次,避免重复绑定。 - 参数传递替代全局变量:通过箭头函数直接在点击时向
playRound传递玩家选择,彻底解决异步点击导致的变量未更新问题。 - 分数类型修正:使用
Number()将获取的字符串分数转换为数值,保证累加逻辑正确。 - 逻辑解耦:移除HTML中的
onclick属性,统一用JavaScript管理事件绑定,代码逻辑更清晰。
内容的提问来源于stack exchange,提问作者Evan Grosso
相关产品推荐
相关产品推荐

