C++ · Robotik · Lernabenteuer ab 10 Jahren

Mission:
Finde den Ausgang! 🤖

Unser Roboter ist in einem Labyrinth gelandet. Er kennt nicht den richtigen Weg – aber er kann zählen! Entdecke, wie er Hindernisse umgeht, aus Sackgassen herauskommt und sein Ziel G findet.

Kapitel 1 · Unsere Mission

Stell dir vor, du bist der Roboter!

Du stehst auf einem Spielfeld. Vor dir sind Wege und Mauern. Irgendwo wartet der Ausgang. Was brauchst du, um ihn zu finden?

🗺️ Eine Welt aus Kästchen

Unser Spielfeld ist 12 Kästchen breit und 8 Kästchen hoch. Der Roboter kann immer nur ein Kästchen weiterfahren. Er darf nach oben, rechts, unten oder links schauen. Schräg fahren geht nicht.

. Freies Feld# MauerG Ausgang▶ Roboter

🧠 Ein kleines Gedächtnis

Unter jedem freien Kästchen liegt ein unsichtbarer Zettel. Darauf steht, wie oft der Roboter dieses Feld betreten hat.

0 bedeutet: „Hier war ich noch nie.“ 1 bedeutet: „Hier war ich einmal.“ 3 bedeutet: „Hier war ich schon dreimal.“

Das Startfeld zählt von Anfang an als 1.

Kapitel 2 · Der geheime Plan

So entscheidet unser Roboter

Es sind nur wenige einfache Regeln. Aber zusammen machen sie aus einem Roboter einen kleinen Entdecker.

1

👀 Alle vier Wege anschauen

Nach jedem Schritt prüft er vorne, rechts, hinten, links – auch dann, wenn vorne kein Hindernis steht.

2

🔍 Den besten Weg wählen

# und Kartenrand sind verboten. G hat Vorrang. Sonst gewinnt das Feld mit der kleinsten Besuchszahl.

3

🚀 Fahren und mitzählen

Der Roboter dreht sich in die gewählte Richtung, fährt ein Feld und erhöht dort den Zähler um 1.

Und wenn zwei Felder gleich gut sind?

Dann entscheidet die Reihenfolge: vorne → rechts → hinten → links. Der Roboter nimmt das erste passende Feld. Deshalb trifft er bei denselben Zahlen immer dieselbe Entscheidung.

3vorne
#
▲Roboter
0rechts
2hinten
Probier es im Kopf!

Welche Richtung gewinnt?

Der Roboter schaut nach oben. Vorne hat er 3 Besuche, rechts 0, hinten 2. Links steht eine Mauer.

Die kleinste erlaubte Zahl ist 0. Also fährt er nach rechts. Dort steht danach eine 1.

Merke: Der Roboter sucht nicht unbedingt den kürzesten Weg. Er probiert Wege aus und merkt sich, wo er schon war. Er darf auch zurückfahren – das ist oft notwendig, um eine Sackgasse zu verlassen.
Kapitel 3 · Bau dein eigenes Abenteuer!

Das interaktive Roboter-Labor: Jetzt mit Labyrinth-Baukasten

Du bist der Baumeister! Zeichne Mauern #, setze den Ausgang G und bestimme, wo dein Roboter startet. Danach schaust du zu, wie er deinen Irrgarten erforscht.

1. ✏️ Werkzeug wählen2. 👆 Auf Felder klicken oder ziehen3. 🏁 G und 🤖 Start festlegen4. ▶️ Roboter ausprobieren

🗺️ Deine Labyrinth-Werkstatt

400 ms
Schritte: 0Position: (0, 7)Blick: Osten →

🧠 Was sieht das Roboter-Gehirn?

Der Roboter ist startklar.

📋 Die letzten Schritte

Noch keine Bewegung. Starte mit „Ein Schritt“.

💡 Entdecker-Aufträge

  1. Baue eine Sackgasse. Findet der Roboter wieder heraus?
  2. Setze G hinter eine Wand. Was meldet „Weg prüfen“?
  3. Stelle die gleiche Karte mit zwei verschiedenen Startrichtungen ein. Verändert sich der Weg?
  4. Baue eine Karte, auf der der Roboter möglichst viele Schritte braucht.

Die Karte wird im Browser bearbeitet. Dein eigener Entwurf bleibt normalerweise auf diesem Gerät gespeichert. Neustart setzt nur den Roboter und die Besuchszahlen zurück – nicht das Labyrinth.

Kapitel 4 · Unser C++-Werkzeugkasten

Welche Bausteine braucht der Roboter?

Diese kleinen Programmier-Ideen wirst du gleich in den Funktionen wiedersehen.

📏

const

Eine Zahl, die gleich bleibt. Die Karte hat z. B. immer 12 Spalten.

🧭

enum Direction

Vier Richtungsnamen: NORTH, EAST, SOUTH und WEST.

🤖

struct Robot

Der Roboter-Rucksack: x, y und seine Blickrichtung.

🗺️

world[y][x]

Eine Tabelle mit Kartenzeichen: Punkt, Mauer oder Ziel.

🔢

visited[y][x]

Eine zweite Tabelle. Sie merkt sich für jedes Feld die Anzahl der Besuche.

✅

bool

Die Antwort auf eine Ja-/Nein-Frage: true oder false.

🔁

for

Wiederholt etwas mehrmals – z. B. vier Richtungen prüfen.

🎁

return und &

return gibt ein Ergebnis zurück. Mit & kann eine Funktion die übergebene Variable verändern.

Achtung bei Koordinaten: Die Position nennen wir (x, y). Im Array schreiben wir aber world[y][x] – zuerst die Zeile (y), dann die Spalte (x). Oben links ist (0, 0).
Kapitel 5 · C++ verstehen

Jede Funktion ist ein Teammitglied

In eurem Programm hat jede Funktion eine eigene Aufgabe. Hier lernst du alle 12 kennen. Auf Wunsch kannst du den passenden C++-Code aufklappen.

📚 Tipp: Erst die Erklärung lesen, dann den Code öffnen.
01
Funktion 01 · switch · return

robotSymbol()

Ein Richtungspfeil für den Roboter

🎯 Wozu brauchen wir sie?

Damit wir auf der Karte sofort sehen, wohin der Roboter schaut.

⚙️ Was macht sie?

Die Funktion bekommt eine Richtung, zum Beispiel EAST. Mit switch wählt sie das passende Zeichen: ^, >, v oder <.

💡 Beispiel: Schaut unser Roboter nach Osten, zeigt die Funktion „>“ an.
Den C++-Code ansehen
char robotSymbol(Direction dir) {
    switch(dir) {
    case NORTH: return '^';
    case EAST:  return '>';
    case SOUTH: return 'v';
    case WEST:  return '<';
    }
    return '?';
}

Gut zu wissen: Die echte Datei enthält nach manchen return-Anweisungen noch break. Sie werden nicht ausgeführt, weil return die Funktion sofort beendet.

02
Funktion 02 · for · cout · if

printWorld()

Die Karte auf dem Bildschirm malen

🎯 Wozu brauchen wir sie?

So können wir beobachten, wo der Roboter steht und welche Felder er schon besucht hat.

⚙️ Was macht sie?

Die Funktion zeichnet die Welt Zeile für Zeile. Wo der Roboter gerade steht, zeichnet sie seinen Richtungspfeil. Danach gibt sie eine zweite Karte mit den Besuchszahlen aus.

💡 Beispiel: Steht der Roboter auf (0, 7) und schaut nach Osten, erscheint dort „>“. Beim Start hat dieses Feld die Besuchszahl 1.
Den C++-Code ansehen
for (int y = 0; y < HEIGHT; y++) {
    for (int x = 0; x < WIDTH; x++) {
        if (x == robot.x && y == robot.y) {
            cout << robotSymbol(robot.direction) << ' ';
        } else {
            cout << world[y][x] << ' ';
        }
    }
    cout << endl;
}

Gut zu wissen: Dies ist der Ausschnitt, der die Spielfeld-Karte zeichnet. In der Originalfunktion wird außerdem die Besuchszahlen-Karte ausgegeben.

03
Funktion 03 · Koordinaten · Referenzen (&)

getFrontPosition()

Welches Feld liegt direkt vor mir?

🎯 Wozu brauchen wir sie?

Bevor ein Roboter losfährt, muss er wissen, welches Feld als Nächstes kommen würde.

⚙️ Was macht sie?

Die Funktion nimmt die aktuelle Position und verändert genau eine Koordinate: Norden heißt y−1, Süden y+1, Osten x+1, Westen x−1.

💡 Beispiel: Roboter bei (5, 4), Blick nach Osten: Das Feld vor ihm ist (6, 4).
Den C++-Code ansehen
frontX = robot.x;
frontY = robot.y;
switch(robot.direction) {
case NORTH: frontY--; break;
case SOUTH: frontY++; break;
case EAST:  frontX++; break;
case WEST:  frontX--; break;
}

Gut zu wissen: Durch int& frontX und int& frontY kann die Funktion beide Ergebnis-Koordinaten an die aufrufende Stelle zurückgeben.

04
Funktion 04 · bool · true/false · ||

outsideWorld()

Bin ich noch innerhalb der Karte?

🎯 Wozu brauchen wir sie?

Der Roboter darf nicht über den Rand der Welt hinausfahren.

⚙️ Was macht sie?

Er überprüft: Ist x kleiner als 0 oder mindestens WIDTH? Ist y kleiner als 0 oder mindestens HEIGHT? Wenn ja, ist das Feld außerhalb.

💡 Beispiel: Bei einer 12 × 8-Karte sind x = 0 bis 11 und y = 0 bis 7 erlaubt. (12, 3) liegt außerhalb.
Den C++-Code ansehen
bool outsideWorld(int x, int y) {
    if (x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) {
        return true;
    }
    return false;
}
05
Funktion 05 · Sensor · if · bool

obstacleAhead()

Der unsichtbare Hindernissensor

🎯 Wozu brauchen wir sie?

Diese Funktion schützt den Roboter vor Wänden und Kartenrändern.

⚙️ Was macht sie?

Zuerst ermittelt sie das Feld vor dem Roboter. Dann prüft sie den Kartenrand. Nur wenn das Feld innerhalb der Karte liegt, schaut sie nach, ob dort ein # steht.

💡 Beispiel: Vor dem Roboter ist ein #? Dann antwortet der Sensor true: „Stopp, dort ist eine Wand!“
Den C++-Code ansehen
bool obstacleAhead(const Robot& robot) {
    int frontX;
    int frontY;
    getFrontPosition(robot, frontX, frontY);
    if (outsideWorld(frontX, frontY)) return true;
    if (world[frontY][frontX] == '#') return true;
    return false;
}

Gut zu wissen: Die Reihenfolge ist entscheidend: ZUERST Rand prüfen, DANN auf world[y][x] zugreifen.

06
Funktion 06 · Zustand ändern · !

moveForward()

Genau einen Schritt fahren

🎯 Wozu brauchen wir sie?

Jetzt wird wirklich die Position des Roboters verändert – aber nur, wenn der Weg frei ist.

⚙️ Was macht sie?

Die Funktion berechnet die nächste Position. Meldet obstacleAhead() kein Hindernis, werden die Werte robot.x und robot.y aktualisiert.

💡 Beispiel: Von (5, 4) nach Osten: Nach dem Schritt steht der Roboter auf (6, 4) – sofern dort keine Wand ist.
Den C++-Code ansehen
void moveForward(Robot& robot) {
    int nextX;
    int nextY;
    getFrontPosition(robot, nextX, nextY);
    if (!obstacleAhead(robot)) {
        robot.x = nextX;
        robot.y = nextY;
    }
}

Gut zu wissen: Wichtig: Diese Funktion erhöht den Besuchszähler nicht. Das erledigt think() direkt nach dem Schritt.

07
Funktion 07 · switch · Direction

turnRight()

Einmal nach rechts drehen

🎯 Wozu brauchen wir sie?

Beim Prüfen der Nachbarn muss der Roboter seine Blickrichtung ändern können.

⚙️ Was macht sie?

Die Funktion wechselt die Richtung im Kreis: NORTH → EAST → SOUTH → WEST → NORTH. Die Position bleibt unverändert.

💡 Beispiel: Er schaut nach Norden (^). Ein Rechtsdrehen macht daraus Osten (>).
Den C++-Code ansehen
void turnRight(Robot& robot) {
    switch (robot.direction) {
    case NORTH: robot.direction = EAST;  break;
    case EAST:  robot.direction = SOUTH; break;
    case SOUTH: robot.direction = WEST;  break;
    case WEST:  robot.direction = NORTH; break;
    }
}
08
Funktion 08 · Modulo % · enum

turnLeft()

Einmal nach links drehen

🎯 Wozu brauchen wir sie?

Manchmal möchten wir den Roboter auch in die andere Richtung drehen.

⚙️ Was macht sie?

Diese Funktion verändert nur die Blickrichtung. Sie verwendet eine kurze Rechenregel mit +3 und %4.

💡 Beispiel: Norden (0) + 3 = 3: Das bedeutet Westen. „% 4“ sorgt dafür, dass die Werte im Bereich 0 bis 3 bleiben.
Den C++-Code ansehen
void turnLeft(Robot& robot) {
    robot.direction =
        static_cast<Direction>((robot.direction + 3) % 4);
}

Gut zu wissen: In der aktuellen Suchstrategie wird turnLeft() nicht aufgerufen. Der Roboter kann trotzdem nach links fahren, weil think() alle vier Richtungen mit turnRight() prüft.

09
Funktion 09 · Bedingung · Rückgabewert

goalReached()

Haben wir das Ziel erreicht?

🎯 Wozu brauchen wir sie?

Die Suche muss stoppen, sobald der Roboter auf dem Feld G angekommen ist.

⚙️ Was macht sie?

Die Funktion schaut unter den Roboter: Wenn auf seiner jetzigen Position ein G steht, gibt sie true zurück, sonst false.

💡 Beispiel: Steht der Roboter bei (10, 1), also auf dem G der Originalkarte, ist die Mission geschafft.
Den C++-Code ansehen
bool goalReached(const Robot& robot) {
    if (world[robot.y][robot.x] == 'G') {
        return true;
    }
    return false;
}
10
Funktion 10 · Array · Prioritäten · numeric_limits

getVisited()

Wie gut ist das Feld vor mir?

🎯 Wozu brauchen wir sie?

Das Roboter-Gehirn braucht für jeden Nachbarn eine Zahl, um verschiedene Wege vergleichen zu können.

⚙️ Was macht sie?

Die Funktion untersucht immer nur das Feld VOR dem Roboter. Für eine normale Zelle gibt sie ihren Besuchszähler zurück. Eine Wand oder ein Feld außerhalb bekommt eine riesige Zahl. Das Ziel G bekommt −1 und gewinnt dadurch immer.

💡 Beispiel: Vorne ist ein freies Feld mit zwei Besuchen → 2. Vorne ist G → −1. Vorne ist # → sehr große Zahl.
Den C++-Code ansehen
int getVisited(const Robot& robot) {
    int frontX;
    int frontY;
    getFrontPosition(robot, frontX, frontY);
    if (outsideWorld(frontX, frontY))
        return numeric_limits<int>::max();
    if (world[frontY][frontX] == '#')
        return numeric_limits<int>::max();
    if (world[frontY][frontX] == 'G')
        return -1;
    return visited[frontY][frontX];
}

Gut zu wissen: Die Besuchszahlen werden in visited[][] gespeichert, NICHT in world[][]. Die Weltkarte behält ihre Zeichen . # und G.

11
Funktion 11 · for · Vergleich < · Minimum

think()

Das Gehirn: Den nächsten Schritt auswählen

🎯 Wozu brauchen wir sie?

Diese Funktion entscheidet, wohin der Roboter fährt. Sie enthält unsere eigentliche Suchstrategie.

⚙️ Was macht sie?

Der Roboter schaut nach vorne, nach rechts, nach hinten und nach links. Er merkt sich die Richtung mit dem niedrigsten Wert aus getVisited(). Danach stellt er sich in diese Richtung, fährt einen Schritt und erhöht genau dort den Besuchszähler.

💡 Beispiel: Vorne 3, rechts 0, hinten 2, links Wand: Das Gehirn wählt rechts. Stehen vorne und rechts beide auf 0, gewinnt vorne.
Den C++-Code ansehen
bool think(Robot& robot) {
    Direction bestDirection = robot.direction;
    int lowestVisits = numeric_limits<int>::max();

    for (int i = 0; i < 4; ++i) {
        int count = getVisited(robot);
        if (count < lowestVisits) {
            lowestVisits = count;
            bestDirection = robot.direction;
        }
        turnRight(robot);
    }
    if (lowestVisits == numeric_limits<int>::max())
        return false;

    robot.direction = bestDirection;
    moveForward(robot);
    visited[robot.y][robot.x]++;
    return true;
}

Gut zu wissen: Vier Rechtsdrehungen bringen den Roboter wieder in die ursprüngliche Richtung. Das Zeichen < in if (count < lowestVisits) ist wichtig: Bei Gleichstand bleibt die zuerst geprüfte Richtung Sieger.

12
Funktion 12 · Startwerte · Schleife · return

main()

Hier beginnt das Abenteuer

🎯 Wozu brauchen wir sie?

main() ist der Startknopf für das ganze Programm.

⚙️ Was macht sie?

main() stellt den Roboter auf seine Startposition, zählt das Startfeld als besucht und startet dann die Schleife: Karte zeigen → Ziel prüfen → denken und fahren → kurz warten.

💡 Beispiel: Start: x = 0, y = 7, Richtung EAST. Nach spätestens 500 Schleifendurchläufen beendet die Sicherheitsgrenze die Suche.
Den C++-Code ansehen
robot.x = 0;
robot.y = 7;
robot.direction = EAST;
visited[robot.y][robot.x] = 1;
const int MAX_STEPS = 500;

for (int step = 1; step <= MAX_STEPS; step++) {
    printWorld(robot);
    if (goalReached(robot)) return 0;
    if (!think(robot)) return 1;
    this_thread::sleep_for(chrono::milliseconds(200));
}

Gut zu wissen: Wichtig: MAX_STEPS = 500 ist eine Sicherheitsgrenze, kein Beweis, dass kein Weg existiert. Das Ziel wird in dieser Programmversion am Anfang jedes Schleifendurchlaufs geprüft.

Kapitel 6 · Teste dein Wissen

Mini-Quiz für Roboter-Profis 🏅

Überlege zuerst selbst. Danach zeigt dir der Computer die Lösung.

1. Welches Feld wählt der Roboter?

Vorne: 2 · Rechts: 0 · Hinten: 1 · Links: #

2. Was passiert in einer Sackgasse?

3. Was macht visited[y][x]++?

Bonus-Aufgabe für echte Tüftler

Ändere im C++-Programm die Startposition oder baue auf Papier ein eigenes Labyrinth. Kann dein Roboter auch nach mehreren Sackgassen das G erreichen? Und was passiert, wenn du die Priorität bei Gleichstand änderst?

🔬 Extra-Wissen für Neugierige und Lehrkräfte

Findet dieser Algorithmus immer den Ausgang? Auf einem endlichen, unveränderten Spielfeld kann die Strategie „wähle den befahrbaren Nachbarn mit der kleinsten Besuchszahl“ jeden vom Start erreichbaren Bereich irgendwann erkunden – vorausgesetzt, die Suche darf unbegrenzt lange laufen und die Zähler laufen nicht über. Aber sie kann dafür sehr viele Schritte brauchen. In eurem Programm stoppt MAX_STEPS = 500 früher. Dann bedeutet „MISSION FAILED“ nicht automatisch, dass der Ausgang unerreichbar ist.

Worin unterscheidet sich die Lösung von der kürzesten Route? Diese Regel merkt sich Häufigkeiten, aber plant keinen optimalen Weg. Kürzeste Wege in solchen Gittern kann man zum Beispiel mit der Breitensuche (BFS) finden. Für unser Robotik-Labor ist die Zählstrategie besonders anschaulich.

Simulation vs. echter Roboter: Der virtuelle Roboter kennt seine exakten (x, y)-Koordinaten und speichert Besuchszähler auf einer Karte. Ein echter Roboter müsste seine Position erst mit Sensoren ermitteln.