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

