Quiz mit Javascript erstellt - bitte um Code-Beurteilung

  • Ah, besten Dank – ich habe das HTML online aktualisiert. Jetzt funktionieren die Klicks, aber die Konsole meldet „Uncaught (in promise) ReferenceError: countofquestions is not defined at sempervivum.js:417“. Liegt es daran, dass die Bedingung if (i == countofquestions)nun nicht mehr innerhalb der Funktion getCountRows liegt?


    Zum Debugger für Javascript: Ich kann nicht behaupten, dass ich mit ihm vertraut bin. Ich kenne ihn und benutze ihn (z. B. habe ich den Eventlistener damit laufen lassen und dabei mitbekommen, dass sich die Klicks summieren). Ich werde mal schauen, ob ich ein gutes Lehrvideo zum Debugger finde, denn ganz sicher bietet er Möglichkeiten, von denen ich noch nichts ahne.

  • Ja, auch dies ist ein unerwünschtes Ergebnis davon, dass wir das Registrieren aus der Funktion heraus genommen haben. Ich dachte zunächst daran, diese Anzahl in einer globalen Variablen zu speichern, was unbefriedigend wäre, aber es gibt eine bessere Lösung:

    In der Funktion makeQuestion brauchen wir die Variable countofquestions jetzt nicht mehr, denn sie wird nur in den Eventlistenern für die Antwort-Buttons gebraucht. Also können wir diesen Parameter bei makeQuestion löschen. Statt dessen definieren wir eine Funktion z. B. addListeners, die die Eventlistener registriert und die Anzahl countofquestions als Parameter hat:

    Jetzt müssen wir nur noch dafür sorgen, dass die Funktion auch mit diesem Parameter aufgerufen wird. Das erreichen wir, indem wir die Funktion als Callback an getCountRows übergeben. Für makeQuestion ist dies jetzt nicht mehr nötig, diese Funktion können wir direkt aufrufen:

    Code
    getCountRows(addListeners);
    makeQuestion();

    Wieder ungetestet, wenn noch Fehler übrig sind, müssen wir weiter sehen.

  • Blitzeis beschert mir heute einen unfreiwillig freien Tag, also habe ich mich gleich wieder mit dem Script beschäftigt. Und ich muss zugeben, dass ich im Augenblick erst mal nicht mehr wirklich durchblicke, ich muss das am Ende noch mal genau analysieren.


    Jetzt habe ich den Zustand, dass keine Mouseevents mehr funktionieren. Wenn ich im Debugger in Chrome als Event Listener Breakpoints „Mouse -> click“ auswähle, wird nichts angezeigt, auch keine Fehlermeldung.


    Das aktualisierte Script ist online, Link unverändert wie in #159. Habe ich irgendwas falsch kopiert?

  • Ach, ich Döskopp – wieder die Hälfte übersehen. Ich danke Dir, jetzt funktioniert alles!


    Nun muss ich mir das wirklich mal in Ruhe anschauen. Das Prinzip der Callbacks habe ich eigentlich verstanden, hatte mir, als es hier darum ging, auch ein paar einfache Beispiele gebastelt. Aber das Script, welches mein Spiel steuert, ist mittlerweile für mich ein ziemliches Monstrum geworden. ;)


    Einen guten und eisfreien Start in die Woche wünsche ich!

  • Ich wünsche allseits ein gesundes neues Jahr!


    Ganz besonders herzliche Wünsche gehen an Sempervivum – Du hast mir hier so aufopferungsvoll und freundlich geholfen, dass ich (ich sagte es zwar schon mehrfach, aber ich wiederhole es gern) Dir dafür sehr, sehr dankbar bin. Viel Glück und Gesundheit in 2022!


    Tja, und schon habe ich wieder eine Frage ...


    Ich möchte mir alle 15 Ziffern aus der Datenbank-Spalte truenumber holen. Dazu habe ich mich an folgendem PHP versucht:


    Code
    $statement = $pdo->prepare("SELECT truenumber FROM questionsAnswers");
        $statement->execute(array());
        while ($row = $statement->fetch()) {
          $numbers = [
            $row['truenumber'],
          ];
          echo json_encode($numbers) . ',';
        }


    Das Ergebnis ist: ["4"],["4"],["3"],["1"],["2"],["3"],["1"],["4"],["1"],["3"],["1"],["2"],["2"],["3"],["4"],


    Ich bekomme also nicht ein Array mit allen Zahlen, wie ich es eigentlich gern hätte, sondern 15 Arrays mit je einer Zahl, was natürlich keinen Sinn ergibt.


    Ich habe Etliches versucht, um die Ausgabe zu ändern, aber es ist mir nichts Brauchbares gelungen. Deswegen die Frage: Wie muss der PHP-Code aussehen, damit ich folgendes Ergebnis bekomme: [4, 4, 3, 1, 2, 3, 1, 4, 1, 3, 1, 2, 2, 3, 4]?


    Herzlichen Dank!

  • Wieso

    Code
    echo json_encode($numbers) . ',';

    Du meinst

    Code
    echo implode(", ", $numbers);

    Und da das nichts mit deinem JavaScript-Problem zu tun hat, hättest du besser einen neuen Thread im Unterforum PHP aufgemacht.

  • Da wir in diesem Thread schon mehrfach über das Zusammenspiel von JavaScript und PHP geschrieben hatten, habe ich mir auch diesmal erlaubt, keinen neuen Thread in einem anderen Unterforum zu eröffnen, da ich annahm, dass es für alle Beteiligten so übersichtlicher bleibt, vielleicht auch für User, die später aus irgendeinem Grund per Suchmaschine in diesem Thread landen und alle Bestandteile an einer Stelle vorfinden.


    Ich habe mein Problem mittlerweile lösen können, Dein Hinweis auf implode brachte mich auf die Idee, das PHP viel einfacher zu halten, und zwar so:


    PHP
    $statement = $pdo->prepare("SELECT truenumber FROM questionsAnswers");
        $statement->execute(array());
        while ($row = $statement->fetch()) {
          echo $row['truenumber'];
        }


    Das JavaScript dazu sieht dann so aus:



    Ich musste die 15-stellige Zahl in 15 Zahlen innerhalb eines Arrays wandeln, was hiermit auch gelungen ist.


    Edit: Die Problematik bezieht sich natürlich immer noch auf mein Musik-Quiz, was der Hauptgrund war, sie hier zu stellen. Das war aber vermutlich nicht eindeutig ersichtlich.

  • Guten Abend Failix, ich wünsche ebenfalls ein frohes und gesundes neues Jahr.

    Und danke für die freundliche Worte.

    Dein Javascript ist ja ein wenig unkonventionell, ich musste drei Mal überlegen, um zu verstehen, wie es funktioniert.

    Ich empfehle, bei dem Verfahren mit JSON zu bleiben, also im PHP ein Array zu erzeugen und dieses in JSON zu kodieren:

    Code
        $statement = $pdo->prepare("SELECT truenumber FROM questionsAnswers");
        $statement->execute(array());
        $rightNumbers = [];
        while ($row = $statement->fetch()) {
            $rightNumbers[] = $row['truenumber'];
        }
        echo json_encode($rightNumbers);

    Wahrscheinlich kann man auch mit fetchAll gleich das ganze Array erzeugen und dieses dann kodieren, aber das habe ich nicht untersucht.


    Mit dem Code oben brauchst Du dann im Javascript überhaupt nichts zu tun sondern in rightInt liegt sofort ein dekodiertes Array vor.

  • Sempervivum Vielen Dank für Deine Wünsche und Deinen Lösungsvorschlag!


    Ja, so ist es wirklich viel besser. Mit PHP und JSON habe ich (auch) noch so meine Schwierigkeiten. Sollte ich diesbezüglich weitere Fragen haben, mache ich dann aber wirklich einen Thread im entsprechenden Unterforum auf.


    Die dritte Version meines Quiz, bei der man die Auswertung der Fragen erst am Ende bekommt, ist auf dem Weg, dazu brauche ich halt andere Arrays als in der zweiten Version.


    Schönen Abend noch!

  • Mir stellte sich gerade die Frage: Gibt es eine mit JavaScript ausführbare Funktion, die alles, was ein JavaScript bewirkt hat, zurücksetzt – oder anders, eine Funktion, die einem Reload des Browserfensters gleichkommt, also einfach alles wieder bei null beginnen lässt?


    Ich habe mir window.location.href = window.location.href ergoogelt, scheint auch zu funktionieren. Gibt’s irgendwelche Stolpersteine, von denen ich noch nichts ahne?


    Angewendet werden soll diese Funktion per Buttonklick für Wiederholung des o. g. Quiz.

  • Für das Neuladen der Seite gibt es auch location.reload(). Ich habe das getestet und dieses und window.location.href = window.location.href verhalten sich offenbar gleich. Stolpersteine sind mir nicht bekannt außer dass die Seite ein wenig flackern kann.


    Eine Alternative ist, die notwendigen Aktionen selber auszuführen, also in deinem Fall den Index der Frage auf 0 zu setzen und dazu die Frage und die Antworten anzuzeigen. Allerdings habe ich keinen Überblick ob dies ausreichend ist oder noch mehr nötig ist, z. B. andere Variablen wieder auf den Anfangszustand setzen.

  • Herzlichen Dank!


    In der neuen Version meines Quiz muss ich eine Menge auf den Ausgangszustand zurücksetzen, Transparenzen, Rotationen und vor allem in Variablen gespeicherte Werte. Da ist es schon praktisch, das mit einem Reload zu erledigen.


    Also, wenn es keine Fallstricke und Stolpersteine gibt, dann lasse ich es so. Und die neue Version ist auf der Zielgeraden … glaube ich. ;)

  • So, ich bin am Ziel angekommen ... dachte ich noch vor einer Stunde. Aber ich habe ein Timing-Problem.


    Hier die aktuelle Version: http://music-quiz.bplaced.net/mq05/ und http://music-quiz.bplaced.net/mq05/musicQuiz.js


    Spielt man das Quiz wie ein "ganz normaler Mensch", scheint alles bestens zu funktionieren. Legt man es aber darauf an, ganz besonders schnell zu sein, funktionieren die Timer nicht mehr – oder besser gesagt: Sie stoppen irgendwann im Laufe des Spiels nicht mehr an der Stelle, an der sie es sollten.


    Auf Zeile 413 des Scripts wird die Funktion answerBlock() aufgerufen, diese beginnt auf Zeile 69. In dieser Funktion wiederum werden die Funktionen stopTimer() und stopCTimer() aufgerufen, welche auf den Zeilen 132 und 210 zu finden sind.


    Klickt man die Buttons ohne Hinzuschauen so schnell wie möglich hintereinander, werden diese beiden Stop-Funktionen mitten im Spiel nach ein paar Fragen nicht mehr ausgeführt. Ich habe ein console.log(csec) eingebaut, dort sieht man es gut. Die Variable csec dürfte nur hochgezählt werden, während eine Frage auf ihre Beantwortung wartet, sobald man einen Button klickt, muss das Hochzählen bis zur nächsten Frage unterbrochen werden.


    Da dies in normaler Spielgeschwindigkeit gelingt, aber nicht, wenn man unnatürlich schnell klickt, vermute ich ein Performance-Problem. Ich habe bewusst noch nicht versucht, das Ganze umzubauen, sondern ich wollte gern Eure Meinung dazu wissen. Ist diese Verschachtelung, die ich mit den Funktionen gemacht habe, nicht das Gelbe vom Ei, sollte man sowas besser vermeiden?

  • Bis in die Details bin ich da nicht eingestiegen, aber ich habe den Eindruck, dass das Problem hier liegt:

    Du schaltest die Pointerevents sofort ein, startest aber die Timer mit 700 ms Verzögerung. Wenn man jetzt während dieser Verzögerung schon klickt, sind die Timer noch gar nicht gestartet. Was dann damit passiert habe ich nicht untersucht. Versuche, die Pointerevents im Callback für setTimeout nach dem Starten der Timer einzuschalten.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!