DIGITAL
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.
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).
Behavior
folgenSofern Sie einige Hinweise haben möchten, wie man mit den Projekt anfangen könnte, lesen Sie die folgenden Hinweise.
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;
};
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: 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: 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.