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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 20:21:18