JS猜数字游戏合法范围猜测被误判越界问题排查
Higher Lower猜数字游戏范围校验误触发问题修复
问题复现
开发Higher Lower猜数字小游戏过程中,猜测值条件校验模块出现异常:完成首次猜测操作后,部分实际处于设定合法数值区间内的猜测值,会错误触发That number is not in range, try again.弹窗告警,初步排查条件判断语句未发现明显逻辑疏漏。
附原始实现代码
index.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>Higher Lower</title> </head> <body> <h1>Higher - Lower</h1> <button onclick="userInput()">Input Maximum Number</button> <!--higherLower Function--> <p>Your Guess:</p> <input type="text" onfocus="this.value=''" id="choice" /><br /><br /> <button onclick="higherLower()">Guess</button> <p id="result"></p> </body> <script src="scripts.js"></script> </html>
scripts.js
let userMax; let randomNumber; let tries = 0; const track = []; function userInput() { userMax = prompt("Please enter a maximum number:"); while (userMax < 1 || isNaN(userMax)) { alert("Maximum number cannot be negative, zero, or non-numbers"); userMax = userInput(); } // Generates random number randomNumber = Math.floor(Math.random() * Number(userMax)) + 1; return userMax; } function isFloat(userMax) { return Number(userMax) === n && n % 1 !== 0; } function higherLower(choice) { window.alert(randomNumber); // Declares user guess variable var guess=document.getElementById('choice').value; // User guess conditional validation if (isNaN(guess)) { alert("That is not a number!"); } else if(guess < 1 || guess > userMax) { alert("That number is not in range, try again."); } // Declares random number variable if(randomNumber==guess) { document.getElementById("result").innerHTML = "You got it! It took you " + tries + " tries and your guesses were "; // Generates new random number after win randomNumber=Math.floor(Math.random() * Number(userMax)) + 1; } else if(randomNumber>=guess) { document.getElementById("result").innerHTML = "No, try a higher number."; tries++; } else if(randomNumber<=guess) { document.getElementById("result").innerHTML = "No, try a lower number."; tries++; } }
根因定位
核心问题是字符串类型的隐式字典序比较:
- 通过
prompt获取的userMax、通过输入框value获取的guess默认都是字符串类型,代码中没有提前统一转成数值类型就做大小比较 - JS对字符串做
</>比较时,会逐字符对比ASCII码,而非按数值大小计算。例如设定最大值为10(字符串"10"),输入猜测值2(字符串"2")时,第一位字符"2"的ASCII码大于"1",会被判定为"2" > "10",直接触发超范围告警。
其余附带缺陷:
isFloat函数引用了未定义的变量n,且全程没有被调用,属于冗余无效代码- 输入校验分支没有阻断逻辑:当用户输入非数字、超范围值触发告警后,代码不会终止,仍会继续执行后续和随机数比对的逻辑,引发额外异常
- 用户猜对答案后,计数变量
tries没有重置,下一轮游戏计数会持续累加 - 页面加载后若用户未先设置数值上限直接点猜测按钮,
userMax为undefined会直接抛出JS错误 higherLower函数开头的window.alert(randomNumber)是调试残留代码,会直接弹出正确答案,正式使用需要删除- 原
userInput用递归方式处理输入错误,极端情况下会引发调用栈溢出,用循环处理更稳妥
修复后代码
scripts.js(核心修改部分)
let userMax; let randomNumber; let tries = 0; // 页面加载后自动提示用户设置最大值 window.onload = userInput; function userInput() { let inputVal = prompt("Please enter a maximum number:"); // 统一转数值类型做校验 userMax = Number(inputVal); while (userMax < 1 || isNaN(userMax)) { alert("Maximum number cannot be negative, zero, or non-numbers"); inputVal = prompt("Please enter a maximum number:"); userMax = Number(inputVal); } // 生成随机数、重置尝试次数 randomNumber = Math.floor(Math.random() * userMax) + 1; tries = 0; return userMax; } function higherLower() { // 猜测值统一转数值类型 const guess = Number(document.getElementById('choice').value); // 校验不通过直接return,阻断后续逻辑 if (isNaN(guess)) { alert("That is not a number!"); return; } if(guess < 1 || guess > userMax) { alert("That number is not in range, try again."); return; } // 数值比对逻辑 tries++; if(randomNumber === guess) { document.getElementById("result").innerHTML = `You got it! It took you ${tries} tries`; // 猜对后生成新随机数,重置计数 randomNumber = Math.floor(Math.random() * userMax) + 1; tries = 0; } else if(randomNumber > guess) { document.getElementById("result").innerHTML = "No, try a higher number."; } else { document.getElementById("result").innerHTML = "No, try a lower number."; } }
可选优化:可以把HTML里的输入框
type="text"改成type="number",移动端会自动唤起数字键盘,同时原生拦截非数字输入。
内容的提问来源于stack exchange,提问作者smmbam
相关产品推荐
相关产品推荐

