Ulrich Vielhauer: Methode zum „Pausieren“ gesucht!

Liebe JavaScript-Gemeinde,

als Informatiklehrer habe ich mich in den vergangenen fünf Jahren intensiv darum bemüht, didaktische Konzepte für die Verwendung der Sprache JavaScript als Implementationsmedium zu entwickeln.

Für die Einführung in die Algorithmik (Anweisungssequenzen, Fallunterscheidungen, Schleifenbildung, ...) habe ich versucht, das Konzept "Niki, der Roboter" ("Karel, the robot") von Pascal nach JavaScript zu übertragen.

Für den unterrichtlichen Einsatz Meines "JavaScript-Niki" ist entscheidend, dass die Schüler(innen) die Möglichkeit haben, Niki bei der Ausführung der von ihnen erstellten Skripte beobachten zu können. Das geht aber nur, wenn Niki nach jedem Arbeitsschritt eine kleine Pause einlegt.

Ich habe das Diskussionsforum intensiv nach Lösungen durchforstet, die mit der Philosophie von JavaSkript kompatibel sind. Leider habe ich keine brauchbare Lösung gefunden.
Ich sehe auch nach längerem Grübeln keine Möglichkeit, die Methoden "SetTimeout()" und "SetInterval()" einzusetzen, weil das Problem darin besteht, dass für die Programmierung von Niki Funktionen bereitgestellt werden müssen, die hinsichtlich der Sequenzierung ihrer Nutzung tolerant sind ("vorwaerts()", "dreheLinks()", "nimmAuf()", "gibAb()").

Über einen konstruktiven Lösungsvorschlag würden sich meine Schüler(innen) und ich sehr freuen.

Hier ist die Verknüpfung zu meiner JavaSkript-Anpassung von Niki:
http://www.ulrich-vielhauer.de/materialien/09if/niki.zip

Erläuterungen:
Die Datei "niki.htm" ist die Datei, deren Kode die Schüler editieren, um Niki zu programmieren.
Die Datei "niki-hinweise.htm" enthält Hinweise, die man gelesen haben sollte, bevor man auf den Knopf "führe aus" klickt.
Die Datei "niki.js" enthält Nikis Grundprogrammierung (Library). Der Kern des von mir geschilderten Problems besteht in der "verbotenen" Funktion "warte()".

  1. Hi,

    warum nicht einfach einen JavaScript-Debugger? Venkman zum Beispiel?

    E7

  2. hi,

    Ich sehe auch nach längerem Grübeln keine Möglichkeit, die Methoden "SetTimeout()" und "SetInterval()" einzusetzen,

    Ich sehe hingegen in Javascript eigentlich keine Möglichkeit, _ohne_ diese Methoden eine "Wartezeit" zu realisieren - außer dem absoluten "Holzhammer", nach jeder abgearbeiteten Funktion mittels alert() eine Ausgabe zu machen, die dann erst wieder weggeklickt werden muss.

    weil das Problem darin besteht, dass für die Programmierung von Niki Funktionen bereitgestellt werden müssen, die hinsichtlich der Sequenzierung ihrer Nutzung tolerant sind ("vorwaerts()", "dreheLinks()", "nimmAuf()", "gibAb()").

    Oh Mann, "Niki" ist bei mir auch schon etwas länger her :-)

    Aber wenn ich mich recht erinnere, ist es für mich als Schüler doch erst mal vollkommen egal, _wie_ diese Funktionen intern arbeiten, oder?
    Sie sind quasi "black boxes", die ich aneinanderreihe, deren Innenleben mich aber nicht weiter zu interessieren hat, ist das korrekt?

    Über einen konstruktiven Lösungsvorschlag würden sich meine Schüler(innen) und ich sehr freuen.

    Falls obige Annahme korrekt ist - dann könntest du die "Niki-Funktionen" wie vorwaerts(), dreheLinks() etc. ja eventuell so umschreiben, dass sie gar nicht mehr _direkt_ die Aktion ausführen - sondern dass sie zunächst einmal nur einen Eintrag für den jeweiligen Arbeitsschritt in einem Array hinterlegen.

    _Anschließend_ durchläufst du dann dieses Array, und benutzt dabei setTimeout(), um immer nach x Millisekunden den nächsten im Array gespeicherten Arbeitsschritt durchzuführen.

    Das könnte z.b. so aussehen, dass sich die Funktion vorwaerts() nur mit dem Text "vorwaerts()" in einem neuen Array-Element verewigt, und sonst nichts tut.
    (Ich weiß nicht mehr, wie war das bei Niki, nahmen diese Funktionen auch Parameter entgegen, so á la vorwaerts(5)? Wenn ja, müsste dieser natürlich ebenfalls noch im Array abgelegt werden.)

    Wenn du jetzt das Array durchläufst, weißt du an Hand des Textes "vorwaerts()", dass du jetzt die _richtige_ Vorwaerts-Funktion aufrufen musst - nennen wir sie mal gehe_vorwartes(), die dann auch wirklich den Niki einen Schritt in der aktuellen Richtung nach vorne bewegt.

    Das sollte sich ja bspw. an Hand eines switches realisieren lassen,

      
    switch(deinArray[Schrittzähler]['Funktionsname']) {  
       case "vorwaerts()":  
         gehe_vorwaerts();  
         break;  
       case "...":  
         ...;  
    }
    

    (Klar, statt des switches könnte man hier ggf. auch eval() verwenden - eval("gehe_"+deinArray[Schrittzähler]['Funktionsname']) - aber wir wollen ja nicht Schüler, die gerade Javascript lernen, durch sowas vom Weg der Tugend abbringen, oder? ;-)

    Wenn auch noch ein Parameter benötigt wird, könnte der z.B. in deinArray[Schrittzähler]['Parameter'] hinterlegt worden sein, und dann wird im case halt
    gehe_vorwaerts(deinArray[Schrittzähler]['Parameter']);
    aufgerufen.

    Hier ist die Verknüpfung zu meiner JavaSkript-Anpassung von Niki:

    Habe ich mir jetzt zunächst mal nicht angesehen, sondern erst mal so meinen Vorschlag geschildert, wie man so etwas ggf. umsetzen könnte - was hältst du davon?

    gruß,
    wahsaga

    --
    /voodoo.css:
    #GeorgeWBush { position:absolute; bottom:-6ft; }
    1. Hallo,
      vielen Dank für die freundliche Antwort!

      Ich sehe hingegen in Javascript eigentlich keine Möglichkeit, _ohne_ diese Methoden ("SetTimeout()" und "SetInterval()") eine "Wartezeit" zu realisieren - außer dem absoluten "Holzhammer", nach jeder abgearbeiteten Funktion mittels alert() eine Ausgabe zu machen, die dann erst wieder weggeklickt werden muss.

      »»

      Habe ich auch schon in Erwägung gezogen; das ist aber fast so schlimm, wie meine "Brechstange" (s. function "warte()" in niki.js)!   :-)

      Aber wenn ich mich recht erinnere, ist es für mich als Schüler doch erst mal vollkommen egal, _wie_ diese Funktionen intern arbeiten, oder?

      »»

      Das ist korrekt!

      Falls obige Annahme korrekt ist - dann könntest du die "Niki-Funktionen" wie vorwaerts(), dreheLinks() etc. ja eventuell so umschreiben, dass sie gar nicht mehr _direkt_ die Aktion ausführen - sondern dass sie zunächst einmal nur einen Eintrag für den jeweiligen Arbeitsschritt in einem Array hinterlegen.

      Das könnte funktionieren!
      Ich werde versuchen, den Gedanken umzusetzen. Vielen Dank auch für die weiteren konkreten Umsetzungstipps.

      Gruß
      Ulrich Vielhauer

      1. hi,

        Das könnte funktionieren!
        Ich werde versuchen, den Gedanken umzusetzen.

        Noch ein Vorschlag:

        Es ist nicht unbedingt nötig, die Funktionen alle zu "doppeln", also zu vorwaerts() noch eine extra Funktion gehe_wirklich_vorwaerts() zu schreiben - sondern stattdessen könntest du die Funktionen auch mit einem optionalen Parameter aufrufen.

        Ist kein Parameter gesetzt, macht die Funktion nur ihren Eintrag ins Arrays - für deine Schüler ändert sich nichts, die rufen immer noch vorwaerts() auf.

        In deiner Funktion, die am Ende das Array mit den gesammelten Answeisungen durchläuft, rufst du dann aber vorwaerts(true) o.ä. auf, und lässt die Funktion daraufhin entscheiden, nicht den Array-Eintrag vorzunehmen, sondern ihre _wirkliche_ Funktionalität auszuführen.

        Siehe dazu http://de.selfhtml.org/javascript/objekte/function.htm#arguments ff.

          
        function vorwaerts() {  
           if(vorwaerts.arguments.length > 0 && vorwaerts.arguments[0] == true) {  
              // Code, um Niki wirklich vorwärts zu bewegen  
           }  
           else {  
              // Code, der Eintrag ins Anweisungs-Array macht  
           }  
        }
        

        Aufruf von vorwaerts() macht jetzt den Eintrag ins Array;
        vorwaerts(true), nachher von dir beim Durchlaufen des Arrays mittels setTimeout aufgerufen, bewegt Niki wirklich einen Schritt nach vorne.

        gruß,
        wahsaga

        --
        /voodoo.css:
        #GeorgeWBush { position:absolute; bottom:-6ft; }
        1. Hallo wahsaga,

          nach einer kompletten Nachtschicht ist es vollbracht:
          Niki zeigt jetzt endlich, was er tut, in allen gängigen Browsern in optisch nachvollziehbaren Schritten, ohne zwischendurch den Prozessor lahmzulegen.

          Nochmals herzlichen Dank für den entscheidenden Tipp; ich habe eine Referenz in der Niki-Hinweisdatei untergebracht!

          Falls Du oder irgendeine andere Person (Informatiklehrer beispielsweise) an einem funktionierenden JavaScript-Niki Interesse haben sollten, hier ist er:

          http://www.ulrich-vielhauer.de/materialien/09if/niki.zip

          Gruß,
          Ulrich.

          p.s.

          Es ist nicht unbedingt nötig, die Funktionen alle zu "doppeln", also zu vorwaerts() noch eine extra Funktion gehe_wirklich_vorwaerts() zu schreiben - sondern stattdessen könntest du die Funktionen auch mit einem optionalen Parameter aufrufen.

          »»

          Es hat sich letztlich doch als praktischer erwiesen, die entscheidenden Funktionen doppelt anzulegen. Der Grund hierfür liegt darin, dass ein Niki-Programm zweimal ausgeführt werden muss:

          • das erste Mal unsichtbar bei gleichzeitiger Erstellung einer Aktionsfolge,
          • das zweite Mal (nach Restaurierung der Anfangsbedingungen) optisch nachvollziehbar bei der Abarbeitung der Aktionsfolge.
            Nur so kann berücksichtigt werden, dass Niki beim Abarbeiten des Programms seine Umgebung verändert.

          Beispiel:
          "vorwaerts()" setzt hingegen einen Eintrag "v" in die Aktionsfolge und führt die Bewegung unsichtbar aus.
          "direktVorwaerts()" wird ausgeführt, wenn ein Eintrag "v" in der Aktionsfolge (realisiert in der Zeichenkette "gAktion") abgearbeitet wird oder der Benutzer auf die Taste "vorwärts" klickt.