Quiz mit Javascript erstellt - bitte um Code-Beurteilung

  • Ich bin jetzt dazu gekommen, mir den Code anzuschauen. Ich habe verstanden, dass neben der ID auch die gewählte Antwort an den Server geschickt wird.


    Ich habe versucht, die Datei "animalgame3.php" anzupassen, hier der bisherige Code:



    Mein Versuch sieht so aus:



    Das überträgt jetzt den Wert der gewählten Antwort, aber ob es der korrekte Ansatz ist, weiß ich nicht – dummerweise ersetzen gerade Vermutungen die Erkenntnis.


    Und dann wäre ja auch noch die Abfrage im JavaScript:


    if (questions.answers[j] == rightOne.trueanswer) {


    Mir ist völlig unklar, welche beiden Werte ich nun miteinander vergleichen müsste. Für Licht in meinem geistigen Dunkel wäre ich dankbar ...

  • Zitat

    Mir ist völlig unklar, welche beiden Werte ich nun miteinander vergleichen müsste.

    $choosen ist ja offenbar die Antwort, für die sich der Benutzer entschieden hat. Und $row['trueanswer'] die richtige Antwort, die in der Datenbank hinterlegt ist. D. h. Du müsstest testen, ob sie gleich sind:

    $choosen == $row['trueanswer']

    liefert true, wenn sie übereinstimmen und false, wenn nicht.

    Und das dann in die Antwort eintragen:

    Code
        $statement = $pdo->prepare("SELECT * FROM animals WHERE id = ?");
        $statement->execute(array($id));
        $statement->execute(array($choosen));
        $row = $statement->fetch();
        $trueanswer = [
          'id' => $id,
          'trueanswer' => ($choosen == $row['trueanswer']),
        ];
        echo json_encode($trueanswer);
  • PS: Und im Browser, wenn Du die Antwort verarbeitest, brauchst Du nur noch zu prüfen, ob trueAnswer true ist:

    Code
    if (rightOne.trueAnswer == true) {
        // die Antwort ist richtig
    } else {
        // die Antwort ist falsch
    }

    oder kürzer:

    Code
    if (rightOne.trueAnswer) {
  • Leider funktioniert der Code nicht wie gewünscht, hier die aktuelle Datei "animalgame3.php":



    Ich bekomme die Warnung "Trying to access array offset on value of type bool in /users/music-quiz/www/animalgame3.php on line 21". Dazu spuckt Google knapp 7 Millionen Treffer aus ... das, was ich zu lesen bekomme, ist für mich völlig unverständlich.


    Schalte ich die PHP-Warnungen aus, wird mir ausschließlich {"id": "1", "trueanswer": false} zurückgegeben – egal, welche Antwort ich anklicke.


    Das Ganze ist auch online zu sehen: http://music-quiz.bplaced.net/

  • "Trying to access array offset on value of type bool in /users/music-quiz/www/animalgame3.php on line 21"

    liegt i. allg. daran, dass eine Funktion false statt eines Arrays liefert, weil bei der Ausführung ein Fehler aufgetreten ist. Siehe z. B. die Doku von fetch:

    https://www.php.net/manual/de/pdostatement.fetch.php


    Um heraus zu finden, was für ein Fehler kannst Du auch die SQL-Fehler anzeigen lassen, siehe hier:

    https://www.php.net/manual/de/pdostatement.errorinfo.php


    Ohne dies zu sehen, scheint mir aber, dass diese Zeile überflüssig ist:

    $statement->execute(array($choosen));

    Du willst ja den Datensatz auslesen, wo die ID passt und dieses $choosen ist etwas anderes als die ID.

  • Sempervivum Wiederum herzlichen Dank, wenngleich die beiden Links mir – zumindest mit meinem derzeitigen Wissensstand – überhaupt nicht weiterhelfen. Das, was ich gerade tue, ist nichts als hilfloses Stochern in einer für mich trüben Brühe, die nur dann aufklart, wenn mir jemand konkret sagt, was zu tun ist.


    Klar bin ich enttäuscht, dass das alles für mich so kompliziert ist. Anderseits muss ich aber auch bedenken, dass ich erst vor ziemlich genau drei Monaten damit angefangen habe, mich überhaupt mit Programmierung zu beschäftigen und dass ich dafür nur wenige Stunden in der Woche Zeit habe. Ich würde gern viel schneller viel mehr wissen, aber der Weg ist steinig und steil. :(


    Die genannte überflüssige Zeile zu löschen, hat mich zumindest von jener PHP-Warnung befreit. Nun bekomme ich auf PHP-Seite auch {"id": "1", "trueanswer": false} bzw. {"id": "1", "trueanswer": true} geliefert, je nach angeklickter Antwort. Das funktioniert also. Aber das JavaScript kann damit leider nichts anfangen.


    Die Online-Version ist aktuell: http://music-quiz.bplaced.net/


    m.scatello Ich hatte die öffnende Klammer und die Zeile mit den Zugangsdaten weggelassen, aber das ist natürlich blöd, wenn man eine Fehlermeldung mit Zeilenangabe postet ... sorry!

  • Es ist geschafft, das gesamte Konstrukt funktioniert jetzt endlich. Und Dir, Sempervivum, wiederum ganz herzlichen Dank! Ich hätte das ohne Dich nicht hinbekommen – vor allem bei PHP sind meine Kenntnisse noch völlig unzureichend.


    Die Vorgehensweise mit dem Debugger, die Du oben zeigst, habe ich gerade nachvollzogen, und nein – selbst wenn ich auf die Idee gekommen wäre, ihn zu benutzen, wäre mir das große "A" nicht aufgefallen. Einen direkten Hinweis, dass es falsch ist, liefert der Debugger ja auch nicht, es muss einem schon wirklich ins Auge stechen.


    Was mich freut: Der Umgang mit MySQL war viel einfacher, als ich zunächst befürchtet hatte. Datenbanken waren bis vor kurzem für mich die großen, geheimnisvollen Unbekannten, jetzt wirken sie schon fast etwas vertraut. Wichtig ist es für mich nun, PHP so weit zu verstehen, dass ich MySQL auch optimal nutzen kann.


    Ich werde deshalb sicher wieder mit Fragen ankommen, aber nicht hier im JavaScript-Bereich, versteht sich. ;)


    Jetzt wünsche ich erst mal allerseits einen guten Start in die Woche, bleibt gesund!

  • Endlich hatte ich mal wieder etwas Zeit ...


    Wie ich in #99 schrieb, störte mich die Redundanz in der Datenbank. Ich hatte ja die richtige Antwort als Kopie einer der Fragen in der Spalte trueanswer hinterlegt. Heute war es mein Ziel, eine Spalte truenumber anzulegen, diese mit der Ziffer der richtigen Antwort zu befüllen und dann mit PHP und Javascript diese Spalte auszuwerten.


    Und es ist mir gelungen. Das PHP anzupassen, war nicht sonderlich schwer, aber fürs JavaScript "musste" ich erst was lernen, und zwar getAttribute, damit ich statt des Inhalts der Antwort die ID des Antwortbuttons auslesen konnte. Das hat wunderbar geklappt, ich bin ein klein wenig stolz auf mich, dass ich mal was ganz ohne Fragen hinbekommen habe. ;)


    Hier ist das Ergebnis: http://music-quiz.bplaced.net/index1.html

  • Ich habe immer noch bzw. immer wieder Probleme mit der richtigen Verschachtelung. Hier mein aktueller Code:



    Schauen wir auf Zeile 4 und 8: Die Funktion questionsAndAnswers() startet mit dem Objekt countIds, alle weiteren Elemente der Funktion sind darin verschachtelt. Das Objekt countIds erzeugt den String ids, welcher mir die Anzahl der Reihen in der DB liefert. Diese Zahl brauche ich, um das Ende des Spiels ermitteln zu können, und deshalb ist countIds auch das äußerste Objekt der Funktion. Es funktioniert tadellos.


    Nun würde ich den String ids aber auch gern außerhalb der Funktion questionsAndAnswers() verwenden, um diese Zahl in einem Prolog zum Spiel anzuzeigen, also bevor questionsAndAnswers() ausgeführt wird. Ist das irgendwie möglich?


    Die meiner Meinung nach unschöne Lösung wäre, das Objekt countIds außerhalb der Funktion zu duplizieren. Das würde funktionieren, aber ist es denn ein sauberer Weg? Irgendwas lässt mich daran zweifeln ...


    Die Frage ist also: Kann ich den String ids irgendwie außerhalb der Funktion questionsAndAnswers() anwenden, ohne das Objekt countIds zu duplizieren?

  • Du hast vollkommen Recht, etwas zu duplizieren ist fast immer eine unschöne Lösung. Und die Standard-Alternative ist, den Code in eine Funktion zu packen und diese mehrfache aufzurufen. Was die Sache hier ein wenig kompliziert macht, ist die Tatsache, dass die Abfrage der Anzahl der Fragen asynchron abläuft, d. h. Du kannst nicht einfach im then einen Return machen, um den Wert zurück zu liefern. Aber es gibt eine Lösung: Der Funktion eine Callback-Funktion als Parameter übergeben, in der die Aktionen stehen und diese dann im then-Zweig aufrufen. Versuche es auf diesem Wege und wenn Du nicht zum Ziel kommst, melde dich wieder.

  • Wie immer vielen Dank für Deine schnelle Rückmeldung, Sempervivum ! Ich habe zunächst countIds in eine Funktion countRows() gepackt, sie beginnt auf Zeile 30 und endet auf Zeile 118, umgibt also alles andere in der Funktion questionsAndAnswers().



    Zum Callback (unbekanntes Land bisher für mich) habe ich gegoogelt und unter anderem dieses Beispiel gefunden:


    Code
    function doSomething(callback) {
      /* ... */
      callback();
      /* ... */
    }
    
    function doSomethingElse() {
      console.log('Callback aufgerufen');
    }
    doSomething(doSomethingElse);  // Ausgabe: "Callback aufgerufen"


    Das kann ich zwar nachvollziehen, verstehe den Sinn aber nicht. Demzufolge gelingt es mir auch nicht, das Beispiel für meinen Code zu abstrahieren. Für weitere Erläuterungen wäre ich sehr, sehr dankbar.

  • Das Beispiel, das Du da gefunden hast, ist schon Mal sehr gut. Angewendet auf deine Zeilenanzahl müsste das dann in etwa so aussehen:

    Vorteil: Das Ganze ist etwas aufgeräumter, weil die einzelnen Bestandteile in Funktionen aufgeteilt wurden.

    Nachteil: Die Reihenfolge, in der die Funktionen aufgerufen werden, ist nicht mehr ganz so offensichtlich.

  • Herzlichen Dank, das muss ich mir ganz in Ruhe ansehen und sicherlich den Code erst mal komplett auseinandernehmen, damit ich es verstehe. Auf den ersten Blick gibt's keine Erleuchtung bei mir. ;)


    Zu Deiner Frage im Kommentar: Die Anzahl der Fragen ist gleich der Anzahl der IDs, deswegen hatte ich es so benannt. Oder lauert da eine Fehlerquelle, die ich noch nicht sehe?

  • Ich kapiere gerade nichts, das nervt mich total. Vielleicht versuchen wir es mal ganz primitiv:



    Was muss man tun, damit die Konsole die ids ausgibt? Ich habe das gesamte Prinzip vorn und hinten nicht verstanden. :(

  • Code
    // Der Fehler liegt hier: Da Du innerhalb der Funktion doSomethingElse auf ids zugreifst,
    // musst Du dies als Parameter definieren:
    // function doSomethingElse() {
    function doSomethingElse(ids) { 
        console.log(ids);
    }

    Verwirrend könnte sein, dass hier keine Rede von dem Parameter ist:

    Code
    getCountRows(doSomethingElse);

    Da in der Funktion getCountRows jedoch die Funktion mit diesem Parameter aufgerufen wird, funktioniert das trotzdem:

    Code
    callback(ids);

Jetzt mitmachen!

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