11

我正在尝试使用 HTML5 画布、JavaScript 和 XML 制作一种游戏。这个想法是,您可以通过将问题和答案放在 XML 文件中来进行测验。我写了一个循环遍历所有问题的主循环,提出它们并检查答案的正确性。现在我只是使用警报和对话框来回答问题问题是我的主循环是一个相互关联的大整体,它从头到尾遍历整个游戏,而不是让警报框提出问题和对话框回答,紧接着,我想要一些用户交互。问题的答案出现在屏幕底部的方框中,用户可以控制起重机来选择正确的答案。这是我坚持的主循环中的代码片段:

answer = loadQuestion(i);
            if (answer == "correct") {
                // answered correctly, update scoreArray and load next question
                scoreArray[currentQuestion] = "correct";
                // show 'next'-button and wait for press to continue

            } else {
                // answered incorrectly again, update scoreArray and load next question
                scoreArray[currentQuestion] = "error";
                // show 'next'-button and wait for press to continue

            }

如您所见,我正在调用 loadQuestion,它会立即加载问题,显示可能的答案,并且现在会立即抛出一个对话框,您可以在其中输入答案。返回并验证此答案。

我已经对起重机的控制进行了编程,用户已经可以用它拿起一个盒子。但是因为我正在调用 loadQuestion 并期望它返回一个值,所以这不起作用。如何让我的主循环“暂停”,直到玩家使用起重机给出答案,然后继续?我已经尝试将答案设为全局变量,并且只有一个空的while answer == ""以使函数忙于什么都不做,直到 answer 得到一个值,但这只会冻结脚本。我还弄乱了区间以试图监视答案变量的状态,并在发生这种情况时清除区间并返回值,但这只是返回 false,因为函数完成而没有立即返回值。

4

3 回答 3

23

如何让我的主循环“暂停”,直到玩家使用起重机给出答案,然后继续?

通过打破它。浏览器上 JavaScript 中唯一的“让步”是让您的函数结束,然后安排稍后回调(通过setTimeoutsetInterval、ajax 回调等)。在您的情况下,我倾向于认为给您回电的触发器应该是用户回答前一个问题的操作,例如,click答案框上的处理程序或类似的(而不是setTimeout自动化的)。

例如,这段代码:

function loopArray(ar) {
    var index;
    for (index = 0; index < ar.length; ++index) {
       doSomething(ar[index]);
    }
}

...可以像这样重铸:

function loopArrayAsync(ar, callback) {
    var index;

    index = 0;
    loop();

    function loop() {
        if (index < ar.length) {
            doSomething(ar[index++]);
            setTimeout(loop, 0);
        }
        else {
            callback();
        }
    }
}

第二个版本在每次循环迭代时将控制权交还给浏览器。还需要注意的是,第二个版本在循环完成之前返回,而第一个版本等待所有循环完成,这就是为什么第二个版本在callback循环完成时具有它调用的函数。

调用第一个的代码可能如下所示:

var a = ["one", "two", "three"];
loopArray(a);
// Code that expects the loop to be complete:
doTheNextThing();
doYetAnotherThing();

...而使用异步版本如下所示:

var a = ["one", "two", "three"];
loopArrayAsync(a, function() {
    // Code that expects the loop to be complete:
    doTheNextThing();
    doYetAnotherThing();
});

这样做,你可能会发现你使用了闭包loop上面,是一个闭包),所以这篇文章可能很有用:闭包并不复杂

于 2011-04-05T12:00:36.047 回答
6

没有同步。在浏览器 JS 中暂停输入/输出工具,除了alert,confirmprompt. 由于您不想使用这些 - 请尝试以下模式:

loadQuestion(i, function(answer) {
   if (answer == "correct") {
            // answered correctly, update scoreArray and load next question
            scoreArray[currentQuestion] = "correct";
            // show 'next'-button and wait for press to continue

        } else {
            // answered incorrectly again, update scoreArray and load next question
            scoreArray[currentQuestion] = "error";
            // show 'next'-button and wait for press to continue

        }
  resumeGameExecution();
});

即当用户回答它时 - 回调函数被执行并且你知道你很高兴。

于 2011-04-05T12:02:49.963 回答
4

据我了解,您有一个问卷调查应用程序,您可以在其中提出一系列问题,然后要求用户使用一些拖放控件(起重机)放弃他的答案。

我要去切线说设计似乎是错误的。Javascript 是基于事件的,并且有一个主线程循环用于用户交互会降低可用性。我不会使用任何方式来停止线程(也就是在 java 中)。Javascript 不是为这样的用例编写的。某些浏览器和几乎所有性能分析器(如 Yslow)都会认为您的应用程序没有响应。

所以我会为每个问题提供一个由内部是一个序列(question1..2)的类标识的div。最初只会启用或显示一个问题。用户回答问题后,我将启用已启用的问题。(在适当的事件上,在这种情况下可能是拖放的拖放事件)。由于它是连续的,我只需要检查用户是否回答了问题 1,然后我将适当地启用问题 2。整个流程应该是事件驱动的。这里的事件是用户回答问题。

于 2011-04-05T12:12:30.357 回答