Correction de l'exécution par Javascript de la fonction pour attendre l'entrée de l'utilisateur

J'essaie de faire une sorte de jeu à l'aide de la toile HTML5, JavaScript et XML. L'idée est que vous pouvez faire un quiz en posant des questions et des réponses dans un fichier XML. J'ai écrit une boucle principale qui boucle toutes les questions, les pose et vérifie l'exactitude de la réponse. Pour l'instant, j'utilise simplement des alertes et des boîtes de dialogue pour répondre aux questions. Le problème est que ma boucle principale est un gros ensemble interconnecté qui parcourt tout le jeu du début à la fin, et au lieu d'avoir des boîtes d'alerte posant des questions et des boîtes de dialogue Réponse, immédiatement après l'autre, je veux une interaction avec les utilisateurs. Les réponses aux questions apparaissent sur les cases en bas de l'écran, et l'utilisateur peut contrôler une grue pour choisir la bonne réponse. Voici l'extrait de code de la boucle principale sur laquelle je suis coincé:

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 } 

Comme vous pouvez le voir, j'appelle loadQuestion, qui charge instantanément la question, montre les réponses possibles et, pour l'instant, lance immédiatement une boîte de dialogue où vous pouvez taper la réponse. Cette réponse est retournée et validée.

J'ai déjà programmé les commandes de la grue, l'utilisateur peut déjà enlever une boîte avec elle. Mais parce que j'appelle loadQuestion et j'espère qu'il retourne une valeur, cela ne fonctionne pas. Comment faire ma boucle principale "pause" jusqu'à ce qu'une réponse ait été donnée par le joueur à l'aide de la grue, puis procédez? J'ai déjà essayé de faire de la réponse une variable globale, et j'ai juste une réponse vide == "" pour garder la fonction occupée à ne rien faire jusqu'à ce que la réponse obtienne une valeur, mais cela gèle simplement le script. J'ai également dérangé avec des intervalles pour tenter de surveiller l'état de la variable de réponse et effacer l'intervalle et renvoyer la valeur lorsque cela se produit, mais cela renvoie simplement false puisque la fonction est terminée sans renvoyer immédiatement une valeur.

    Comment faire ma boucle principale "pause" jusqu'à ce qu'une réponse ait été donnée par le joueur à l'aide de la grue, puis procédez?

    En le séparant. Le seul "rendement" en JavaScript sur les navigateurs est de permettre à votre fonction de finir et ensuite de vous rappeler plus tard (via setTimeout , setInterval , un rappel ajax, etc.). Dans votre cas, j'aurais tendance à penser que le déclencheur pour vous rappeler devrait être l'action de l'utilisateur répondant à la question précédente, par exemple, un gestionnaire de click sur les répondeurs ou un tel (plutôt que setTimeout et tel que automatisé).

    Par exemple, ce code:

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

    … peut être reformulé comme ceci:

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

    La deuxième version renvoie le contrôle au navigateur sur chaque itération en boucle. Il est également important de noter que la deuxième version revient avant que les boucles ne soient terminées, tandis que la première version attend jusqu'à ce que toutes les boucles soient terminées, c'est pourquoi la deuxième version a la fonction de callback qu'elle appelle lorsque la boucle est terminée.

    Le code appelant le premier pourrait ressembler à ceci:

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

    … alors que l'utilisation de la version asynchique ressemble à ceci:

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

    Ce faisant, vous trouverez probablement que vous utilisez des fermetures ( loop , ci-dessus, est une fermeture), et cet article peut être utile: les fermetures ne sont pas compliquées

    Il n'y a pas de synchronisation. Des outils d'entrée / sortie en pause dans le navigateur JS, à l'exception de l' alert , de la confirm et de l' prompt . Puisque vous ne souhaitez pas les utiliser, essayez le modèle suivant:

     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(); }); 

    C'est-à-dire lorsque l'utilisateur le répond – la fonction de rappel est exécutée et vous savez que vous êtes prêt à aller.

    D'après ce que je comprends, vous avez une demande de questionnaire, où vous posez une série de questions et demandez à l'utilisateur de déposer sa réponse en utilisant un contrôle de glisser-déposer (une grue).

    Je vais faire une tangente et dire que le design semble être faux. Javascript est basé sur les événements et un premier thread principal autour de l'interaction de l'utilisateur va réduire la convivialité. Je n'utiliserai aucun moyen de bloquer le fil (aka in java). Javascript n'est pas écrit pour une telle utilisation. Votre application sera perçue comme non adaptée par certains navigateurs et par presque tous les analyseurs de performance (comme Yslow).

    Je voudrais donc fournir chaque question avec un div identifié par une classe qui, en interne, est une séquence (question1..2). Initialement, une seule question sera activée ou visible. Une fois que l'utilisateur répond à la question, je vais activer la question activée. (Sur l'événement approprié, dans ce cas probablement l'événement de baisse de glisser-déposer). Comme il est séquentiel, je dois simplement vérifier si l'utilisateur a répondu à la question1, alors je vais permettre la question2 de manière appropriée. L'ensemble du flux devrait être conduit par l'événement. L'événement étant l'utilisateur qui répond à la question.