如何修复石头剪刀布游戏中isValid()函数的循环异常问题?
石头剪刀布游戏isValid()函数问题修复
问题描述
开发了一款通过prompt交互的石头剪刀布游戏,其余功能正常,但isValid()函数仅执行一次循环,只有输入R能正常进入游戏,输入P或S会触发无效输入提示。尝试将数组转为字符串输出未解决问题,需分析原因并修复。
原游戏代码
var options = ['R','P','S','r','p','s'] var userRes; var checkVar; var compChoice; var checkStat; var winStat = 0; var lossStat = 0; var tieStat = 0; function isValid() { for (var i = 0; i < options.length; i++) { const found = options[i]; if (userRes === found) { return checkVar = true; } else if (userRes !== found) { return checkVar = false; } } } function getCompChoice() { let compSet = options[Math.floor(Math.random() * options.length)]; compChoice = compSet.toUpperCase(); console.log(compChoice) return alert('The computer chose ' + compChoice); } function getUserChoice () { userSet = prompt('Rock Paper or Scissors?'); if (userSet === null) { return startGame(); } else { userRes = userSet.toUpperCase(); } isValid() if (checkVar === true) { console.log('continue') userRes.toUpperCase(); console.log(userRes); getCompChoice() if((userRes === 'R' && compChoice === 'S') || (userRes === 'P' && compChoice === 'R' || (userRes === 'S' && compChoice === 'P'))) { console.log('win') alert('You Won !') checkStat = true playAgain() } else if (userRes === compChoice) { console.log('tie') alert('You Tied !') checkStat = null playAgain() } else if (userRes !== compChoice) { console.log('loss') alert('You Lost !') checkStat = false playAgain() } } else if (checkVar === false) { console.log('end') console.log(userRes); alert('Please enter R, P, or S. (Not case sensitive).'); getUserChoice(); } } function playAgain() { if (checkStat) { winStat++; alert('Your Stats:\nWins: ' + winStat + '\nLosses: ' + lossStat + '\nTies: ' + tieStat) } else if (checkStat === null){ tieStat++; alert('Your Stats:\nWins: ' + winStat + '\nLosses: ' + lossStat + '\nTies: ' + tieStat) } else if (!checkStat) { lossStat++; alert('Your Stats:\nWins: ' + winStat + '\nLosses: ' + lossStat + '\nTies: ' + tieStat) } pAgain = confirm('Play Again ?') if (pAgain) { getUserChoice(); } } function startGame () { askUser = confirm('Would you like to play a game of Rock, Paper, Scissors ?') if (askUser) { return getUserChoice(); } else if (!askUser) { return alert('Come back next time !') } } startGame();
问题原因
isValid()函数的循环逻辑错误:
- 循环第一次执行时,若用户输入的
userRes不等于数组第一个元素'R',会直接执行return checkVar = false,终止循环,不会检查后续的'P'、'S'等元素。 - 只有当用户输入恰好是
'R'(或'r')时,才会返回true,其他有效输入都会被误判为无效。
修复方案
方案1:修正循环逻辑
修改isValid()函数,先默认设为无效,遍历所有元素找到匹配项后标记为有效,循环结束后返回结果:
function isValid() { checkVar = false; // 默认设为无效 for (var i = 0; i < options.length; i++) { const found = options[i]; if (userRes === found) { checkVar = true; // 找到匹配项,标记为有效 break; // 找到后跳出循环,无需继续遍历 } } return checkVar; }
方案2:使用数组includes()方法简化代码
由于getUserChoice()中已经将userRes转为大写,options数组可以简化为仅存大写字母,再用includes()直接判断是否包含有效输入,代码更简洁:
// 先简化options数组 var options = ['R','P','S']; function isValid() { return checkVar = options.includes(userRes); }
额外优化建议
- 用
let或const替代var声明变量,避免全局变量污染(比如userSet、pAgain、askUser这些变量都没声明,会自动成为全局变量)。 getUserChoice()中userRes.toUpperCase();这行代码多余,因为之前已经执行过userRes = userSet.toUpperCase();,可以删除。
内容的提问来源于stack exchange,提问作者sullivanstresser
相关产品推荐
相关产品推荐

