You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

石头剪刀布游戏分数追踪器异常:点击按钮分数随机变动

石头剪刀布游戏分数异常问题修复

问题描述

我正在开发一款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>

修复说明

  1. 移除重复事件绑定:删除外层的for循环,每个按钮只绑定一次点击事件,确保每次点击只执行一次游戏逻辑。
  2. 新增回合计数:用currentRound变量追踪当前回合数,达到5回合后禁用按钮,结束游戏。
  3. 保存单次回合结果:将winner()的结果保存到currentResult变量,避免重复调用函数,同时让分数更新逻辑更清晰。
  4. 优化分数更新函数:直接使用currentResult来更新分数,减少冗余计算。

内容的提问来源于stack exchange,提问作者Jose Velasco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 00:41:14