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

如何在JavaScript石头剪刀布游戏中嵌入函数实现分数追踪及bug修复

石头剪刀布项目问题修复

问题描述

我是JavaScript新手,正在完成The Odin Project的石头剪刀布项目。目前获取用户输入、电脑随机选择的函数,以及无分数的5轮游戏均可正常运行,但添加分数后仅能获取playRound()的最后结果,甚至无法显示游戏结束提示。我认为问题出在函数变量的声明位置(playerSelection = getPlayerChoice(); computerSelection = getComputerChoice())。此外,当在prompt中点击取消时,getPlayerChoice()会出现“无法读取null的toLowerCase属性”错误。我希望保留现有函数结构,理解JS相关概念,实现每轮得分统计及最终胜负判定,同时修复该错误。

原代码

//get input from the player
function getPlayerChoice() {
   let playerInput = prompt("Choose rock, paper or scrissors.");
   let playerChoice = playerInput.toLowerCase();
   if (playerChoice === "rock") {
       playerChoice = "Rock";
 } else if (playerChoice === "paper") {
       playerChoice = "Paper";
 } else if (playerChoice === "scrissors") {
       playerChoice = "Scrissors";
 } else {
     alert("Choose one of these objects");
     getPlayerChoice();
  }
     return playerChoice;
    }

//get random input from the computer
function getComputerChoice() {
  const comChoice = ["Rock", "Paper", "Scrissors"];
  const comResult = Math.floor(Math.random() * comChoice.length);
    return comChoice[comResult];
   }

//play one round using the functions and assign them to two variables 
and checks the winner
function playRound() {
  const playerSelection = getPlayerChoice();
  const computerSelection = getComputerChoice();
  let response = "";
    if (playerSelection === computerSelection) {
        response += "It's a tie";
  } else if ((playerSelection === "Rock" && computerSelection === "Scrissors") ||
             (playerSelection === "Paper" && computerSelection === "Rock") ||
             (playerSelection === "Scrissors" && computerSelection === "Paper")) {
        response += `You win. ${playerSelection} beats ${computerSelection}`;
  } else if ((playerSelection === "Rock" && computerSelection === "Paper") ||
             (playerSelection === "Paper" && computerSelection === "Scrissors") ||
             (playerSelection === "Scrissors" && computerSelection === "Rock")) {
        response += `You lose. ${playerSelection} beats ${computerSelection}`;
      }
      return response;
    }

//playing a game of 5 rounds and get score
function game() {
  let playerScore = 0;
  let computerScore = 0;
  for (let i = 0; i < 5; i++) {
    let playerSelection = getPlayerChoice();
    let computerSelection = getComputerChoice();
    console.log(playRound());
    if (playRound() === `You win. ${playerSelection} beats ${computerSelection}`) {
        playerScore++;
        console.log(`Player score: ${playerScore}`)
      } else if (playRound() === `You lose. ${playerSelection} beats ${computerSelection}`) {
        computerScore++;
        console.log(`Computer score: ${computerScore}`)
    }
      console.log("---------");
   }

    if (playerScore > computerScore) {
       console.log("You win.")
    } else if (playerScore < computerScore) {
       console.log("You lose.")
    } else if (playerScore === computerScore) {
       console.log("Drawn")
    }
     console.log("Game Over")
   }

    game();

修复后的代码

// 获取玩家输入
function getPlayerChoice() {
  let playerInput = prompt("Choose rock, paper or scissors.");
  // 处理取消prompt的情况
  if (playerInput === null) {
    alert("游戏已取消");
    // 终止游戏
    throw new Error("User cancelled the game");
  }
  let playerChoice = playerInput.toLowerCase().trim();
  if (playerChoice === "rock") {
    return "Rock";
  } else if (playerChoice === "paper") {
    return "Paper";
  } else if (playerChoice === "scissors") {
    // 修正拼写错误:scrissors → scissors
    return "Scissors";
  } else {
    alert("请选择rock、paper或scissors中的一个");
    // 递归调用时必须return,否则会返回undefined
    return getPlayerChoice();
  }
}

// 电脑随机选择
function getComputerChoice() {
  const comChoice = ["Rock", "Paper", "Scissors"];
  const comResult = Math.floor(Math.random() * comChoice.length);
  return comChoice[comResult];
}

// 单轮游戏:改为接收玩家和电脑的选择作为参数,避免重复调用输入函数
function playRound(playerSelection, computerSelection) {
  let response = "";
  let result = "tie"; // 新增结果标识,方便统计分数
  if (playerSelection === computerSelection) {
    response = "It's a tie";
  } else if (
    (playerSelection === "Rock" && computerSelection === "Scissors") ||
    (playerSelection === "Paper" && computerSelection === "Rock") ||
    (playerSelection === "Scissors" && computerSelection === "Paper")
  ) {
    response = `You win. ${playerSelection} beats ${computerSelection}`;
    result = "win";
  } else {
    response = `You lose. ${computerSelection} beats ${playerSelection}`;
    // 修正原逻辑错误:原字符串里写的是playerSelection击败电脑选择,实际输局是电脑选择获胜
    result = "lose";
  }
  // 返回包含响应文本和结果的对象,方便分数统计
  return { response, result };
}

// 五轮游戏
function game() {
  let playerScore = 0;
  let computerScore = 0;
  try {
    for (let i = 0; i < 5; i++) {
      console.log(`第 ${i + 1} 轮`);
      // 只调用一次输入函数,获取本轮的选择
      const playerSelection = getPlayerChoice();
      const computerSelection = getComputerChoice();
      // 只调用一次playRound,获取本轮结果
      const roundResult = playRound(playerSelection, computerSelection);
      console.log(roundResult.response);
      // 根据结果统计分数
      if (roundResult.result === "win") {
        playerScore++;
        console.log(`玩家分数: ${playerScore}`);
      } else if (roundResult.result === "lose") {
        computerScore++;
        console.log(`电脑分数: ${computerScore}`);
      }
      console.log("---------");
    }

    // 最终胜负判定
    if (playerScore > computerScore) {
      console.log("你赢下了整个游戏!");
    } else if (playerScore < computerScore) {
      console.log("你输掉了整个游戏!");
    } else {
      console.log("游戏平局!");
    }
    console.log("游戏结束");
  } catch (err) {
    // 捕获用户取消游戏时抛出的错误
    console.log(err.message);
  }
}

game();

关键修复点说明

  1. 修复prompt取消的null错误:在getPlayerChoice开头判断playerInput是否为null,给出提示并抛出错误终止游戏,避免调用toLowerCase时报错。
  2. 修正递归返回问题:原代码递归调用getPlayerChoice()时未return,导致错误输入后函数返回undefined,现在添加return确保递归后能正确返回用户选择。
  3. 解决playRound重复调用问题:原game函数每轮调用3次playRound,每次都会重新触发prompt和电脑选择,导致一轮游戏实际执行3次。现在改为在game中先获取选择,再传递给playRound,仅调用一次playRound得到结果。
  4. 优化分数统计逻辑:让playRound返回包含result(win/lose/tie)的对象,代替原有的精确字符串匹配,逻辑更可靠易维护。
  5. 修正拼写和文本错误:把所有scrissors改为正确的scissors,并修正输局时的文本描述(原文本错误地写玩家选择击败电脑选择,实际是电脑选择获胜)。
  6. 添加错误捕获:用try/catch捕获用户取消游戏时抛出的错误,避免程序崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 00:54:55