Teil 2: Auf die Umgebung reagieren

Herzlich willkommen beim zweiten Teil unseres kostenlosen Kurses Programmieren lernen für Anfänger.

Dieser Teil baut auf dem Wissen des ersten Teils auf. Lass uns nochmals kurz zusammenfassen was wir schon gelernt haben.

  • Wir haben gelernt einfache Funktionen wie forward(), turnLeft() oder takeStone() aufzurufen um Nana zu steuern.
  • Wir wissen, dass Fehler ganz normal und wichtig sind! Wir versuchen Fehlermeldungen zu verstehen um daraus zu lernen. So können wir beim nächsten Mal das Problem schneller lösen.
  • Abstände, Einrückungen und Kommentare helfen den Programmcode übersichtlich und verständlich zu halten. So können wir Fehler schneller finden und uns in altem Code noch gut zurechtfinden.
  • Wir haben gelernt mit dem Schlüsselwort fun eigene Funktionen wie turnRight oder forward3 zu erstellen. So halten wir unseren Code kurz und müssen uns nicht dauernd wiederholen.

Falls du dich an manche Dinge nicht mehr so gut erinnern kannst, schau einfach nochmal im ersten Teil „Deine ersten Schritte beim Programmieren“ vorbei und löse die Aufgaben dort.

Im letzten Beispiel des ersten Teils sind wir auf ein, für uns noch nicht zu schaffendes, Problem gestoßen. Nana muss zwei Level mit dem gleichen Programmcode meistern. Bisher waren alle unsere Programme ein fix einprogrammierter Ablauf von Befehlen. In diesem Teil lernst du dynamisch auf deine Umgebung zu reagieren und so Nana flexibel zum Ziel zu steuern.

Hier nochmal das Beispiel mit der Lösung für den ersten Level.


fun forward2() {
    forward()
    forward()
}

fun forward3() {
    forward2()
    forward()
}

fun turnRight() {
    turnLeft()
    turnLeft()
    turnLeft()
}

//sampleStart
fun solution() {
    forward3()
    takeStone()
    takeStone()
    forward()
    takeStone()
    forward()
}
//sampleEnd

Im zweiten Level explodiert Nana, weil sie versucht einen Loridium Stein aufzunehmen der nicht da liegt. An dieser Stelle liegen im ersten Level noch zwei Steine, im zweiten aber nur noch einer.

Tipp: In Beispielen mit mehreren Leveln, kannst du nach dem „Zurücksetzen“ mit den Pfeilen oben zwischen den Leveln wechseln.

Funktionen, die Antworten liefern

Du brauchst eine Möglichkeit um zu überprüfen ob ein Stein am Feld liegt, bevor du ihn versuchst aufzunehmen. Nana hat dazu die Funktion fieldHasStone() im Bordcomputer einprogrammiert. Übersetzt bedeutet das „Feld hat Stein“. Diese Funktion ist etwas anders als die uns bisher bekannten Funktionen. Die uns bekannten forward() und turnLeft() bewegen Nana. Die Funktion fieldHasStone() hingegen beantwortet eine Frage. Sie sagt ob auf dem Feld auf dem Nana gerade steht ein Loridium Stein liegt. Die Antwort ist also entweder „Ja“ oder „Nein“. Beim Programmieren wird anstatt „Ja“ und „Nein“, true und false verwendet. Auf Deutsch also „wahr“ und „falsch“. Lass uns mal ausprobieren fieldHasStone() aufzurufen.

Aufgabe: Führe den Code unten aus und schaue was passiert.


//sampleStart
fun solution() {
    fieldHasStone()
}
//sampleEnd

Viel hat sich da ja jetzt nicht gerade getan. Nana steht einfach nur rum und nichts passiert? Wie oben beschrieben ist fieldHasStone() eine Funktion die eine Antwort liefert. Nur in diesem Fall machen wir nichts mit der Antwort. Das ist ein wenig so als wenn du eine Freundin fragst: „Magst du ein Eis?“ Sie sagt zwar „Ja!“ aber du hörst einfach nicht zu und machst nichts mit der Information. Das ist etwas unfreundlich, da hättest du gar nicht erst fragen brauchen. 😀 Genauso ist es hier, wir fragen ob auf dem Feld ein Stein liegt, machen aber nichts weiter mit der Information. Der Aufruf ist in dieser Form also nutzlos. Wir müssen mit der Information erst etwas anfangen.

Beim Programmieren nennt man Funktionen die eine Antwort liefern, „Funktionen mit Rückgabewert“. Der Rückgabewert ist die Antwort. Im Fall von fieldHasStone() ist die Antwort immer true oder false. Das nennt man einen „Boolean“ Rückgabewert.

Auf English sagt man zu Rückgabewert „return value“.

Programmteile bedingt ausführen mit „if“

Was wir brauchen ist eine Möglichkeit takeStone() nur dann aufzurufen, wenn fieldHasStone() mit true antwortet. Kotlin hat dazu den Befehl if, auf Deutsch also „wenn“, eingebaut. Dieser funktioniert so:

if (/* Code der mit true oder false antwortet */) {
    // Dieser Code hier wird nur ausgeführt wenn 
    // der Code in den Klammern oben mit true antwortet.
}

Direkt hinter dem if Befehl kommt, zwischen runden Klammern, ein Stück Code das mit einem Boolean-Wert (also true oder false) antworten muss. Man nennt diesen Code-Teil des if-Befehls „Bedingung“. Also zum Beispiel if (fieldHasStone()). Danach kommt ein Block an Code der zwischen geschwungenen Klammern steht. Dieser Block wird nur dann ausgeführt, wenn die Bedingung mit true antwortet. Wenn sie mit false antwortet, wird dieser Teil einfach übersprungen.

Schaffst du es mit der Hilfe von if und fieldHasStone() den Code unten so umzubauen, damit Nana beide Level erfolgreich absolviert?

Aufgabe: Passe den Code im folgenden Eingabefeld so an, dass Nana beide Level erfolgreich absolviert.

Hinweis: Nimm der etwas Zeit um es auszuprobieren. Falls du etwas Hilfe benötigst, findest du direkt unter dem Beispiel einen Tipp.


fun forward2() {
    forward()
    forward()
}

fun forward3() {
    forward2()
    forward()
}

fun turnRight() {
    turnLeft()
    turnLeft()
    turnLeft()
}

//sampleStart
fun solution() {
    forward3()
    takeStone()
    forward2()
}
//sampleEnd

Wie ist es dir dabei gegangen? Hat alles geklappt? Hier ein Tipp. 🙂 Der Code unten nimmt einen Stein nur dann, wenn er da liegt. Wenn nicht, wird takeStone() einfach übersprungen. So kannst du vermeiden, dass Nana einen Loridium Stein aufnimmt den es nicht gibt und explodiert.

if (fieldHasStone()) {
    takeStone()
}

Hilft dir das weiter? Versuche es gleich nochmal!

Falls du es nach ein paar mal versuchen nicht weiterkommst, schau dir hier die ganze Lösung an. So fällt dir das nächste Beispiel bestimmt gleich leichter!


fun forward2() {
    forward()
    forward()
}

fun forward3() {
    forward2()
    forward()
}

fun turnRight() {
    turnLeft()
    turnLeft()
    turnLeft()
}

fun solution() {
    forward3()
    // Wenn kein Stein am Feld liegt überpringen wir das Aufheben.
    if (fieldHasStone()) {
       takeStone()
    }
    forward2()
}
//sampleStart
// Klappe diesen Block auf um unsere Lösung zu sehen
//sampleEnd

Einrückungen, Leerzeichen und sonstige Abstände spielen in Kotlin in den meisten Fällen keine Rolle. So auch im Zusammenhang mit dem if Befehl. Die folgenden Versionen sind für Kotlin alle genau gleich.

// Version 1
if (fieldHasStone()) {
    takeStone()
    forward()
}

// Version 2
if (fieldHasStone()) {
takeStone()
forward()
}

// Version 3
if (fieldHasStone())
{
    takeStone()
    forward()
}

Kotlin erlaubt sogar die geschwungenen Klammern wegzulassen. In diesem Fall wird nur der direkt hinter den runden Klammern kommende Befehl übersprungen, wenn die Bedingung false zurückliefert. Ohne Klammern kann also nur ein einziger Befehl übersprungen werden.

// Version 4
if (fieldHasStone())
    takeStone()

// Version 5
if (fieldHasStone()) takeStone()

// Version 6
if (fieldHasStone()) { takeStone() }

// Version 7 (Achtung!)
if (fieldHasStone())
    takeStone()
    forward()

Versionen 4 bis 7 machen alle genau das gleiche. Aufpassen bei Nummer 7! Auch hier wird nur der Befehl takeStone() übersprungen, wenn kein Stein im Feld liegt. Der Befehl forward() wird hingegen immer ausgeführt. Das ist, weil wir keine geschwungenen Klammern verwenden. Kotlin überspringt somit nur den ersten Befehl hinter der Bedingung.

Hier ist nochmals Version 7 mit besserer Formatierung. Du erkennst auf den ersten Blick welcher Code übersprungen wird und welcher nicht.

fun solution() {
    // version 7 (besser formatiert)
    if (fieldHasStone())
        takeStone()

    forward()
}

Wie du siehst, ist es sehr wichtig den Code gut einzurücken. In der Praxis ist Version 1 sehr beliebt. Sie ist kompakt, übersichtlich und erlaubt auch mehrere Befehle zu überspringen.

Hier ein weiteres Beispiel, dass du nur mit dem if Befehl lösen kannst. Die Steine werden bei jedem Mal neu Ausführen zufällig am Planeten verteilt. Es liegt aber immer maximal ein Stein auf einem Feld.

Aufgabe: Löse das Beispiel unten mit der Hilfe des if-Befehls.

Tipp: Versuche das Programm Schritt für Schritt zu lösen. Führe das Programm dazwischen oft aus. So siehst du gleich ob noch alles funktioniert.


fun turnRight() {
    turnLeft()
    turnLeft()
    turnLeft()
}

//sampleStart
fun solution() {
    
}
//sampleEnd

Hast du es geschafft? Wie lange ist dein Code geworden? Schaffst du es deine solution Funktion in weniger als 15 Zeilen zu programmieren? Tipp: Erstelle eine Funktion die Nana nach vorne bewegt und dann den Stein nimmt, falls er dort liegt. Wenn du nicht mehr ganz sattelfest im Erstellen von Funktionen bist, schau einfach nochmal im entsprechenden Abschnitt in Teil 1 dieses Kurses nach.


fun turnRight() {
    turnLeft()
    turnLeft()
    turnLeft()
}

/**
 * Bewegt Nana nach vorne und nimmt einen Stein,
 * wenn er auf dem neuen Feld liegt.
 */
fun forwardAndTake() {
    forward()
    if (fieldHasStone()) {
        takeStone()
    }
}

fun solution() {
    forwardAndTake()
    turnLeft()
    forwardAndTake()
    turnRight()
    forwardAndTake()
    forwardAndTake()
    turnRight()
    forwardAndTake()
    turnLeft()
    forwardAndTake()
    forwardAndTake()
    turnLeft()
    forward()
}
//sampleStart
// Klappe diesen Block auf um unsere Lösung zu sehen
//sampleEnd

Super! Das war schon ein sehr komplexes Level. Obwohl die Steine völlig zufällig verteilt sind, kann Nana sie alle einsammeln.

Entscheidungen treffen mit „if“ und „else“

Im nächsten Beispiel muss Nana ein Labyrinth durchfahren. Die Steine am Feld dienen dabei als Wegweiser. Wenn ein Loridium Stein auf dem Feld liegt, geht es nach rechts weiter, ansonsten nach links. In diesem Fall müssen wir also abhängig davon ob ein Stein auf dem Feld liegt die eine oder andere Aktion ausführen. Der if-Befehl kann dafür mit else erweitert werden. „else“ kann ins Deutsche mit „andernfalls“ oder „sonst“ übersetzt werden.

if (/* Bedingung */) {
    // Dieser Code wird ausgeführt, wenn die Bedingung mit "true" antwortet.
} else {
   // Ansonsten wird dieser Code ausgeführt.
}

Wenn die Bedingung mit true antwortet, wird der Code-Block direkt hinter if ausgeführt und der hinter else übersprungen. Antwortet die Bedingung mit false, ist es genau umgekehrt. Der if-Block wird übersprungen und der else-Block ausgeführt. Es wird also abhängig von der Bedingung der eine oder andere Code ausgeführt.

Schaue dir beide Level im folgenden Beispiel an. Kannst du die Gemeinsamkeit zwischen ihnen erkennen? Vergiss nicht, die Steine dienen hier als Wegweiser. Wenn ein Stein auf dem Feld liegt, geht es nach rechts weiter. Wenn kein Stein auf dem Feld liegt nach links. Viel Spaß beim Lösen dieser Aufgabe mit if und else!


fun turnRight() {
    turnLeft()
    turnLeft()
    turnLeft()
}

//sampleStart
fun solution() {
    
}
//sampleEnd

Wie ist es dir dabei gegangen? Hat alles gleich geklappt? Hier noch ein Tipp: Nach jeder Drehung muss Nana zweimal gerade aus fahren. Das ist die Gemeinsamkeit in beiden Leveln.

Okay, ich nehme mal an du hast es geschafft. Falls nicht, sende uns eine e-mail und wir helfen gerne weiter. Du kannst auch gerne unten ein Kommentar hinterlassen.

Kannst du deinen Code noch kürzer und übersichtlicher gestalten, indem du Programmteile in eigenen Funktionen auslagerst?

Unten findest du wie immer unsere Lösung für diese Aufgabe.


fun turnRight() {
    turnLeft()
    turnLeft()
    turnLeft()
}

fun move() { 
    if (fieldHasStone()) {
        takeStone()
        turnRight()
    } else {
        turnLeft()
    }
    
    forward()
    forward()
}

fun solution() {
    move()
    move()
    move()
    move()
    move()
    move()
    move()
}
//sampleStart
// Klappe diesen Block auf um unsere Lösung zu sehen
//sampleEnd

Obwohl wir schon eine eigene Funktion verwenden, ist der Code noch immer ziemlich lange. Außerdem scheint es ziemlich sinnlos, dass wir move() ganze acht mal direkt hintereinander schreiben müssen. Was wenn der Level viel größer wäre?

Im nächsten Teil dieses Kurses „Programmieren lernen für Anfänger„, lernen wir eine sogenannte Schleife kennen. Mit dieser können wir solchen Code optimieren und Nana noch viel flexibler steuern. Wir werden lernen den Boardcomputer so zu programmieren, dass Nana unbekannte Labyrinthe völlig selbständig lösen kann.

Melde dich bei unserem Newsletter an! Wir erinnern dich sobald der nächste Teil verfügbar ist 🙂

19 Kommentare zu „Teil 2: Auf die Umgebung reagieren“

    1. also, macht mega Spass! Nur eine Frage zum Verständnis: Muss die if / else Abfrage immer in einer Funktion festgelegt werden? Denn wenn die if / else Abfrage unter fun solution steht dann macht der das NICHT !!
      Danke für die Antwort

  1. warte gespannt auf den dritten teil oder halt weitere, wenn es nich dazu kommt bitte ich um gute andere Seiten um zu programmieren zu lernen.
    Danke für ihr Verständnis

  2. Hallo,

    erst einmal Danke für die Mühe. Leider wird eure eigene Lösung – die auch meine ist – nich angenommen.

    fun turnRight() {
    turnLeft()
    turnLeft()
    turnLeft()
    }

    fun solution()
    {if (fieldHasStone()) {
    turnLeft()
    } else {
    turnRight()}

    Zum einen ist der erste Teil bereits im Hintergrund vorhanden.
    Beim zweiten Teil gibt es die Fehlermeldung
    „Expecting ‚}'“

    Könnte mir das bitte einer erklären?

    Vielen lieben Dank

    1. Hey
      Falls du das noch liest 😀
      Ich denke dir fehlt ganz zum Schluss noch eine geschweifte Klammer } (das sagt dir ja auch die Fehlermeldung), die deine fun solution eingrenzt. Bisher schließt deine letzte Klammer nur die „else“ Bedingung.
      Und wenn die Funktion turnRight() schon gegeben ist, musst du sie natürlich nicht nochmal selbst hinschreiben.

    2. dominic.czyszczon

      Hallo es ist gemeint
      fun turnRight() {
      turnLeft()
      turnLeft()
      turnLeft()
      }

      fun solution()
      {if (fieldHasStone()) {
      turnLeft()
      } else {
      turnRight()
      }
      Nicht
      fun turnRight() {
      turnLeft()
      turnLeft()
      turnLeft()
      }

      fun solution()
      {if (fieldHasStone()) {
      turnLeft()
      } else {
      turnRight()}

  3. bei mir kommt immer die Fehlermeldung expecting was habe ich hier falsch gemacht ? zur info das unterste zeichen ist anscheinend das problem ?
    fun solution() {
    forward()
    if (fieldHasStone()) {
    takeStone()
    forward()

    }

  4. Ich finde diesen Kurs einfach genial und bin euch so dankbar, dass dieser Kurs nur für Anfänger und kostenlos ist. Ich wollte schon immer mal Programmieren lernen, habe aber leider nichts gefunden. Ich bin 15 und in der Schule lernen wir nur so „Kindergarten programmieren“.
    Ich muss den dritten Teil haben, kann es kaum erwarten 🤣.
    LG Bünni 🙃

  5. Hallo Maximze,
    Als Antwort auf deine Frage:
    Auf der Internetseite der „Sendung mit der Maus“ des WDR gibt es einen Kurs zum Programmieren von Computerspielen mit der – auch für Anfänger/Innen geeigneten – Programmiersprache „Scratch“.
    Hilft dir das weiter?

  6. Hallo,
    ich verstehe die letzte Aufgabe nicht ganz: Soll Nana die Steine, sofern vorhanden, auch einsammeln oder sich nur nach rechts drehen bzw. nach links, wenn kein Stein da liegt?

  7. Hey, ich freue mich schon sehr auf den nächsten Kurs!
    (Hab festgestellt. dass euer Programm die „repeat (Anzahl) {Funktion}“ Funktion zulässt. Aber autonom ist das ja noch nicht richtig XD)
    LG Konstantin

  8. Thomas Winter

    Ich hab eine frage warum wen ich bei dem 2. Level schon bei der Fahe bin bewegt sich es bei mir noch weiter uns so drifte ich ins all das hier ist meine Programierung.
    fun solution() {
    turnLeft()
    forward2()
    if ( fieldHasStone()){
    takeStone()
    turnRight()
    forward2()
    turnLeft()
    forward2()
    takeStone()
    turnRight()
    forward2()
    turnLeft()
    forward2()
    turnLeft()
    forward2()
    takeStone()
    turnRight()
    forward2()
    }
    turnLeft()
    forward2()
    if ( fieldHasStone()){
    takeStone()}
    turnLeft()
    forward2()
    if ( fieldHasStone()){
    takeStone()}
    turnRight()
    forward2()
    if ( fieldHasStone()){
    takeStone()}
    turnRight()
    forward2()
    turnLeft()
    forward2()
    turnLeft()
    forward2()}
    fun forward2() {
    forward()
    forward()
    }
    fun forward3(){
    forward()
    forward()
    forward()
    }
    Ich hoffe mir kann jemand schnell helfen weil ich umbedingt mit dem Kurs fertig werden will.

Kommentar verfassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.