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

开发西蒙游戏时网页按键后冻结,循环已设终止条件求排查

问题分析与修复方案

核心冻结原因:异步操作与同步循环冲突

你的代码里的while ($c && order_array.length > 0)是同步循环,但内部的setTimeout是异步执行的——也就是说,$c = order_check()要等3秒才会执行,但while循环不会等待,会持续疯狂占用CPU资源,直接导致浏览器冻结。

JavaScript是单线程的,同步循环会阻塞事件队列,异步的setTimeout回调根本没机会执行,$c永远是初始的true,循环永远停不下来。

其他关键问题

  • 重复绑定点击事件:order_check的for循环里,每次都会给.play按钮绑定N次点击事件(N为序列长度),点击一次会触发多个回调,逻辑完全混乱。
  • 闭包陷阱:for循环里的i是全局变量,点击回调执行时i已经等于序列长度,永远拿不到正确的当前索引。
  • 逻辑时序错误:order_check会在用户点击前直接返回结果,根本等不到用户输入,返回值毫无意义。

修复后的代码示例

$(document).ready(function () {
    var order_array = [];
    var currentStep = 0;
    var isUserTurn = false;

    function press(j) {
        $("#" + j).addClass("play_pressed");
        // 此处可添加音效逻辑
        setTimeout(function () {
            $("#" + j).removeClass("play_pressed");
        }, 500);
    }

    function order_add() {
        var jk = Math.floor(Math.random() * 4);
        var j = 'p';
        switch (jk) {
            case 1: j = 'q'; break;
            case 2: j = 'r'; break;
            case 3: j = 's'; break;
        }
        order_array.push(j);
        press(j);
    }

    function playSequence() {
        isUserTurn = false;
        $("h1").text("Watch the sequence!");
        var index = 0;
        var interval = setInterval(function() {
            press(order_array[index]);
            index++;
            if (index >= order_array.length) {
                clearInterval(interval);
                setTimeout(startUserTurn, 1000);
            }
        }, 800);
    }

    function startUserTurn() {
        isUserTurn = true;
        currentStep = 0;
        $("h1").text("Click the keys in Order!");
    }

    function checkUserInput(e) {
        if (!isUserTurn) return;

        var clickedId = e.target.id;
        if (clickedId === order_array[currentStep]) {
            press(clickedId);
            currentStep++;
            if (currentStep === order_array.length) {
                // 用户完成当前序列,进入下一轮
                isUserTurn = false;
                setTimeout(function() {
                    order_add();
                    playSequence();
                }, 1000);
            }
        } else {
            // 用户出错,游戏结束
            gameOver();
        }
    }

    function gameOver() {
        isUserTurn = false;
        $("h1").text("The game has ended!!");
        $("body").addClass("end");
        $(".play").off("click", checkUserInput);
    }

    // 仅绑定一次点击事件,避免重复绑定
    $(".play").click(checkUserInput);

    $(document).keypress(function (e) {
        // 防止重复触发游戏
        if (order_array.length > 0) return;
        
        $("h1").text("The game has begun!!");
        order_add();
        setTimeout(playSequence, 1000);
    });
});

关键修复点

  • 移除同步while循环,改用异步的"序列播放+用户输入监听"模式,符合JavaScript单线程异步特性。
  • 点击事件仅绑定一次,避免重复绑定导致的逻辑混乱。
  • 用currentStep跟踪用户当前需要点击的序列位置,规避闭包陷阱。
  • 明确区分"播放序列"和"用户输入"两种状态,防止用户在序列播放时误操作。

内容的提问来源于stack exchange,提问作者Gautam Ranka

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 10:48:20