Robots

Aus Vokabulabor
Zur Navigation springen Zur Suche springen

Links

Zielsetzung

Es soll ein Programm entwickelt werden, das eine grafische Robotersimulation implementiert. Das ganze wird mit ASCII-Grafik dargestellt.

Modell

  • Es gibt ein rechteckiges Gelände.
  • In dem Gelände gibt es rechteckige Hindernisse.
  • Es gibt N Roboter, jeweils als Punkt gezeichnet.
    • Jeder Roboter hat einen Namen: A...Z
    • Jeder Roboter hat eine zufällige Ausgangsposition im Gelände.
    • Jeder Roboter hat einen Zielpunkt (markiert mit "a"..."z"), zu dem er sich bewegen soll
  • Ein Roboter kann nicht dort sein, wo sich ein Hindernis oder ein anderer Roboter befindet.
  • Ein Roboter kann sich immer nur auf einen benachbarten Punkt bewegen (wenn sich dort nichts anderes befindet).
  • Ein Simulationsschritt: Die Roboter bewegen sich eine Position weiter, wenn sie ihr Ziel noch nicht erreicht haben.
  • Wenn der Roboter sein Ziel erreicht hat, bleibt er dort stehen.
  • Wenn sich kein Roboter mehr bewegt, dann ist die Simulation beendet.

Farben

Die Farben werden in einer ASCII-Grafik mit Zeichen dargestellt. Weiß (genauer die Hintergrundfarbe) ist das Leerzeichen. Es gibt eine Wert DEFAULT_COLOR: Wenn dieser auftaucht, soll das Objekt seine eigene Farbe nehmen.

Die Klasse Sheet

  • Definiere eine Klasse Sheet, die das "Zeichenblatt" modeliert.
  • Parameter des Konstruktors: die Breite und die Höhe des Blattes.
  • Wir speichern die "Punkte" in einer Liste von Zeilen: Jede Zeile ist ein String mit den Spalten, also $width Zeichen.
  • Ein Punkt x, y wird also durch $list->lines[y][x] adressiert.

Konstruktor

  • Erzeuge die Zeilenliste $height Einträgen, jeder Eintrag mit Länge $width.

clearTerminal()

Damit die ASCII-Grafik funktioniert, müssen wir ein "Terminal löschen" einbauen:

    public function clearTerminal()
    {
        echo "\x1b\x5b\x48\x1b\x5b\x32\x4a\xc";
    }

isOccupied()

  • Definiere die Methode isOccupied, die als Parameter x und y bekommt und als Ergebnis eine Wahrheitswert liefert, ob der Punkt schon belegt ist.
  • Belegt ist ein Punkt, wenn dort eine Farbe außer Weiß ist und wenn dort keine Farbe eines Zielpunktes ist.

setPoint()

  • Definiere eine Methode, die einen Punkt in das Blatt einträgt. Parameter: x, y, color

setRandomPosition()

  • Definiere eine Methode, die in einen Punkt (als Parameter) eine zufällige Position einträgt, die noch nicht belegt ist.

draw()

  • Definiere eine Methode, die das Blatt ins Terminal ausgibt.

Klasse Point

  • Definiere eine Klasse, die die Attribute x, y und Color hat.
  • Definiere den Konstruktor mit den Parametern x, y, und color

draw()

  • Definiere eine Methode, die als Parameter ein Blatt und eine Farbe bekommt.
  • Zeichne die Position des Punktes in das Blatt: Wenn die Farbe den Wert DEFAULT_COLOR hat, soll die eigene Farbe genommen werden.

Klasse Rectangle

  • Leite die Klasse Rectangle aus Punkt ab, mit den zusätzlichen Attributen width und height.
  • Der Konstruktor hat die Parameter x, y, width, length und color

draw()

  • Definiere eine Methode, die als Parameter ein Blatt und eine Farbe bekommt.
  • Zeichne die Position aller Punkte des Rechteck in das Blatt: Wenn die Farbe den Wert DEFAULT_COLOR hat, soll die eigene Farbe genommen werden.

Klasse Robot

  • Leite die Klasse Robot von Punkt ab, mit den zusätzlichen Parametern target, colorTarget, xDirection und yDirection
    • xDirection kann die Werte +1 und -1 annehmen: wenn ein Hindernis umgangen werden soll, wird die x-Koordinate um diesen Wert geändert.
    • yDirection kann die Werte +1 und -1 annehmen: wenn ein Hindernis umgangen werden soll, wird die y-Koordinate um diesen Wert geändert.
  • Der Konstruktor hat die Parameter color und das Blatt sheet
  • Im Konstrutor wird die zufällige Startposition eingestellt ($sheet->setRandomPosition())

setTarget()

  • Wenn es noch kein Target gibt ($this->target == null): Erzeugen eines Targets.
  • Sonst: Löschen des Punktes im Blatt: Zeichnen mit der Farbe weiß.
  • Zufällige Position des Targets erzeugen ($sheet->setRandomPosition()).

checkDirection()

  • Wenn die x-Koordinate den Wert 0 hat, wird xDirection auf +1 gesetzt: Damit wird die Richtung vom linken Rand weg eingestellt.
  • Wenn die x-Koordinate den Wert $sheet->width - 1 hat, wird xDirection auf -1 gesetzt. Damit wird die Richtung vom rechten Rand weg eingestellt.
  • Analog yDirection

move()

  • Erzeuge die Methode mit dem Parameter sheet und dem Ergebistyp bool.
  • Der Code kommt später. Liefere false als Ergebis.

Klasse Simulator

  • Erzeuge eine Klasse, mit den Attributen:
    • sheet: das Zeichenblatt.
    • Ein Array statics, das die Hindernisse enthält.
    • Ein Array mobiles, das die Roboter enthält.
  • Der Konstruktor bekommt den Parameter sheet.

add()

  • Definiere eine Methode add, die ein Element bekommt und den Parameter isStatic (als bool).
  • Wenn isStatic true ist, trage in die Liste statics ein.
  • Sonst trage in die Liste mobiles ein.
  • Zeichne das Element.

buildBarriers()

  • Definiere eine Methode, die als Parameter die Anzahl Reihen (rows) und Spalten (cols) bekommt.
  • Die Hindernisse (Rechtecke) sollen eine Breite width und Höhe height haben.
    • $width = $this->sheet->width / $rows / 2;
    • Analog $height
  • Der Abstand zum nächsten Hindernis soll $width bzw. $height haben
  • Der Abstand vom Außenrand soll die Hälfte von $width bzw. $height sein.

buildRobots()

  • Die Methode hat den Parameter count.
  • Es werden count Roboter erzeugt und in der Liste mobiles eingetragen.

show()

Die Methode löscht das Terminal (clearTerminal) und zeichnet das Blatt.

step()

  • Die Methode liefert einen bool-Wert: Wenn es eine Bewegung gab: true, sonst false.
  • Die Methode hat eine Variable $countMoves.
  • In einer Schleife werden alle Elemente aus mobiles geholt und deren Methode move() aufgerufen.
  • Wenn diese den Wert true liefert (Element hat sich bewegt), dann erhöhe $countMoves.
  • Liefere false, wenn $countMoves gleich 0 ist, sonst true

Hauptprogramm

  • Erzeuge ein Blatt.
  • Erzeuge einen Simulator.
  • Erzeuge Hindernisse.
  • Erzeuge Roboter.
  • Eine Schleife: Solange es Bewegungen gibt, führe die Methode step() aus, danach warte 1 Sekunde.
  • Gib die Anzahl der Schleifen aus, die benötigt wurden.
  • Probiere das Programm aus.

Implementierung der Methode Robot::move()

  • Setzen den Rückgabewert $rc auf false.
  • Prüfe, ob der Zielpunkt erreicht ist.
  • Wenn nein:
    • Setze die Variablen $x und $y auf die aktuelle Position
    • Wenn $x nicht den Wert von $target->x hat, ändere $x so, dass $x näher an $target->x ist
    • Analog $y
    • Korrigiere die Richtungen, wenn nötig: checkDirection()
    • Wenn der Punkt (x, y) belegt ist:
      • Bewege x in die eingestellte Richtung
      • Wenn der Punkt (x, y) belegt ist: Bewege y in die eingestellte Richtung
    • Wenn der Punkt (x, y) nicht belegt ist:
      • Zeichne das Ziel.
      • Lösche die alte Position (Zeichnen mit Weiß).
      • Merke die Position.
      • Zeichne den Punkt
      • Merke, dass bewegt wurde: $rc = true