Auf diesem Blatt üben Sie den Einsatz von Lambda-Ausdrücken und Methodenreferenzen. Sie modellieren das Observer-Pattern in einem kleinen Spiel.
Klonen/forken Sie die Vorgaben "Calculator" und laden Sie das Projekt in Ihre IDE. Konfigurieren Sie Gradle für dieses Projekt.
Im Package calculator finden Sie einige Interfaces und Klassen, mit
denen man einen einfachen Taschenrechner modellieren kann: Dieser kann
einfache mathematische Operationen auf zwei Integern ausführen.
In der Klasse calculator.Calculator finden Sie vier mit TODO
markierte Stellen in der Methode setupOperationSelector:
- Erstellen Sie eine neue Java-Klasse
Sub, die das InterfaceOperationimplementiert und eine Subtraktion bereitstellt. Erweitern Sie denCalculatorund binden Sie eine Instanz dieser Klasse ein. Nutzen Sie hier keine anonymen Klassen oder Lambda-Ausdrücke. - Erstellen Sie eine weitere Operation "Mul" (Multiplikation von zwei Integern). Nutzen Sie dazu eine passende anonyme Klasse.
- Erstellen Sie eine weitere Operation "Div" (Integerdivision). Erstellen Sie einen passenden Lambda-Ausdruck.
- Für die
JComboBoxoperationSelectorwird einActionListenermit Hilfe einer anonymen Klasse definiert. Konvertieren Sie dies in einen entsprechenden Lambda-Ausdruck.
Klonen/forken Sie die Vorgaben "LockSnake" und laden Sie das Projekt in Ihre IDE. Konfigurieren Sie Gradle für dieses Projekt.
Ziel des Projekts ist es, ein kleines Swing-basiertes Spiel nach dem Vorbild von "Mouse: P.I. For Hire Lockpicking Gameplay" (16 s) zu implementieren.
Sie finden im Projekt ein lauffähiges Projektgerüst mit:
- einem lauffähigen Swing-Fenster (
Main,GamePanel) inkl. Timer-Loop, - einem fertigen Renderer (
Java2DRenderer) sowie fertiger Level-Logik (Level,LevelLoader, Beispiellevelsrc/main/resources/levels/level1.txt), - den Datentypen
CellType,Position,Direction,PinundSnake, - einer leeren Modellierung für den Spielzustand
GameStatesowie einem leeren SpielmodellGameEngine.
Das fertige Spiel mit dem Beispiellevel könnte wie im folgenden Screenshot gezeigt aussehen:

(hier noch ein Link zu einem kurzen Video [YT]/[HSBI]).
Analysieren Sie die Vorgaben und erstellen Sie ein UML-Klassendiagramm, welches die Beziehungen zwischen den Klassen zeigt.
Ergänzen Sie das Spielmodell GameEngine und die Modellierung des
Spielzustands GameState so, dass das Spiel spielbar ist und die
Pin-Mechanik korrekt funktioniert. (Die mit TODO markierten Stellen
sind ein guter Ausgangspunkt ...)
- Nutzen Sie das Observer-Pattern, so dass die GUI
GamePanelautomatisch aktualisiert wird, wenn sich der Spielzustand ändert. - Nutzen Sie das Observer-Pattern, so dass die
GameEngineautomatisch benachrichtigt wird und den Spielzustand aktualisieren kann, wenn eine konfigurierte Taste gedrückt wird.
Schreiben Sie Unit-Tests mit JUnit 6 für Ihre Implementierung der Klasse
GameState, um die Spielzustands-Logik zuverlässig zu validieren.
Decken Sie dabei mindestens diese Kernfälle ab: Bewegungen,
Pin-Interaktionen, Kollisionen/Blockaden, Gewinn-/Verlustzustände,
Initialzustand.
Checkliste:
- Mindestens 10 gut dokumentierte Tests für GameState, wie oben beschrieben.
- Tests decken alle genannten Kernfälle ab (Wand, Pin blockiert, Pin aktivierbar, Selbstkollision, Gewinnbedingung, etc.).
- Tests verwenden klare Assertions, keine Off-by-One-Fehler, eindeutige Erwartungshaltung, sprechende Testnamen, "given-when-then"-Mantra.
- Tests bauen auf Level/Pin-Setup auf, sodass sie reproduzierbar sind (Test-Fixtures).
- Korrekte Behandlung von Wand / Pin blockiert / Pin aktivierbar
- Korrekte Behandlung von Selbstkollision
- Gewinnbedingung "alle Pins gesetzt"
- Mind. 10 JUnit-Tests für
GameState - Observer-Pattern sichtbar im Code:
- UI (
GamePanel) ist Observer fürGameStatein derGameEngine GameEngineist Observer fürDirection(Tastatur-Events) imGamePanel
- UI (
- Lösung enthält mindestens 3 Lambda-Ausdrücke
- Lösung enthält mindestens 2 Methodenreferenzen
Sie finden in den Vorgaben Skizzen für TextureRenderer und
MusicPlayer. Implementieren Sie davon ausgehend einen Renderer, der
mit Texturen arbeitet. Lassen Sie im Hintergrund passend zum
Spielzustand Soundeffekte abspielen (weiterer Observer in GameEngine).
Erstellen Sie weitere Levels und ermöglichen Sie eine Level-Auswahl oder
ein Fortschreiten der Level, sobald die User das aktuelle Level gelöst
haben.
Details
Das Spielfeld besteht aus Zellen (Grid). Es gibt:
- Wände
#(blockieren Bewegung), - leere Felder
., - Pin-Slots (im Level durch Pfeile markiert, z.B.
^ v < >), - eine Startposition
Sfür die Snake.
(Symbole wie in der Level-Datei verwendet)
- Die Spielschlange ("Snake") bewegt sich automatisch in Ticks.
- Pro Tick gilt: Es wird höchstens ein Schritt in Blickrichtung ausgeführt.
- Die Schlange erhält eine "Blickrichtung", wenn eine der Tasten "W A S D" oder "H J K L" oder die Pfeiltasten gedrückt werden.
- Die Blickrichtung wird als kleine rote "Nase" angezeigt.
- Die Blickrichtung bleibt erhalten, bis eine Tasteneingabe eine neue Blickrichtung setzt oder die Blickrichtung durch eine Blockade aufgelöst wird.
- Ohne gesetzte Blickrichtung passiert nichts.
- Die Schlange wächst bei jedem erfolgreich ausgeführten Schritt (der alte Kopf wird Teil des Körpers).
- Eine Bewegung in eine Wand wird verworfen (Schlange bleibt stehen).
Jeder Pin hat:
- eine Position,
- einen Zustand
LOW(nicht gesetzt) oderHIGH(gesetzt/aktiviert), - eine Aktivierungsrichtung (z.B. Pin
<kann nur von links angestoßen werden).
Regeln:
- Wenn die Schlange von der richtigen Richtung an einen
LOW-Pin "anstößt", wird der Pin aufHIGHgesetzt. - In diesem Fall wird das Feld nicht betreten (Schlange bleibt auf der alten Position stehen).
- Ist der Pin bereits
HIGHoder die Richtung falsch, blockiert er wie eine Wand.
- Wenn die Schlange in ihren eigenen Körper laufen würde: Game Over.
- Wenn alle Pins
HIGHsind: Gewonnen (oder nächstes Level).
- Bearbeitung: Einzelbearbeitung
- Abgabe Post Mortem im ILIAS: bis 18. Mai, 08:00 Uhr
- Vorstellung im Praktikum: 18./20. Mai
Unless otherwise noted, this work is licensed under CC BY-SA 4.0.
Last modified: 9f2cf5c 2026-05-14 b03: add a checklist for the junit task
