Files
4Gewinnt/TECHNISCHE_SPEZIFIKATION.md

41 KiB
Raw Permalink Blame History

Technische Spezifikation 4Gewinnt

1. Projektübersicht

Name der Anwendung

4Gewinnt (Vier-Gewinnt als lokaler und online Multiplayer).

Ziel der Anwendung

Bereitstellung eines browserbasierten Vier-Gewinnt-Spiels mit zwei Betriebsarten:

  • Lokaler Modus (zwei lokale Spieler, optional Bot-Spieler)
  • Online-Modus (zwei entfernte Spieler über Spielcode und SignalR)

Problem, das gelöst wird

Die Anwendung löst die technische Herausforderung, ein rundenbasiertes Rasterspiel gleichzeitig:

  • mit reaktiver Benutzeroberfläche,
  • mit serverautoritärer Validierung der Spielzüge,
  • mit Echtzeit-Event-Übertragung,
  • und mit einfacher Lobby-Logik über 6-stellige Codes zu betreiben.

Zielgruppe

  • Spieler:innen, die im Browser schnell ein Vier-Gewinnt-Spiel starten wollen
  • Entwickler:innen/Lernende für ein Referenzprojekt zu Vue 3 + SignalR + ASP.NET Core

Hauptfunktionen

  1. Spiel erstellen mit variabler Feldgröße
  2. Spiel beitreten über sechsstelligen Code
  3. Echtzeit-Synchronisation von Spielzustand und Spielende
  4. Gewinn-/Unentschieden-Erkennung serverseitig
  5. Lokales Spiel (ohne externen Gegenspieler)
  6. Wiederholungsrunde (Replay-Code) nach Spielende

2. Systemarchitektur

Beschreibung der Gesamtarchitektur

Das Projekt ist als zweiteilige Client-Server-Architektur umgesetzt:

  • Frontend (GUI): Vue 3 SPA, Rendert UI und delegiert Spiellogik-Kommandos an SignalR-Verbindung
  • Backend (API): ASP.NET Core Web API + SignalR Hub, verwaltet Spielinstanzen in Memory

Frontend-/Backend-Struktur

  • Frontend enthält:
    • Routing und Seitenzustände
    • UI-Komponenten für Menüs, Spielfeld und Spielende
    • Client-seitige Orchestrierung (OnlineGame, LocalGame)
    • Transport-Layer (GameConnection) für SignalR
  • Backend enthält:
    • Hub-Endpunkte als Eintrittspunkt für Spieloperationen
    • Game-Manager als fachliche Orchestrierung
    • Repository als In-Memory-Persistenz
    • Domain-Modelle (Spiel, Feld, Spieler, DTOs)

Verwendete Technologien

  • Vue 3 + TypeScript + Vuetify + Vite
  • ASP.NET Core 9 + SignalR + Swagger/OpenAPI

Datenfluss zwischen Frontend und Backend

  1. Frontend öffnet SignalR-Verbindung zu /api/gamehub.
  2. Frontend ruft Hub-Methoden (CreateGame, JoinGame, Drop, ...).
  3. Hub delegiert an IGameManager.
  4. GameManager liest/schreibt via IGameRepository.
  5. GameManager sendet Events an einzelne Clients oder Gruppen.
  6. Frontend aktualisiert lokalen State über Event-Callbacks.

Wichtige Designentscheidungen

  • Serverautorität: Züge werden im Backend validiert.
  • In-Memory-Repository: schnell, aber nicht persistent.
  • Gruppenkommunikation: SignalR-Gruppen nach game.Id.
  • DTO-Transformation: 2D-Array im Backend wird in jagged array (int[][]) für Frontend gewandelt.
  • Zeitgesteuerte Aufräumlogik: Spiele werden nach Endbedingungen entfernt.

3. Technologie-Stack

Kategorie Technologie Rolle
Frontend Framework Vue 3 Komponenten, Reaktivität, SPA
Frontend Sprache TypeScript Typsicherheit in UI- und Spiel-Logik
UI-Bibliothek Vuetify 3 Material Design Komponenten
Frontend Routing Vue Router Seitenwechsel (/, /localMode, /onlineMode)
Echtzeitkommunikation (Client) @microsoft/signalr Verbindungsaufbau, Invoke, Event-Handling
Build Tool Frontend Vite Dev-Server, Build, Alias-Auflösung
Backend Framework ASP.NET Core 9 Hosting, DI, HTTP-Pipeline, SignalR
Echtzeitkommunikation (Server) ASP.NET SignalR Hub-Methoden, Gruppen- und Client-Events
API-Dokumentation OpenAPI + Swagger Test/Inspektion im Development
Persistenz In-Memory (GameRepository) Laufzeitverwaltung von Spielen
Lösung/Build .NET SDK + npm Backend/Frontend Build und Start

4. Projektstruktur

/
├── API/                            # Backend (.NET 9)
│   ├── Controllers/                # Status-Controller + SignalR Hub
│   ├── Models/
│   │   ├── DataClasses/            # Value Objects (z. B. SixDigitInt)
│   │   └── Game/                   # Domänenmodelle, DTOs, Spielfeldlogik
│   ├── Repository/GameRepo/        # Spielspeicher (Interface + In-Memory-Impl.)
│   ├── Services/GameManager/       # Use-Case- und Ablaufsteuerung
│   ├── Program.cs                  # App-Konfiguration und DI
│   └── appsettings*.json           # Konfiguration
├── GUI/                            # Frontend (Vue 3 + TS)
│   ├── public/                     # Statische Assets (Sprites, Hintergrund, Icons)
│   ├── src/
│   │   ├── components/             # Wiederverwendbare UI-Komponenten
│   │   │   └── game/               # Spielfeld-/Info-Komponenten
│   │   ├── routes/                 # View-Komponenten pro Route
│   │   ├── router/                 # Router-Konfiguration
│   │   ├── scripts/
│   │   │   ├── interfaces/         # TS-Typdefinitionen
│   │   │   ├── logic/              # Anwendungslogik (lokal/online/signalR)
│   │   │   └── utils/              # Hilfsfunktionen
│   │   ├── Layout.vue              # App-Shell
│   │   ├── Home.vue                # Startseite
│   │   ├── NotFound.vue            # 404-Fallback
│   │   └── main.ts                 # Bootstrapping
│   ├── vite.config.ts              # Build-/Alias-Konfiguration
│   └── package.json                # npm Scripts + Abhängigkeiten
├── 4Gewinnt.sln                    # .NET Lösung
└── TECHNISCHE_SPEZIFIKATION.md     # Diese Spezifikation

5. Backend-Architektur

Überblick

Das Backend besteht aus vier Schichten:

  1. Controller/Hub-Schicht: externer Zugriff
  2. Service-Schicht: Geschäftsabläufe
  3. Repository-Schicht: Speicherung und Lookup
  4. Model-Schicht: Domänenobjekte und Algorithmen

Klassen- und Typdokumentation (Backend)

Program (Program.cs)

Zweck

Konfiguriert Dependency Injection, Middleware und Endpunkte der Anwendung.

Eigenschaften

Name Typ Beschreibung
builder WebApplicationBuilder Aufbau des DI-Containers und Hostings
app WebApplication Laufende ASP.NET Anwendung

Methoden

Methode Parameter Rückgabewert Beschreibung
Top-Level Setup - - Registriert Controller, SignalR, Swagger, Repositories und Services; mappt Endpunkte

Beziehungen

  • Verwendet IGameManager/GameManager und IGameRepository/GameRepository via DI.
  • Mappt GameHubSocket als SignalR-Hub unter /api/gamehub.

StatusController

Zweck

Einfacher Healthcheck-Endpunkt (GET /api/status) zur Verfügbarkeitsprüfung.

Eigenschaften

Name Typ Beschreibung
- - Keine eigenen Felder

Methoden

Methode Parameter Rückgabewert Beschreibung
Get - IActionResult Gibt 200 OK mit "Running" zurück

Beziehungen

  • Keine Abhängigkeiten zu Domain-Services.

GameHubSocket

Zweck

SignalR-Hub als Eintrittspunkt für Spiel-Kommandos aus Clients.

Eigenschaften

Name Typ Beschreibung
_gameManager IGameManager Service für Spielfunktionen

Methoden

Methode Parameter Rückgabewert Beschreibung
CreateGame playerName: string, gFs: Coordinates Task Validiert Feldgröße, erstellt Spiel, fügt Client zur Spielgruppe hinzu, sendet GameCreated
JoinGame playerName: string, gameCode: int Task Lässt Client einem Spiel beitreten, sendet GameJoined oder Error
RequestGameInformation gameId: string Task Delegiert an Manager für aktuellen Spielzustand
Drop gameId: string, column: int Task Delegiert Zugausführung an Manager
OnDisconnectedAsync exception?: Exception Task Meldet Disconnection und ruft Basisverhalten auf

Beziehungen

  • Ruft IGameManager-Methoden auf.
  • Sendet Events über Clients und verwaltet Gruppenmitgliedschaft.

IGameManager (Interface)

Zweck

Definiert die fachlichen Operationen für Spiele.

Eigenschaften

Name Typ Beschreibung
- - Interface ohne Felder

Methoden

Methode Parameter Rückgabewert Beschreibung
CreateGame gFs: Coordinates, player: Player (string, int) Erstellt neues Spiel und gibt (gameId, gameCode)
JoinGame player: Player, gameCode: int Task<string?> Versucht Beitritt; liefert gameId oder null
RequestGameInformation gameId: string, playerConnectionId: string Task Liefert Spielzustand an anfragenden Client
Drop gameCode: string, column: int, playerConnectionId: string Task Führt Spielzug aus
DisconnectedPlayer playerConnectionId: string Task Beendet Spiel bei Verbindungsabbruch

Beziehungen

  • Implementiert durch GameManager.

GameManager

Zweck

Orchestriert Kern-Use-Cases: Spielstart, Beitritt, Zuglogik, Endbedingungen und Aufräumen.

Eigenschaften

Name Typ Beschreibung
gameRepository IGameRepository Zugriff auf Spielinstanzen
hubContext IHubContext<GameHubSocket> Serverseitiges Senden von SignalR-Events

Methoden

Methode Parameter Rückgabewert Beschreibung
CreateGame gFs: Coordinates, player: Player (string, int) Legt Spiel an, fügt Ersteller hinzu, liefert Kennungen
JoinGame player: Player, gameCode: int Task<string?> Prüft Lobbyzustand/Platz, fügt Gruppe hinzu, sendet bei 2 Spielern GameStarted
RequestGameInformation gameId: string, playerConnectionId: string Task Baut DTO und sendet GameInformation an den Client
Drop gameCode: string, column: int, playerConnectionId: string Task Prüft Zugrecht/Zustand, lässt Stein fallen, sendet FieldUpdated, prüft Win/Draw, sendet GameEnded
DisconnectedPlayer playerConnectionId: string Task Entfernt Spieler aus Spiel, beendet Spiel, sendet GameEnded mit PlayerDisconnected
ConvertField (privat, statisch) field: int[,]? int[][] Transformiert 2D-Array in jagged array für DTO
ScheduleGameDeletion (privat) gameId: string, delay: TimeSpan void Verzögerte Löschung in Hintergrund-Task und Versand GameDestroyed

Beziehungen

  • Verwendet IGameRepository, Game, GameField, GameInformationDto.
  • Ruft SignalR-Clients/Gruppen auf (GameStarted, FieldUpdated, GameEnded, GameInformation, GameDestroyed).

IGameRepository (Interface)

Zweck

Abstraktion der Spielpersistenz.

Eigenschaften

Name Typ Beschreibung
- - Interface ohne Felder

Methoden

Methode Parameter Rückgabewert Beschreibung
GetAll - List<Game> Liefert alle Spiele
GetOne id: string Game? Sucht Spiel per ID
GetOne gameCode: SixDigitInt Game? Sucht Spiel per Spielcode
GetOneByConnectionId connectionId: string Game? Sucht Spiel, in dem ein Spieler verbunden ist
Create gameFieldSize: Coordinates Game Erstellt neues Spiel
Destroy id: string void Entfernt Spiel aus Speicher

Beziehungen

  • Implementiert durch GameRepository.

GameRepository

Zweck

In-Memory-Implementierung für Spielverwaltung inklusive Codegenerierung.

Eigenschaften

Name Typ Beschreibung
_games List<Game> Aktive Spiele im Arbeitsspeicher

Methoden

Methode Parameter Rückgabewert Beschreibung
GetAll - List<Game> Gibt interne Liste zurück
GetOne id: string Game? Lookup über Game.Id
GetOne gameCode: SixDigitInt Game? Lookup über Game.GameCode
GetOneByConnectionId connectionId: string Game? Spielsuche nach enthaltenem Spieler
Create gameFieldSize: Coordinates Game Erzeugt Game mit einzigartigem Code, fügt zur Liste hinzu
Destroy id: string void Entfernt Spiele mit ID
GenerateGameCode (privat) - SixDigitInt Erzeugt kryptografisch zufälligen 6-stelligen, einzigartigen Code

Beziehungen

  • Instanziiert Game und SixDigitInt.
  • Wird von GameManager genutzt.

SixDigitInt (record struct)

Zweck

Value Object für sechsstellige Spielcodes mit Wertebereichsvalidierung.

Eigenschaften

Name Typ Beschreibung
Value int Interner numerischer Wert (0999999)

Methoden

Methode Parameter Rückgabewert Beschreibung
Konstruktor value: int - Validiert Bereich und setzt Value
ToString - string Gibt Code links mit Nullen aufgefüllt (D6) zurück
implicit operator int v: SixDigitInt int Ermöglicht implizite Konvertierung nach int

Beziehungen

  • Wird in Game und Repository als Spielcode verwendet.

Coordinates (readonly struct)

Zweck

Datenstruktur für Felddimensionen oder Koordinaten.

Eigenschaften

Name Typ Beschreibung
X int Breite / X-Koordinate
Y int Höhe / Y-Koordinate

Methoden

Methode Parameter Rückgabewert Beschreibung
- - - Keine Methoden

Beziehungen

  • Wird von Game, GameField und Hub-Aufrufen genutzt.

GameState (enum)

Zweck

Statusautomat eines Spiels.

Werte

Wert Beschreibung
Lobby Spiel erstellt, wartet auf zweiten Spieler
Running Spiel aktiv
Ended Spiel beendet

Player

Zweck

Spielerobjekt mit Name, Connection-ID und Spielerrolle (1 oder 2).

Eigenschaften

Name Typ Beschreibung
Name string Anzeigename
ConnectionId string SignalR-Verbindungs-ID
PlayerTag int Rolle/Steinfarbe (1 oder 2)

Methoden

Methode Parameter Rückgabewert Beschreibung
Konstruktor name: string, connectionId: string - Initialisiert Spieler

Beziehungen

  • Bestandteil von Game.Players.

Game

Zweck

Aggregate Root für einen kompletten Matchzustand.

Eigenschaften

Name Typ Beschreibung
Id string Eindeutige Spiel-ID (GUID)
GameCode SixDigitInt Human-readable Join-Code
Players List<Player> Teilnehmer (max. 2)
CurrentTurn int Aktuelle Spielerrolle (1/2)
State GameState Lobby/Running/Ended
Field GameField Spielfeldinstanz

Methoden

Methode Parameter Rückgabewert Beschreibung
Konstruktor gFs: Coordinates, gameCode: SixDigitInt - Erstellt neues Spiel mit Feld
AddPlayer player: Player bool Fügt Spieler hinzu, weist PlayerTag zu, startet Spiel bei 2 Spielern
RemovePlayer playerConnectionId: string void Entfernt Spieler anhand Connection-ID
GetPlayerByConnectionId playerConnectionId: string Player? Spielersuche nach Connection-ID
GetPlayerByTag playerTag: int Player? Spielersuche nach Rolle
StartGame - void Setzt Status auf Running
EndGame - void Setzt Status auf Ended

Beziehungen

  • Enthält GameField und Player.
  • Wird über GameManager gesteuert.

DropResult (enum)

Zweck

Ergebniscode für Zugversuche im Spielfeld.

Werte

Wert Beschreibung
OutOfGameField Spalte außerhalb gültigen Bereichs
NotAllowedPlayer Ungültiger Spielerwert
ColumnFull Spalte ist voll
InvalidFieldValue Feld enthält ungültige Werte
Placed Stein erfolgreich platziert

FieldState (enum)

Zweck

Status eines einzelnen Feldpunktes.

Werte

Wert Beschreibung
OutOfGameField Koordinate außerhalb
Empty Feld leer
OccupiedRed Belegt durch Spieler 1
OccupiedYellow Belegt durch Spieler 2
InvalidFieldValue Unerwarteter Wert

GameField

Zweck

Kapselt Feldzustand und Algorithmen für Einwurf, Vollprüfung und Gewinnerkennung.

Eigenschaften

Name Typ Beschreibung
GFs Coordinates Spielfeldgröße
CurrentField int[,] Aktuelles Feldraster (0 leer, 1/2 Spieler)
BackupField int[,] Sicherung für Rücksetzen bei Fehlern

Methoden

Methode Parameter Rückgabewert Beschreibung
Konstruktor gFs: Coordinates - Erzeugt Raster und Backup
Drop column: int, player: int DropResult Lässt Stein in Spalte fallen; nutzt Backup vor Änderung
CheckField coordinates: Coordinates FieldState Liefert Status eines Feldpunktes
IsFull - bool Prüft, ob kein Leerfeld mehr existiert
CountInDirection (privat) startX,startY,dx,dy,player int Zählt zusammenhängende Steine in Richtung
CheckLine (privat) startX,startY,dx,dy,player bool Prüft 4er-Linie über beide Richtungen
CheckForWin - int Durchsucht Feld nach Gewinner (0/1/2)
ResetToLastSave - void Stellt Feld aus Backup wieder her
CreateSave - void Kopiert CurrentField nach BackupField

Beziehungen

  • Wird von Game gehalten.
  • Von GameManager.Drop aufgerufen.

GameInformationDto

Zweck

Transportobjekt für Frontend-Synchronisation.

Eigenschaften

Name Typ Beschreibung
Id string Spiel-ID
Players List<Player> Spielerliste
State GameState? Spielstatus
CurrentField int[][] Feldzustand in serialisierbarer Struktur
CurrentTurn int Nächster Spieler

Methoden

Methode Parameter Rückgabewert Beschreibung
- - - Reines DTO ohne Logik

Beziehungen

  • Wird vom GameManager erzeugt und über Hub-Ereignisse versendet.

6. Frontend-Architektur

Seiten / Views

  • /Home.vue (Moduswahl)
  • /localModeLocalMode.vue (lokales Spiel)
  • /onlineModeOnlineMode.vue (Lobbyauswahl + Online-Spiel)
  • Fallback → NotFound.vue

Komponenten

  • Layout: App-Shell mit Header und Router-View
  • CreateOrJoinMenu: Auswahl „Erstellen“/„Beitreten“
  • GameCreationMenu: Spieler-/Feldeinstellungen
  • GameJoinMenu: Name + 6-stelliger Join-Code
  • GameEndedMenu: Endstand + Restart
  • Field: Spielfelddarstellung + Spaltenauswahl
  • InfoField: Textstatus aktueller Spielerzug
  • Slider: Wiederverwendbarer numerischer Slider

State Management

Kein zentrales Store-Framework; Zustand wird komponentenlokal mit Vue ref/computed gehalten.

  • Spielzustand fließt über Callback-Events aus den Logikklassen (OnlineGame, LocalGame).

API-Kommunikation

  • Keine klassische REST-Spiel-API.
  • Vollständig ereignisgesteuert via SignalR (GameConnection).
  • REST nur für Healthcheck (/api/status).

Routing

Router in router/index.ts mit createWebHistory.

Klassen- und Komponentendokumentation (Frontend)

main.ts

Zweck

Bootstrapping von Vue-App, Vuetify, Router und globalen Styles.

Eigenschaften

Name Typ Beschreibung
vuetify Vuetify-Instanz Dark Theme, Komponenten/Directives
app Vue App Root-App mit Layout.vue

Methoden

Methode Parameter Rückgabewert Beschreibung
Top-Level Setup - - Initialisiert App, bindet Plugins, mountet #app

Beziehungen

  • Nutzt Layout.vue und Router.

Router (router/index.ts)

Zweck

Definiert Navigationsstruktur der SPA.

Eigenschaften

Name Typ Beschreibung
router Router Routentabelle und History-Strategie

Methoden

Methode Parameter Rückgabewert Beschreibung
createRouter(...) Konfigurationsobjekt Router Baut Router mit vier Routen

Beziehungen

  • Verknüpft Views Home, LocalMode, OnlineMode, NotFound.

Layout.vue (Komponente)

Zweck

Stellt globale App-Hülle (AppBar + Inhalt) bereit.

Props

Keine.

State / reactive Daten

Keine.

Methoden

Keine.

Events

  • Klick auf Titel navigiert zur Startseite.

API Calls

Keine.


Home.vue (Komponente)

Zweck

Startseite zur Auswahl des Spielmodus.

Props

Keine.

State / reactive Daten

Name Typ Beschreibung
buttons Array Konfiguration der zwei Modus-Buttons

Methoden

Keine expliziten Methoden.

Events

  • Navigationsereignisse über :to auf Button.

API Calls

Keine.


OnlineMode.vue (Komponente)

Zweck

Steuert gesamten Online-Flow von Auswahl bis laufendem Spiel.

Props

Keine.

State / reactive Daten

Name Typ Beschreibung
settings Ref<GameSettings> Einstellungen zum Erstellen
joiningModel Ref<JoinGameObject> Daten für Join-Flow
currentState Ref<CurrentState> UI-State-Maschine
game Ref<OnlineGame> Online-Spielorchestrator
gameField Ref<number[][]> Feld für Anzeige
currentSelectionIndex Ref<number | null> Hover-/Klickspalte
gameEndedInformation Ref<GameEnded | null> Endscreen-Daten

Methoden

Methode Parameter Rückgabewert Beschreibung
createGame - Promise<void> Delegiert an OnlineGame.createGame
tryToJoin - Promise<void> Delegiert an OnlineGame.joinGame
restartGame - Promise<void> Startet neue Runde via Replay-Code
onUnmounted Hook - - Trennt SignalR-Verbindung

Events

  • Child-Events: createGame, join, restart-game, click-on-game-field.
  • Interne Callbacks: onGameStateChanged, onGameEnded, onGameCreated, onGameStarted, onGameJoinedFailed.

API Calls

Indirekt über OnlineGameGameConnection (CreateGame, JoinGame, Drop).


LocalMode.vue (Komponente)

Zweck

Steuert lokalen Spielmodus inkl. optionalem Bot.

Props

Keine.

State / reactive Daten

Name Typ Beschreibung
settings Ref<GameSettings> Lokale Spieleinstellungen
currentState Ref<CurrentState> UI-State (Create/Game/End)
game Ref<LocalGame> Lokaler Spielorchestrator
gameField Ref<number[][]> Angezeigter Feldzustand
currentSelectionIndex Ref<number | null> Ausgewählte Spalte
gameEndedInformation Ref<GameEnded | null> Endinformationen

Methoden

Methode Parameter Rückgabewert Beschreibung
startGame - Promise<void> Verbindet beide lokale Clients und erstellt Spiel
restart - Promise<void> Trennt beide Clients und startet neu

Events

  • Child-Events: create-game, restart-game, click-on-game-field.

API Calls

Indirekt über LocalGame → 2× GameConnection.


NotFound.vue (Komponente)

Zweck

Fallback-Anzeige für unbekannte Routen.

Props / State / Methoden / Events / API Calls

Keine fachliche Logik.


CreateOrJoinMenu.vue (Komponente)

Zweck

Zwischenschritt im Online-Modus zur Auswahl zwischen Erstellen und Beitreten.

Props

Keine.

State / reactive Daten

Keine.

Methoden

Keine.

Events

Event Beschreibung
createGame Wechselt in Erstellungsflow
joinGame Wechselt in Join-Flow

API Calls

Keine.


GameCreationMenu.vue (Komponente)

Zweck

Eingabe von Namen, Feldgröße und optional Bot-Konfiguration.

Props

Name Typ Beschreibung
settings (Model) GameSettings Zweiwegegebundene Einstellungen

State / reactive Daten

Name Typ Beschreibung
settingsProp ModelRef<GameSettings> Reaktiver Zugriff auf Einstellungen

Methoden

Methode Parameter Rückgabewert Beschreibung
gameFieldPreset x: number, y: number void Setzt vordefinierte Spielfeldgröße

Events

Event Beschreibung
createGame Startet Spiel-/Lobby-Erzeugung

API Calls

Keine direkten.


GameJoinMenu.vue (Komponente)

Zweck

Erfasst Spielername und sechsstelligen Beitrittscode.

Props

Name Typ Beschreibung
joinGameObject (Model) JoinGameObject Daten inklusive Fehlerzustand

State / reactive Daten

Name Typ Beschreibung
joiningModel ModelRef<JoinGameObject> Lokaler Zugriff auf Join-Modell

Methoden

Keine.

Events

Event Beschreibung
join Löst Join-Operation aus

API Calls

Keine direkten.


GameEndedMenu.vue (Komponente)

Zweck

Anzeige des Endzustands (Sieg/Draw/Disconnect) und Neustartaktion.

Props

Name Typ Beschreibung
gameEndedInformation GameEnded | null Endereignis-Payload

State / reactive Daten

Name Typ Beschreibung
restarted Ref<boolean> Verhindert Mehrfachklick auf Neustart
message ComputedRef<string> Aufbereiteter Endtext

Methoden

Methode Parameter Rückgabewert Beschreibung
restartClicked - void Emitet Neustart und setzt Sperrflag

Events

Event Beschreibung
restartGame Triggert neues Spiel

API Calls

Keine direkten.


Slider.vue (Komponente)

Zweck

Generischer Slider mit numerischer Anzeige.

Props

Name Typ Beschreibung
label string Beschriftung
min number Untergrenze
max number Obergrenze
step number Schrittweite
width string | number Breite Inputfeld
disabled boolean Deaktivierung
readonlyValue boolean Schreibschutz Input

State / reactive Daten

Name Typ Beschreibung
model ModelRef<number> Aktueller Wert
inputWidth ComputedRef<string> CSS-Breite des Append-Inputs

Methoden

Keine separaten Methoden.

Events

Standard v-model-Update.

API Calls

Keine.


Field.vue (Komponente)

Zweck

Visuelle Darstellung des Spielfeldes inkl. Hover-/Auswahlspalte.

Props

Name Typ Beschreibung
gameState number[][] Feldzustand
currentSelectionIndex (Model) number | null aktuell gewählte Spalte

State / reactive Daten

Name Typ Beschreibung
gameFieldSize ComputedRef<FieldSize> abgeleitete Feldgröße

Methoden

Methode Parameter Rückgabewert Beschreibung
translateNumberToImage num: number string Mapt Feldwert auf Sprite-Pfad
selectionUpdate index: number, active: boolean void Setzt/entfernt Spaltenauswahl

Events

Event Beschreibung
clickOnGameField Anwender klickt auf Spielfeld, Parent löst drop aus

API Calls

Keine direkten.


InfoField.vue (Komponente)

Zweck

Zeigt Status- oder Hinweistext zum aktuellen Zug.

Props

Name Typ Beschreibung
msg string Meldung
currenlyWaiting? boolean Optionales Ausblend-Flag

State / Methoden / Events / API Calls

Keine.


FieldSize (Interface)

Zweck

Typsichere Feldgrößenbeschreibung.

Eigenschaften

Name Typ Beschreibung
x number Breite
y number Höhe

GameSettings (Interface)

Zweck

Konfigurationsmodell für Spielanlage.

Eigenschaften

Name Typ Beschreibung
fieldSize FieldSize Spielfeldgröße
playerName1 string Spieler 1
playerName2? string | null Spieler 2 (lokal/optional)
botPlayer2? boolean | null Bot-Flag für Spieler 2
message? string | null UI-Nachricht nach Erstellung

JoinGameObject (Interface)

Zweck

Eingabemodell für Beitritt zu bestehendem Spiel.

Eigenschaften

Name Typ Beschreibung
failed boolean Fehlerstatus (UI)
playerName string Anzeigename
gameCode? string Eingetippter 6-stelliger Code

GameConnection (Klasse)

Zweck

SignalR-Transportabstraktion für Hub-Aufrufe und Eventbindung.

Eigenschaften

Name Typ Beschreibung
connection signalR.HubConnection Physische SignalR-Verbindung
playerName string Lokaler Name für Hub-Aufrufe
Callback-Felder optionale Funktionen Reaktion auf Hub-Events (onGameCreated, onError, ... )

Methoden

Methode Parameter Rückgabewert Beschreibung
Konstruktor - - Baut HubConnection (/api/gamehub) und registriert Event-Listener
connect playerName: string Promise<void> Startet Verbindung
disconnect - Promise<void> Stoppt Verbindung
createGame gFs: FieldSize Promise<void> Hub-Invoke CreateGame
joinGame gameCode: number Promise<void> Hub-Invoke JoinGame
requestGameInformation gameId: string Promise<void> Hub-Invoke RequestGameInformation
drop gameId: string, column: number Promise<void> Hub-Invoke Drop

Beziehungen

  • Wird von OnlineGame und LocalGame verwendet.
  • Spiegelt Server-Eventmodell 1:1.

OnlineGame (Klasse)

Zweck

Use-Case-Orchestrierung für Online-Spiel aus Sicht eines einzelnen Clients.

Eigenschaften

Name Typ Beschreibung
player GameConnection SignalR-Clientinstanz
currentDescription string Text zur aktuellen Runde
gameId string Serverseitige Spiel-ID
gameState GameInformationDto | undefined Lokaler Snapshot
Callback-Felder optionale Funktionen Hooks für UI (onGameCreated, onGameEnded, ...)

Methoden

Methode Parameter Rückgabewert Beschreibung
Konstruktor - - Verkabelt alle Transport-Events auf UI-Callbacks
createGame settings: GameSettings Promise<void> Verbindet Spieler und erstellt Lobby
joinGame joinObject: JoinGameObject Promise<void> Validiert Codeformat, verbindet, tritt Spiel bei
updateState newState: GameInformationDto Promise<void> Aktualisiert lokalen Zustand und Callback
drop index: number Promise<void> Führt Zug im aktuellen Spiel aus
changePlaceDescription - void Setzt zufällige Zugmeldung anhand currentTurn
restartGame replayGameCode: any Promise<void> Trennt Verbindung und joint Replay-Code

Beziehungen

  • Nutzt GameConnection und Utility getRandomMovePhrase.

LocalGame (Klasse)

Zweck

Orchestriert lokalen Modus durch zwei parallele GameConnection-Instanzen.

Eigenschaften

Name Typ Beschreibung
player1 GameConnection Lokaler Client 1
player2 GameConnection Lokaler Client 2/Bot
currentDescription string UI-Text aktueller Spieler
gameId string Aktuelle Spiel-ID
botGame boolean Bot-Modus für Spieler 2
gameState GameInformationDto | undefined Spielsnapshot
Callback-Felder optionale Funktionen UI-Hooks für State-Änderung und Spielende

Methoden

Methode Parameter Rückgabewert Beschreibung
Konstruktor - - Verdrahtet Events beider Player-Verbindungen
start settings: GameSettings Promise<void> Verbindet beide Spieler und erstellt neues Spiel
updateState newState: GameInformationDto Promise<void> Aktualisiert lokalen Zustand
drop index: number Promise<void> Führt Zug durch aktuellen Spieler aus; Bot setzt random verzögert
changePlaceDescription - void Erzeugt zufällige Zugmeldung
disconnectAll - Promise<void> Trennt beide SignalR-Verbindungen

Beziehungen

  • Nutzt 2× GameConnection, optional Bot-Zug per Zufall.

buildFieldArray (Funktion)

Zweck

Erzeugt initiales number[][]-Spielfeld in gewünschter Größe.

Signatur

buildFieldArray(fieldSize: FieldSize): number[][]

Verhalten

  • Erstellt y Zeilen, jede Zeile enthält x Nullen.

getRandomMovePhrase (Funktion)

Zweck

Erzeugt abwechslungsreiche Statusmeldung für die UI.

Signatur

getRandomMovePhrase(playerName: string): string

Verhalten

  • Wählt zufällig eine Phrase aus movePhrases.
  • Ersetzt Platzhalter {playerName}.

7. Datenmodelle

Backend-Datenmodelle

Game

  • id: string
  • gameCode: SixDigitInt
  • players: List
  • currentTurn: int (1 oder 2)
  • state: GameState
  • field: GameField

Beziehungen:

  • 1 Game besitzt 1 GameField
  • 1 Game besitzt 0..2 Player

Player

  • name: string
  • connectionId: string
  • playerTag: int

GameField

  • gFs: Coordinates
  • currentField: int[,]
  • backupField: int[,]

GameInformationDto

  • id: string
  • players: List
  • state: GameState?
  • currentField: int[][]
  • currentTurn: int

Coordinates

  • x: int
  • y: int

SixDigitInt

  • value: int

Frontend-Datenmodelle

GameInformationDto (TS)

  • id: string | null
  • players: Player[]
  • state: number
  • currentField: number[][]
  • currentTurn: number

Player (TS)

  • name: string
  • connectionId: string
  • playerTag: number

GameEnded (TS)

  • method: string
  • player?: Player | null
  • replayGameCode?: number | null

GameIdentifier (TS)

  • gameId: string
  • gameCode: number

GameSettings (TS)

  • siehe Abschnitt 6

JoinGameObject (TS)

  • siehe Abschnitt 6

8. Spiel- / Geschäftslogik

Spiel erstellen

  1. Client verbindet SignalR (connect).
  2. Client ruft CreateGame(playerName, fieldSize).
  3. Server erstellt Game, setzt Spieler 1, vergibt GameCode.
  4. Server fügt Client zur Gruppe game.Id hinzu.
  5. Server sendet GameCreated an Ersteller.

Spiel beitreten

  1. Client validiert 6-stelligen Code lokal.
  2. Client ruft JoinGame(playerName, gameCode).
  3. Server prüft Spiel vorhanden + Lobby + Platz frei.
  4. Server fügt Spieler 2 hinzu, setzt ggf. Spiel auf Running.
  5. Server fügt Client zur Gruppe game.Id hinzu.
  6. Server sendet GameStarted an Gruppe.

Spiel starten

  • Start erfolgt implizit beim zweiten Spieler (AddPlayer/JoinGame).

Spielzüge

  1. Aktiver Spieler sendet Drop(gameId, column).
  2. Server prüft Verbindung zu Spiel + Turn-Recht + Zustand Running.
  3. GameField.Drop setzt Stein in unterste freie Zelle.
  4. Server toggelt CurrentTurn.
  5. Server sendet FieldUpdated an Spielgruppe.

Spielende

  • Gewinn: CheckForWin() != 0, dann GameEnded(Method=Win) + Replay-Code.
  • Unentschieden: IsFull() == true, dann GameEnded(Method=Draw) + Replay-Code.
  • Disconnect: DisconnectedPlayer, dann GameEnded(Method=PlayerDisconnected).

9. Datenfluss

Ablauf „Spiel erstellen“

  1. Frontend (OnlineGame.createGame) sendet CreateGame.
  2. GameHubSocket.CreateGame erstellt Player und delegiert.
  3. GameManager.CreateGame ruft Repository Create.
  4. Hub fügt Verbindung zur SignalR-Gruppe hinzu.
  5. Hub sendet GameCreated an Caller.
  6. Frontend zeigt Join-Code in GameCreationMenu.

Ablauf „Spielzug“

  1. Nutzer klickt Spalte in Field.vue.
  2. Route ruft game.drop(index).
  3. GameConnection.drop invokt Hub-Methode.
  4. GameManager.Drop validiert und setzt Stein.
  5. FieldUpdated wird an Gruppe gesendet.
  6. Clients aktualisieren gameField und Statusnachricht.

Ablauf „Spielende + Replay“

  1. Nach Win/Draw erstellt Server ein neues Spiel mit gleicher Feldgröße.
  2. Server sendet GameEnded inkl. ReplayGameCode.
  3. Frontend zeigt GameEndedMenu.
  4. Beim Neustart joint Client per Replay-Code.

10. Wichtige Algorithmen

Spielzug validieren

  • Prüfungen in Reihenfolge:
    1. Spiel existiert
    2. Spieler gehört zum Spiel
    3. Spielzustand ist Running
    4. CurrentTurn == player.PlayerTag
    5. Spalte in Bounds
    6. Spalte nicht voll
    7. Feldwerte konsistent (nur 0/1/2)

Gewinner erkennen

  • Für jede Zelle mit Spielerwert 1/2 werden vier Richtungen geprüft:
    • Horizontal (1,0)
    • Vertikal (0,1)
    • Diagonal rechts-unten (1,1)
    • Diagonal links-unten (-1,1)
  • Der Algorithmus zählt zusammenhängende Steine in beide Richtungen und addiert die Startzelle.
  • >= 4 ergibt Sieg.

Spielstatus berechnen

  • Lobby → weniger als 2 Spieler.
  • Running → 2 Spieler und laufendes Spiel.
  • Ended → bei Win/Draw/Disconnect.

11. API-Dokumentation

HTTP-Endpunkte

Endpoint Methode Beschreibung
/api/status GET Healthcheck (Running)

SignalR Hub-Endpunkt

Endpoint Methode Beschreibung
/api/gamehub SignalR Echtzeitkommunikation für Spiellogik

Hub-Methoden

Hub-Methode Parameter Beschreibung
CreateGame playerName: string, gFs: Coordinates Erstellt neues Spiel
JoinGame playerName: string, gameCode: int Tritt bestehendem Spiel bei
RequestGameInformation gameId: string Liefert aktuellen Zustand
Drop gameId: string, column: int Führt Zug aus

12. Ereignisse / Echtzeitkommunikation

Event Sender Empfänger Beschreibung
GameCreated Server Caller Enthält gameId, gameCode nach Erstellung
GameJoined Server Caller Bestätigt Beitritt
GameStarted Server Gruppe game.Id Initialer Spielzustand nach 2. Spieler
GameInformation Server Einzelclient Zustandsabfrage-Antwort
FieldUpdated Server Gruppe game.Id Feld/Turn nach gültigem Zug
GameEnded Server Gruppe game.Id Endgrund: Win/Draw/Disconnect + optionale Daten
GameDestroyed Server Gruppe game.Id Hinweis nach geplanter Löschung
Error Server Caller/Client Fehlertext (z. B. ungültiger Zug / Spiel nicht gefunden)

13. Benutzeroberfläche

Screens

  1. Startseite: Moduswahl lokal/online
  2. Online: Auswahlseite: Erstellen oder Beitreten
  3. Spielerstellung: Namen, Feldgröße, Presets
  4. Join-Seite: Name + OTP-Feld für Spielcode
  5. Spielansicht: Spielfeld + Zugstatus
  6. Endscreen: Ergebnis + Neustartoption

UI-Ablauf

  • Nutzer startet auf Home und navigiert über Buttons.
  • In Spielansicht zeigt Field den Rasterzustand mit Hover-Pfeil.
  • InfoField zeigt dynamische Spielzugtexte.
  • Endzustand sperrt Spiel und bietet Neustart/Abbruch.

Benutzeraktionen

  • Namen eingeben
  • Feldgröße per Slider/Presets auswählen
  • Beitrittscode eingeben
  • Spalte durch Hover/Klick auswählen
  • Neustart auslösen

14. Anwendungsabläufe (User-Flows)

Flow A: Online-Spiel erstellen

  1. Home → Online Multiplayer.
  2. Auswahl „Erstellen“.
  3. Name/Feldgröße setzen, Spiel starten.
  4. Code wird angezeigt.
  5. Warten bis zweiter Spieler beitritt.
  6. Spiel startet automatisch.

Flow B: Online-Spiel beitreten

  1. Home → Online Multiplayer.
  2. Auswahl „Beitreten“.
  3. Namen + 6-stelligen Code eingeben.
  4. Bei Erfolg Übergang in Spielansicht.
  5. Bei Fehler (failed=true) visuelles Feedback.

Flow C: Lokal spielen

  1. Home → Lokaler Multiplayer.
  2. Namen/Feldgröße/Bot-Option setzen.
  3. Spiel starten.
  4. Spieler wechseln ab (oder Bot setzt random).
  5. Endscreen erscheint bei Win/Draw.

Flow D: Spiel erneut starten

  1. Endscreen „Spiel Neustarten“.
  2. Online: Join auf vom Server gelieferten Replay-Code.
  3. Lokal: Verbindungen schließen und neu initialisieren.

15. Annahmen und Einschränkungen

  1. Keine persistente Speicherung: Alle Spiele gehen bei Serverneustart verloren.
  2. Maximal 2 Spieler pro Spiel.
  3. Keine Authentifizierung/Autorisierung für Spielzugriffe.
  4. Disconnect-Handling simpel: Ein Disconnect beendet das Spiel.
  5. Fehlertoleranz begrenzt: Teilweise nur Logging/Events, keine Retry-Strategie.
  6. Lokaler Modus nutzt trotzdem Server/SignalR (zwei Verbindungen im selben Client-Kontext).
  7. Skalierung: In-Memory-Liste ist nicht für Multi-Instance-Betrieb ausgelegt.

16. Erweiterungsmöglichkeiten

  1. Persistentes Repository (SQL/NoSQL) inkl. Match-Historie
  2. Benutzerkonten, Auth und Freundeslisten
  3. Elo-/Ranking-System
  4. Beobachtermodus (Spectator)
  5. Chat pro Spielgruppe
  6. Zugtimer und automatische Aufgabe
  7. Mehrsprachigkeit (i18n)
  8. KI mit heuristischer oder minimax-basierter Strategie
  9. Reconnect-Mechanismus mit Session-Tokens
  10. Horizontale Skalierung mit verteiltem Backplane/Cache für SignalR
  11. REST-API für Match-Archiv und Statistiken
  12. Erweiterte Telemetrie und strukturiertes Logging

Ableitbarkeit für Folgeartefakte

Diese Spezifikation enthält alle notwendigen Informationen, um automatisiert folgende Artefakte abzuleiten:

  • Pflichtenheft: Kapitel 1, 2, 8, 14, 15
  • Meilensteinplanung: Kapitel 3, 4, 5, 6, 16
  • UML-Klassendiagramm: Kapitel 5, 6, 7
  • Ablaufplan / Flowchart: Kapitel 8, 9, 14
  • Benutzerdokumentation: Kapitel 13, 14