石头剪刀布游戏分数追踪器异常:点击按钮分数随机变动
石头剪刀布游戏分数异常问题修复
问题描述
我正在开发一款5回合制石头剪刀布游戏,期望每回合结束后更新分数。但出现异常:每次点击选择按钮时,分数会随机变动。刷新页面后,首次点击显示电脑获胜,本该电脑得1分、其余得0分,但分数却随机变化。
原代码
JavaScript代码
let player; let computer; let result; let playerScore = 0; let computerScore = 0; let tieScore = 0; const playerText = document.querySelector("#playerText"); const computerText = document.querySelector("#computerText"); const resultText = document.querySelector("#resultText"); const choiceBtns = document.querySelectorAll(".choiceBtns"); const playerScoreText = document.querySelector(".playerScoreText"); const computerScoreText = document.querySelector(".computerScoreText"); const tieScoreText = document.querySelector(".tieScoreText"); for (let i = 0; i < 5; i++) { choiceBtns.forEach((button) => button.addEventListener("click", () => { player = button.textContent; computerChoice(); playerText.textContent = `Player: ${player}`; computerText.textContent = `Computer: ${computer}`; resultText.textContent = winner(); scoreTracker(); playerScoreText.textContent = `Player Score: ${playerScore}`; computerScoreText.textContent = `Computer Score: ${computerScore}`; tieScoreText.textContent = `Tie Score: ${tieScore}`; }) ); } function computerChoice() { const randNum = Math.floor(Math.random() * 3) + 1; switch (randNum) { case 1: computer = "Rock"; break; case 2: computer = "Paper"; break; case 3: computer = "Scissors"; break; } } function winner() { if (player == computer) { return "Tie!"; } else if ( (player == "Rock" && computer == "Scissors") || (player == "Paper" && computer == "Rock") || (player == "Scissors" && computer == "Paper") ) { return "Player Wins!"; } else { return "Computer Wins!"; } } function scoreTracker() { if (winner() === "Tie!") { tieScore += 1; } else if (winner() === "Player Wins!") { playerScore += 1; } else if (winner() === "Computer Wins!") { computerScore += 1; } }
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>Document</title> <link rel="stylesheet" href="style.css" /> </head> <body> <div class="container"> <h1 class="gameText" id="playerText">Player:</h1> <h1 class="gameText" id="computerText">Computer:</h1> <h1 class="gameText" id="resultText">Result:</h1> <button class="choiceBtns">Rock</button> <button class="choiceBtns">Paper</button> <button class="choiceBtns">Scissors</button> <h3 class="playerScoreText">Player Score:</h3> <h3 class="computerScoreText">Computer Score:</h3> <h3 class="tieScoreText">Tie</h3> </div> <script src="script.js"></script> </body> </html>
问题原因
- 重复绑定点击事件:外层的
for循环执行了5次,每次都给所有按钮绑定一次点击事件,最终每个按钮绑定了5个点击事件。每次点击按钮时,会触发5次游戏逻辑:每次触发都会重新生成电脑选择、重新判断胜负、累加分数,导致分数随机跳变且多倍增加。 - 冗余的胜负判断:
scoreTracker()中重复调用winner(),虽然这不会直接导致随机问题,但重复绑定事件已经让每一次点击的结果不可控。
修复后的代码
JavaScript代码
let player; let computer; let currentResult; let playerScore = 0; let computerScore = 0; let tieScore = 0; let currentRound = 0; // 新增回合计数 const playerText = document.querySelector("#playerText"); const computerText = document.querySelector("#computerText"); const resultText = document.querySelector("#resultText"); const choiceBtns = document.querySelectorAll(".choiceBtns"); const playerScoreText = document.querySelector(".playerScoreText"); const computerScoreText = document.querySelector(".computerScoreText"); const tieScoreText = document.querySelector(".tieScoreText"); // 只绑定一次点击事件,移除外层for循环 choiceBtns.forEach((button) => button.addEventListener("click", () => { if (currentRound >= 5) return; // 达到5回合后不再响应点击 player = button.textContent; computerChoice(); currentResult = winner(); // 保存单次回合的结果,避免重复计算 // 更新界面文本 playerText.textContent = `Player: ${player}`; computerText.textContent = `Computer: ${computer}`; resultText.textContent = currentResult; // 更新分数 updateScore(); // 更新分数显示 playerScoreText.textContent = `Player Score: ${playerScore}`; computerScoreText.textContent = `Computer Score: ${computerScore}`; tieScoreText.textContent = `Tie Score: ${tieScore}`; currentRound++; // 5回合结束后禁用按钮 if (currentRound === 5) { choiceBtns.forEach(btn => btn.disabled = true); resultText.textContent += " | 游戏结束!"; } }) ); function computerChoice() { const randNum = Math.floor(Math.random() * 3) + 1; switch (randNum) { case 1: computer = "Rock"; break; case 2: computer = "Paper"; break; case 3: computer = "Scissors"; break; } } function winner() { if (player == computer) { return "Tie!"; } else if ( (player == "Rock" && computer == "Scissors") || (player == "Paper" && computer == "Rock") || (player == "Scissors" && computer == "Paper") ) { return "Player Wins!"; } else { return "Computer Wins!"; } } // 优化分数更新逻辑,直接使用已保存的currentResult function updateScore() { switch(currentResult) { case "Tie!": tieScore++; break; case "Player Wins!": playerScore++; break; case "Computer Wins!": computerScore++; break; } }
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>石头剪刀布</title> <link rel="stylesheet" href="style.css" /> </head> <body> <div class="container"> <h1 class="gameText" id="playerText">Player:</h1> <h1 class="gameText" id="computerText">Computer:</h1> <h1 class="gameText" id="resultText">Result:</h1> <button class="choiceBtns">Rock</button> <button class="choiceBtns">Paper</button> <button class="choiceBtns">Scissors</button> <h3 class="playerScoreText">Player Score: 0</h3> <h3 class="computerScoreText">Computer Score: 0</h3> <h3 class="tieScoreText">Tie Score: 0</h3> </div> <script src="script.js"></script> </body> </html>
修复说明
- 移除重复事件绑定:删除外层的
for循环,每个按钮只绑定一次点击事件,确保每次点击只执行一次游戏逻辑。 - 新增回合计数:用
currentRound变量追踪当前回合数,达到5回合后禁用按钮,结束游戏。 - 保存单次回合结果:将
winner()的结果保存到currentResult变量,避免重复调用函数,同时让分数更新逻辑更清晰。 - 优化分数更新函数:直接使用
currentResult来更新分数,减少冗余计算。
内容的提问来源于stack exchange,提问作者Jose Velasco
相关产品推荐
相关产品推荐

