Odin Project控制台石头剪刀布游戏问题求助及代码优化建议
问题分析与优化建议
我是一名JavaScript初学者,在完成Odin Project的控制台石头剪刀布游戏时遇到问题:目前游戏可运行多轮,但每轮不会重新调用玩家选择函数,始终使用首次选择;最后一行还出现未定义变量问题,无法自行排查。
原代码
// get computer choice function getComputerChoice() { let choices = ["rock", "paper", "scissors"]; let computerChoice = choices.at(Math.floor(Math.random() * choices.length)); return computerChoice; } // get player choice function getPlayerChoice() { let playerInput = prompt("type your choice..."); let result = playerInput.toLowerCase(); return result; } // play one round and save the score function playRound(playerSelection, computerSelection) { if (playerSelection === computerSelection) { return "it's a tie replay this round"; } else if (playerSelection === "rock" && computerSelection === "paper") { return `You lose! paper beats rock`; } else if (playerSelection === "rock" && computerSelection === "scissors") { return `You win! rock beats scissors`; } else if (playerSelection === "paper" && computerSelection === "scissors") { return `You lose!scissors beats paper`; } else if (playerSelection === "paper" && computerSelection === "rock") { return `You win! paper beats rock`; } else if (playerSelection === "scissors" && computerSelection === "rock") { return `You lose! rock beats scissors`; } else if (playerSelection === "scissors" && computerSelection === "paper") { return `You win! scissors beats paper`; } } const playerSelection = getPlayerChoice(); const computerSelection = getComputerChoice(); console.log(playRound(playerSelection, computerSelection)); function game() { let computerScore = 0, playerScore = 0; for (i = 0; i < 3; i++) { const result = playRound(playerSelection, computerSelection); if (result.includes("win")) { playerScore++; console.log(`computer: ${computerScore} | player: ${playerScore}`); } else if (result.includes("lose")) { computerScore++; console.log(`computer: ${computerScore} | player: ${playerScore}`); } console.log( "Final Results: Player: " + playerScore + " Computer: " + computerScore ); if (playerScore > computerScore) { console.log("You win the game!"); } else if (playerScore < computerScore) { console.log("You lose the game."); } else { console.log("The game was an overall tie."); } } } game();
问题分析
每轮选择不更新:
全局作用域中定义的playerSelection和computerSelection只执行了一次获取逻辑,循环内反复使用的是首次生成的值,不会重新调用函数获取新选择。未定义变量问题:
循环变量i未用let/const声明,会自动成为全局变量,在严格模式下会直接抛出未定义错误。结果判断时机错误:
将整场游戏的最终结果判断放在了单轮循环内部,导致每轮结束都打印一次最终结果,逻辑不符合预期。
优化后的代码
// 获取电脑选择 function getComputerChoice() { const choices = ["rock", "paper", "scissors"]; return choices[Math.floor(Math.random() * choices.length)]; } // 获取玩家选择,增加输入合法性验证 function getPlayerChoice() { let playerInput; do { playerInput = prompt("请输入你的选择:rock/paper/scissors").toLowerCase(); } while (!["rock", "paper", "scissors"].includes(playerInput)); return playerInput; } // 单轮游戏逻辑,返回结构化结果便于计分 function playRound(playerSelection, computerSelection) { if (playerSelection === computerSelection) { return { type: "tie", message: `平局!双方都选了${playerSelection}` }; } // 用对象存储获胜规则,简化判断逻辑 const winRules = { rock: "scissors", paper: "rock", scissors: "paper" }; if (winRules[playerSelection] === computerSelection) { return { type: "win", message: `你赢了!${playerSelection}击败${computerSelection}` }; } else { return { type: "lose", message: `你输了!${computerSelection}击败${playerSelection}` }; } } function game() { let computerScore = 0, playerScore = 0; const totalRounds = 3; for (let i = 0; i < totalRounds; i++) { console.log(`=== 第 ${i + 1} 轮 ===`); // 每轮重新获取玩家和电脑选择 const playerSelection = getPlayerChoice(); const computerSelection = getComputerChoice(); const roundResult = playRound(playerSelection, computerSelection); console.log(roundResult.message); // 根据结果类型更新分数 switch(roundResult.type) { case "win": playerScore++; break; case "lose": computerScore++; break; } // 打印当前比分 console.log(`当前比分:玩家 ${playerScore} | 电脑 ${computerScore}\n`); } // 所有轮次结束后,打印最终结果 console.log("=== 游戏结束 ==="); console.log(`最终比分:玩家 ${playerScore} | 电脑 ${computerScore}`); if (playerScore > computerScore) { console.log("你赢得了整场游戏!"); } else if (playerScore < computerScore) { console.log("你输掉了整场游戏!"); } else { console.log("整场游戏平局!"); } } game();
优化说明
- 每轮刷新选择:将选择获取逻辑移到循环内部,确保每轮都调用函数生成新的玩家输入和电脑随机值。
- 修复变量声明问题:用
let声明循环变量i,避免污染全局作用域。 - 增加输入验证:通过循环确保玩家输入有效的选项,避免非法输入导致逻辑出错。
- 简化判断逻辑:用对象存储获胜规则,替代冗余的
else if判断,代码更易维护。 - 调整结果输出时机:将最终游戏结果判断放在循环结束后,符合正常游戏流程的预期。
内容的提问来源于stack exchange,提问作者Mohammed-Abol-Fotouh
相关产品推荐
相关产品推荐

