JGU Logo JGU Logo JGU Logo JGU Logo

Institut für Informatik

Michael Wand
David Hartmann
Sommersemester 2020DIGITAL

Blatt 07

Projektaufgabe
Einführung in die Softwareentwicklung





Projekt Simulation von Bewegungsmustern

Letzte Änderung: 02. June 2020, 11:22 Uhr
Ansicht:   |  

Wenn viele Menschen an einem Ort sind und verschiedene Ziele haben, zu denen Sie sich bewegen, kann es schnell chaotisch werden. Denken Sie z.B. an die lokale Einkaufsmeile oder ein vergangenes Stadtfest. C++ gibt uns durch Polymorphie die Mittel dazu, unterschiedliche Verhaltensweisen elegant zu kapseln und damit eine Simulation einer solchen Menschenmenge aus der Vogelperspektive zu implementieren. Nebenbei erzeugen wir einen potenziell hohen Unterhaltungswert.


Ihre Aufgabe

Implementieren Sie eine Software zum Simulieren eines solchen Szenarios. Der Einfachheit halber können Sie die Simulation taktweise implementieren (die Akteure führen immer einen Bewegungsschritt pro Takt durch, etc.).


Die Simulation soll mindestens folgende Features unterstützen:


Als Beispiel ist oben eine Simulation der zufälligen Bewegung von Schachfiguren (statt Menschen) auf einem quadratischen 2D-Gitter ohne Wände dargestellt, die auf der Konsole ausgegeben wird. Ihre Simulation muss natürlich nicht so aussehen, aber wenn Sie Ihre Software ausreichend modular formulieren, sollte eine solche Simulation auch in Ihrer Software problemlos möglich sein. Bei der Visualisierung können Sie gerne kreativ werden.


Bonuspunkte:
Eigene Ideen für Features sind hierbei sehr gerne gesehen. (Für eine bessere Korrektur: Beschreiben Sie Ihre Idee in der Abgabe).



Zusatzfeature: Erst öffnen, wenn das Basisprogramm steht, und sich bereits Akteure auf dem Spielfeld bewegen!
(Andernfalls zerstören Sie den Lerneffekt für sich selbst.)
Wählen und Implementieres Sie auch eines der im Beispiel gezeigten Features, indem Sie eine abgeleitete Klassen definieren: Ein weiteren Typen:
  • Eine zufällige Richtung würfeln und 5 Schritte lang in diese Richtung laufen, danach neu würfeln und wiederholen
  • Einem anderen Objekt vom Typ Behavior folgen
Ein weiteres Spielfeld-Feature:
  • Definieren Sie ein Feld, an denen Personen aus der Simulation verschwinden
  • "wrap-around"-Verhalten des Spielfeldes, also z.B. "links rein, rechts raus"


Sofern Sie einige Hinweise haben möchten, wie man mit den Projekt anfangen könnte, lesen Sie die folgenden Hinweise.

(freiwillig) Implementierungshinweise zu oben dargestellter Simulation
Unsere Empfehlung für einen OOP-Start ins Klassendesign
Sie können, wenn Sie möchten, für die Simulation folgendes Grundgerüst aus abstrakten Klassen nutzen:
class MovementSystem {
public:
    virtual bool is_valid(const Position& from, const Offset& movement) const = 0;
};

class Behavior {
public:
    virtual Offset move(const Position& current_position, const MovementSystem& ms) = 0;
    virtual wchar_t get_symbol() = 0;
};

class Simulation {
public:
    virtual void draw() = 0;
    virtual void step() = 0;
};

Die Idee dahinter ist folgende:
Objekte vom Typ Behavior stellen jeweils ein sich bewegendes Objekt dar, etwa eine Person in der Menschenmenge. Die verschiedenen Verhaltensweisen können Sie in Unterklassen von Behavior ausdrücken. Die Funktion move ist dafür vorgesehen, in einem Simulationsschritt ein- oder mehrfach aufgerufen zu werden. move soll ein Offset zurückgeben, also eine Bewegung relativ zur aktuellen Position (current_position). Mithilfe des zweiten Arguments MovementSystem kann die move-Methode prüfen, ob ein Offset gültig oder ungültig ist. Ein ungültiges Offset könnte zum Beispiel daher kommen, dass die Person durch die Bewegung in einer Wand oder einer anderen Person stehen würde. Mögliche Verhaltensweisen, die man mittels Unterklassen von Behavior kodieren könnte, wären zum Beispiel:
  • keine Bewegung
  • Nur alle 3 Simulationsschritte einen Zug machen
  • etc.

Denken Sie daran, dass Sie auch mehrere Personen mit der gleichen Bewegungsstrategie in ihrer Simulation haben können, indem Sie mehrere Instanzen derselben Klasse erzeugen.
Objekte vom Typ Simulation kodieren die Simulation als Ganzes. Eine Unterklasse von Simulation muss sich irgendwie die beteiligten Personen zusammen mit deren Positionen speichern. Die Funktion draw gibt eine Darstellung des aktuellen Spielfeldes auf der Konsole aus. Die Funktion step führt einen Simulationsschritt durch, dieser könnte zum Beispiel daraus bestehen, dass einmal move auf jede Person auf dem Spielfeld aufgerufen wird und die Positionen entsprechend angepasst werden. Natürlich kann move in einem Schritt auch noch andere Dinge tun, etwa das Spielfeld verändern, neue Personen hinzufügen oder vorhandene Personen entfernen. Simulation kann außerdem Information über das Spielfeld enthalten, darunter folgendes:
  • Grenzen des Spielfeldes
  • Hindernisse, z.B. Wände, Löcher

Die Simulation muss selbstständig die Personen bewegen und dabei aufpassen, dass eventuelle Einschränkungen (z.B. nur eine Person pro Feld) eingehalten werden.
MovementSystem kodiert, wie man sich auf dem Spielfeld bewegen kann. is_valid gibt für eine feste Position und ein festes Offset zurück, ob das dadurch erreichte Feld frei ist. Die Idee ist, dass es dadurch Objekten vom Typ Behavior möglich ist, ihre Umgebung auf Hindernisse zu überprüfen. Das sollte natürlich konsistent mit dem Spielfeld selbst sein, d.h. wenn ein Zug auf dem Spielfeld nicht möglich ist (etwa weil er in einer Wand endet), sollte das durch MovementSystem auch so weitergegeben werden. MovementSystem entkoppelt die Implementierung von Behavior von der Implementierung von Simulation, d.h. eine Person in der Simulation muss nicht wissen, wie das Spielfeld intern gespeichert wird. Dadurch kann ich dieselben Personen auf unterschiedlichen Spielfeldern wiederverwenden.
Position und Offset sind der Einfachheit wegen fest kodiert und nicht austauschbar, die genaue Implementierung dieser Datentypen steht Ihnen aber frei. Eine mögliche Implementierung für Position könnte ein 2D-Punkt mit ganzzahligen Koordinaten sein.