Files
Jander_Semester2/Semesterprojekt/docs/data-structures.md
Jean-Luc Makiola c205d1f49b docs: correct stale documentation and drop planning artifacts
The docs had drifted from the code and described things that never existed.

- architecture.md documented a QuitCommand class (quit/exit are aliases on
  MenuCommand) and a GameIO interface of read()/write(String); the real one is
  readLine() plus print(StyledText) with presentation hooks. Both corrected,
  along with the package diagram and the game-loop sketch.
- conventions.md listed a package tree missing save, menu, io.text and
  command.impl. Updated, including why MapLayout lives in game.
- data-structures.md claimed LinkedList was deliberately avoided (Pathfinder
  uses one for O(1) addFirst during path reconstruction), named the wrong queue
  for the Swing bridge, and listed an input history that was never built.
- Removed enhancement-ideas.md and implementation-status.md: a backlog and a
  phase tracker, neither of which documents the delivered project.

Also stop tracking the built jars. They still ship in the submission, but a
22 MB binary that changes on every build does not belong in git history.
2026-07-14 12:40:09 +02:00

4.0 KiB

Datenstrukturen

Bewusste Wahl jeder Collection — der Dozent bewertet das laut Aufgabenstellung explizit.

Übersicht

Verwendung Struktur Komplexität Lookup
Ausgänge eines Raums EnumMap<Direction, Room> O(1)
Alle Räume der Welt HashMap<String, Room> O(1)
Item-Registry (global) HashMap<String, Item> O(1)
NPC-Registry (global) HashMap<String, Npc> O(1)
Items in einem Raum LinkedHashMap<String, Item> O(1)
NPCs in einem Raum LinkedHashMap<String, Npc> O(1)
Spieler-Inventar LinkedHashMap<String, Item> O(1)
Befehlsregistry HashMap<String, Command> O(1)
NPC-Reaktionen HashMap<String, NpcReaction> O(1)
Besuchte Räume (für die Karte) LinkedHashSet<String> O(1) + Besuchsreihenfolge
BFS-Queue (Pathfinder, MapLayout) ArrayDeque<Room> O(1) FIFO
BFS-Pfadrekonstruktion LinkedList<Room> O(1) addFirst
GUI-Eingabebrücke (EDT → Worker) LinkedBlockingQueue<String> blockierend, unbegrenzt

Begründungen im Detail

EnumMap<Direction, Room> für Raum-Ausgänge

  • Direction ist Enum (NORTH, SOUTH, EAST, WEST)
  • EnumMap ist array-backed, kein Hashing nötig → schneller und kompakter als HashMap
  • Iteration in Enum-Deklarationsreihenfolge (stabil)

HashMap<String, Room> für die Welt

  • Lookup über id beim Auflösen von Exits
  • Reihenfolge irrelevant (keine Anzeige der gesamten Welt)
  • Standardwahl wenn nur Lookup gebraucht wird

LinkedHashMap<String, Item> für Inventar & Raum-Items

Zwei Anforderungen gleichzeitig:

  1. O(1) Lookup beim take letter / read letter
  2. Stabile Anzeigereihenfolge beim inventory

Eine plain HashMap würde Punkt 2 verletzen (Items springen scheinbar zufällig zwischen Ausgaben). Eine ArrayList<Item> würde Punkt 1 auf O(n) drücken und Duplikat-Prüfung verlangen.

Entscheidung "keine Stapel" (1 Item pro id) macht das Map-basierte Modell sauber.

HashMap<String, Command> für Befehle

  • O(1)-Dispatch
  • Aliase durch Mehrfach-Registrierung (put("go", goCmd); put("move", goCmd);)
  • Entspricht dem expliziten Tipp aus der Aufgabenstellung
  • Vermeidet wachsendes switch-Statement

ArrayDeque<Room> als BFS-Queue

  • Pathfinder (Auto-Travel go to <raum>) und MapLayout (Karten-Layout) sind beides Breitensuchen → brauchen eine FIFO-Queue
  • ArrayDeque ist die Standardwahl dafür: O(1) an beiden Enden, keine Node-Allokation wie bei LinkedList, bessere Cache-Lokalität

LinkedList<Room> für die Pfadrekonstruktion

Die eine Stelle, an der LinkedList die richtige Wahl ist (Pathfinder): Nach der BFS läuft man über cameFrom rückwärts vom Ziel zum Start und will den Pfad in Vorwärtsreihenfolge. addFirst() ist bei LinkedList O(1) — bei ArrayList wäre add(0, x) O(n), weil alles verschoben werden müsste.

Bewusst NICHT gewählt

Struktur Warum nicht
ArrayList<Item> für Inventar O(n)-Lookup, Duplikat-Handling nötig
HashMap<String, Item> für Inventar Anzeige-Reihenfolge instabil
TreeMap irgendwo Keine sortierte Iteration nötig, O(log n) ohne Nutzen
LinkedList als Queue dafür ist ArrayDeque besser (s.o.) — als addFirst-Liste in der Pfadrekonstruktion aber sehr wohl genutzt
Vector / Hashtable Legacy, synchronisiert (nicht gebraucht), langsamer
Map<String, String> für Exits in Domain Direction sollte Enum sein, nicht String

Threading

Single-threaded: Game-Loop liest, dispatcht, schreibt — keine parallelen Mutationen.

Ausnahme: Bei Swing-GUI läuft Input über den Event-Dispatch-Thread, der Game-Loop in einem Worker-Thread. Als Brücke dient eine LinkedBlockingQueue<String> (SwingIO): Der JTextField-ActionListener (EDT) legt die Zeile ab, der Worker blockiert in take(). Unbegrenzt statt ArrayBlockingQueue, weil es keine sinnvolle Obergrenze für getippte Zeilen gibt und ein volles offer() Eingaben verlieren würde — siehe architecture.md.