Lektion 2

Karel the Robot

Fallunterscheidungen

Durch Kontrollstrukturen (hier die if-Abfrage) kann kontrolliert werden, wann (und später auch wie lange) bestimmte Teile des Codes ausgeführt werden

Ab Kapitel 1.3.2 „repairTheStreet“ verändert sich die Welt um Karel herrum jedes mal, wen das Kapitel neu geladen wird (siehe Video).

Also brauchen wir eine neue Möglichkeit, um unseren Code an die stetig neuen Welten anzupassen. 

Verdeutlichen wir uns das doch einfach mal am Beispiel von Kapitel 1.2.2 „fillTheHoles“ an.

Der Unterschied zu 1.3.2 „repairTheStreet“ ist, dass sich die Welt hier nicht verändert. Da zudem der Abstand (ein Loch alle 2 Felder) immer gleich ist, können wir hier ausnahmsweise „repeat“ verwenden.

Karel muss also erkennen, ob eine Wand (hier) rechts von ihm ihm ist!

Wenn unter Karel keine Wand (ein Loch) ist:

Lege einen Beeper in das Loch und laufe weiter

moveForward();
turnRight();
moveForward();
dropBeeper();
turnAround();
moveForward();
turnRight();
moveForward();

Wenn unter Karel eine Wand ist:

Lauf weiter

moveForward();

Karel kennt fünf elementare Bedingungen

F7onBeeper()Karel prüft, ob auf dem Platz, auf dem er gerade steht, ein Beeper liegt
F8beeperAhead()Karel prüft, ob sich ein Beeper auf dem Platz unmittelbar vor ihm befindet
F9leftIsClear()Karel prüft, ob sich keine Mauer zwischen ihm und dem Platz links von ihm befindet
F10frontIsClear()Karel prüft, ob sich keine Mauer zwischen ihm und dem Platz vor ihm befindet
F11rightIsClear()Karel prüft, ob sich keine Mauer zwischen ihm und dem Platz rechts von ihm befindet

So geht’s:

Achte auf die { } – Klammern

Welche Bedingung wird hier benötigt?

 

Und so wird es im Programm umgesetzt

Bedingung erfüllt
Bedingung nicht immer erfüllt

Hinweis: onBeeper() überprüft, ob Karel auf einem Beeper steht.

Hinweis: Mit einem Linksklick auf ein Kreuz, könnt ihr Beeper setzen oder entfernen!

Für alle Fälle?

Der Anfang und das Ende können schwierig sein und stimmen nicht immer direkt von Anfang an (auch wenn der Rest perfekt funktioniert).

-> Ladet jedes Kapitel mehrfach (wie ganz oben im Video gezeigt) und überprüft, ob euer Code auch wirklich immer Funktioniert!

Im Beispiel von Kapitel 1.3.2 solltet ihr also kontrollieren, was passiert, wenn ganz am Anfang oder ganz am Ende ein Loch in der Straße ist.

1.3.2 "repairTheStreet"

Der Code muss ähnlich zu dem Code oben (aus der Erklärung) aufgebaut werden.

Achte darauf, wann der Befehl moveForwand() ausgeführt werden soll. Das ist oben extra etwas anders programmiert.

void repairTheStreet(){

 

repeat(9){

if(rightIsClear()){          // Reihenfolge wichtig, falls direkt am Anfang ein Loch ist

turnRight();
moveForward();
dropBeeper();
turnAround();
moveForward();
turnRight();

}

moveForward();

}

 

 

// Reihenfolge wichtig, falls ganz am Ende ein Loch ist … Muss nochmal aufgerufen werden

if(rightIsClear()){

turnRight();
moveForward();
dropBeeper();
turnAround();
moveForward();
turnRight();

}

}

Funktioniert euer Code auch, wenn ein Loch am Anfang und am Ende ist?

Ladet das Level ein paar mal Neu und probiert es aus

1.3.3 "cleanTheRoom"

Karel hat 3 verschiedene Bewegungsmuster

Laufen

Drehen (am rechten Rand)

Drehen (am linkem Rand)

 

Warum  nicht 3 Funktionen daraus machen!

void cleanTheRoom(){

repeat(5){

Gerade();
Linksdrehung();
Gerade();
Rechtsdrehung();

}

}

 

 

 

 

void Gerade(){

repeat(9){

if(onBeeper()){

pickBeeper();

}

moveForward();

}

 

if(onBeeper()){

pickBeeper();

}

}

 

 

void Linksdrehung(){

turnLeft();
moveForward();
turnLeft();

}

 

 

void Rechtsdrehung(){

if(rightIsClear()){

turnRight();
moveForward();
turnRight();

}

}

Das Semikolon beendet einen Befehl

Zur besseren lesbarbekit (aus Platzgründen) können Befehle hintereinander geschrieben.

Dem Programm ist egal, ob in eurem Code jeder Befehl in einer neuen Zeile steht (alles untereinander) oder eben nicht. Indem ihr ein Semikolon ; setzt, weiß dass Programm, dass der Befehl an der stelle beendet ist

moveForward();

moveForward();

moveForward();  moveForward();

Üblicherweise wird jedoch jeder Befehl in eine neue Zeile geschrieben (da der Code dann leichter zu lesen ist).

Die if-else-Anweisung

Normalerweise wird das Zusammenspiel von if-else verwendet: Wenn – Sonst

Wird if nicht ausgeführt, wird else automatisch aufgerufen

Wird if ausgeführt, wird else übersprungen

So können auch komplexere Abfragen erstellt (implementiert) werden

Diese Regeln müssen beachtet werden:

In else kommt KEINE Bedingung

Wird if nicht ausgeführt, wird else automatisch aufgerufen

Wird if ausgeführt, wird else übersprungen

Stehen vorher mehrere if-Abfragen, wird else nur ausgeführt, wenn KEINE if ausgeführt wurde

Sonst (wenn eine oder mehrere if-Anweisungen) ausgeführt werden, wird else übersprungen

else muss NACH if stehen

Der Aufbau

Vervollständige das Bild - Wo endet Karels Weg? (5 Aufgaben)

Aufgabe

Ziehe das X (aus dem Satz) auf das richtige Feld.

Zusätzlich kannst du die Beeper auf das Feld ziehen und wieder entfernt.

Code 1
Code 2
Code 3
Code 4
Code 5

Hinweis: Die (eigentliche) Lösung „goal“ von Kapitel 1.3.4 überspringen wir an dieser Stelle.  1.3.4 „fillTheHoles“ betrachten wir in der nächsten Lektion: Hier werden die sogenannten Vergleichsoperatoren verwendet. 

Kapitel 1.4.1 "stealOlympicFire"

Die Treppe ist die selbe wie in Kapitel 1.2.1, aber wir können ja jetzt if/else-Abfragen.

Verwende if/else!

Erstelle dir eine Funktion Treppe() zum hochlaufen.

Das Einsammeln und herunterlaufen ist nicht sonderlich kompliziert.

void stealOlympicFire(){

Treppe();                         // würde auch mit Kapitel 1.2.1 gehen -> schöner mit if/else
pickBeeper();
moveForward();
turnRight();
repeat(6){

moveForward();

}

turnLeft();
moveForward();

}

 

// Wir unterscheiden, ob Karel momentan vor einer Stufe steht oder nicht

void Treppe(){

repeat(13){

if(frontIsClear()){

moveForward();

}

else{

turnLeft();
moveForward();
turnRight();

}

}

}

Kapitel 1.4.2 "removeTheTiles"

Nutze die repeat-Anweisung

repeat(100){ … }

Dann muss du nur unterscheiden, ob sich gerade ein Beeper in der Nähe befindet

void removeTheTiles(){

repeat(100){ 

pickBeeper();

 

if(beeperAhead()){

moveForward();

}
     

else{

turnLeft();
moveForward();

}

 

}

}