diff --git a/src/app/game.component.html b/src/app/game.component.html index 296a661..17ab555 100644 --- a/src/app/game.component.html +++ b/src/app/game.component.html @@ -6,6 +6,20 @@ @if (gameStarted) { +
+
+ + +
+ +
+ + +
+ + +
+
@for (opponent of opponents; track opponent; let i = $index) {
@@ -30,7 +44,7 @@ }
-
Spieler: {{ player.score }} @for (opponent of opponents; track opponent; let i = $index) { | Gegner {{ i + 1 }}: {{ opponent.score }} } | Runde: {{ currentRound }}/10
+ @@ -42,10 +56,18 @@ - - - - + + + + @for(opponentTip of roundPredictions[stat.round - 1]?.opponentPredictions; track opponentTip; let j = $index){ + + }
{{ stat.round }}{{ stat.playerStitches }}{{ stitches }}
{{ stat.round }} + {{ roundPredictions[stat.round - 1]?.playerPrediction === null ? '-' : roundPredictions[stat.round - 1]?.playerPrediction }}/{{ stat.playerStitches }} + {{ player.score }} + + {{ opponentTip === null ? '-' : opponentTip }}/{{ stat.opponentStitches[j] }} + {{ opponents[j].score }} +
diff --git a/src/app/game.component.scss b/src/app/game.component.scss index 4cefe92..fb10036 100644 --- a/src/app/game.component.scss +++ b/src/app/game.component.scss @@ -15,13 +15,14 @@ } .opponents-area { display: flex; - justify-content: space-around; + justify-content: center; min-height: 320px; } .opponent-hand { position: relative; width: 200px; height: 280px; + margin-right: 150px; } .stacked-card { position: absolute; @@ -83,12 +84,14 @@ font-size: 14px; z-index: 100; text-align: center; + border-collapse: collapse; + text-align: center; } .round-stats th, .round-stats td { - padding: 8px; - border-bottom: 1px solid #ddd; + padding: 5px; + border: 1px solid #ddd; } .round-stats thead { @@ -99,3 +102,51 @@ .round-stats tbody tr:last-child td { border-bottom: none; } +.tip-value { + font-size: 12px; + vertical-align: top; + display: block; +} + +.stitch-value { + font-size: 24px; + font-weight: bold; + display: block; +} +.round-value { + font-size: 24px; + font-weight: bold; +} +.tip-phase { + position: fixed; + top: 20px; + left: 20px; + background-color: #f9f9f9; + border: 1px solid #ccc; + padding: 10px; + border-radius: 8px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + z-index: 100; +} + +.tip-phase input { + width: 60px; + height: 30px; + border: 2px solid #ccc; + border-radius: 5px; + text-align: center; + margin-bottom: 10px; +} + +.tip-phase input.active { + border-color: red; + box-shadow: 0 0 10px red; +} +td.alreadyTipped { + border-color: blue; + box-shadow: 0 0 10px blue; +} +.tip-phase label { + margin-right: 10px; + font-weight: bold; +} diff --git a/src/app/game.component.ts b/src/app/game.component.ts index 29d7200..5f6e111 100644 --- a/src/app/game.component.ts +++ b/src/app/game.component.ts @@ -1,9 +1,9 @@ -import { Component, OnInit } from '@angular/core'; import { CommonModule } from '@angular/common'; +import { Component, OnInit } from '@angular/core'; import { FormsModule } from '@angular/forms'; -import { CardFrontComponent } from './card-front.component'; import { CardBackComponent } from './card-back.component'; -import { CardService, Card } from './card.service'; +import { CardFrontComponent } from './card-front.component'; +import { Card, CardService } from './card.service'; import { GameRuleEngine } from './game-rule-engine'; export interface Player { @@ -17,12 +17,16 @@ interface RoundStats { playerStitches: number; opponentStitches: number[]; } +interface RoundPrediction { + playerPrediction: number | null; + opponentPredictions: Array; +} @Component({ selector: 'app-game', standalone: true, imports: [CommonModule, FormsModule, CardFrontComponent, CardBackComponent], templateUrl: './game.component.html', - styleUrls: ['./game.component.scss'] + styleUrls: ['./game.component.scss'], }) export class GameComponent implements OnInit { player: Player = { id: 0, hand: [], playedCard: null, score: 0 }; @@ -36,17 +40,24 @@ export class GameComponent implements OnInit { roundStats: RoundStats[] = []; private ruleEngine: GameRuleEngine; + roundPredictions: RoundPrediction[] = []; + currentTipPlayerIndex: number = 0; + isTipPhase: boolean = true; + numberTips = 0; constructor(private cardService: CardService) { this.ruleEngine = new GameRuleEngine(cardService); } - ngOnInit() {} + ngOnInit() { + this.startGame(); + } startGame() { - if (this.numberOfOpponents < 1 || this.numberOfOpponents > 3) { - alert("Bitte wählen Sie 1 bis 3 Gegner."); - return; - } + // if (this.numberOfOpponents < 1 || this.numberOfOpponents > 3) { + // alert('Bitte wählen Sie 1 bis 3 Gegner.'); + // return; + // } + this.numberOfOpponents = 2; this.gameStarted = true; this.initializePlayers(); this.startNewRound(); @@ -75,8 +86,74 @@ export class GameComponent implements OnInit { }); this.resetPlayedCards(); - this.currentPlayerIndex = this.ruleEngine.determineStartingPlayer(this.currentRound, this.opponents.length + 1); - this.playTrick(); + + // Runde für roundStats initialisieren + if (!this.roundStats[this.currentRound - 1]) { + this.roundStats[this.currentRound - 1] = { + round: this.currentRound, + playerStitches: 0, + opponentStitches: new Array(this.opponents.length).fill(0), + }; + } + + // Tipp-Phase initialisieren + this.isTipPhase = true; + this.currentTipPlayerIndex = (this.currentRound - 1) % (this.opponents.length + 1); + this.initializeTipPhase(); + } + initializeTipPhase() { + // Initialisiere die Vorhersagen für die Runde + this.roundPredictions[this.currentRound - 1] = { + playerPrediction: null, + opponentPredictions: new Array(this.opponents.length).fill(null), + }; + + // Starte das Tippen beim richtigen Spieler basierend auf der Runde + this.currentTipPlayerIndex = (this.currentRound - 1) % (this.opponents.length + 1); + this.numberTips = 0; + // Wenn der aktuelle Spieler kein menschlicher Spieler ist, den ersten Gegner automatisch tippen lassen + if (this.currentTipPlayerIndex > 0) { + this.submitOpponentTip(this.currentTipPlayerIndex - 1); + } + } + + submitOpponentTip(index: number) { + const randomTip = Math.floor(Math.random() * this.getCardsForRound(this.currentRound)); + this.roundPredictions[this.currentRound - 1].opponentPredictions[index] = randomTip; + + this.numberTips++; + if (this.numberTips === this.opponents.length + 1) { + // Alle haben getippt, beende die Tippphase + this.isTipPhase = false; + this.playTrick(); + } else if ((this.currentTipPlayerIndex + 1) % 3 === 0) { + // Spieler ist jetzt dran + this.currentTipPlayerIndex = 0; + return; + } else { + // Nächster Gegner ist dran + this.currentTipPlayerIndex++; + setTimeout(() => this.submitOpponentTip(this.currentTipPlayerIndex - 1), 1000); + } + } + + submitPlayerTip() { + const playerPrediction = this.roundPredictions[this.currentRound - 1]?.playerPrediction; + if (playerPrediction === null || playerPrediction < 0 || playerPrediction > this.getCardsForRound(this.currentRound)) { + return; // Ungültiger Tipp oder noch nicht gesetzt + } + + // Spieler hat getippt, wechsle zum nächsten Spieler + this.currentTipPlayerIndex++; + this.numberTips++; + if (this.numberTips === this.opponents.length + 1) { + // Alle haben getippt, beende die Tippphase + this.isTipPhase = false; + this.playTrick(); + } else { + // Der nächste Gegner ist an der Reihe + setTimeout(() => this.submitOpponentTip(0), 1000); + } } playTrick() { @@ -135,8 +212,8 @@ export class GameComponent implements OnInit { const allPlayers = [this.player, ...this.opponents]; const winner = this.ruleEngine.determineWinner(this.playedCards, allPlayers); winner.score++; - - // Neue Logik, um Stiche zu speichern + + // Stiche in den roundStats aktualisieren if (!this.roundStats[this.currentRound - 1]) { this.roundStats[this.currentRound - 1] = { round: this.currentRound, @@ -144,15 +221,29 @@ export class GameComponent implements OnInit { opponentStitches: new Array(this.opponents.length).fill(0), }; } - + if (winner === this.player) { this.roundStats[this.currentRound - 1].playerStitches++; } else { const opponentIndex = this.opponents.indexOf(winner); this.roundStats[this.currentRound - 1].opponentStitches[opponentIndex]++; } - + + // Überprüfe, ob die Runde vorbei ist if (this.player.hand.length === 0) { + // Tipp-Prüfung und Extrapunkte + const predictions = this.roundPredictions[this.currentRound - 1]; + if (predictions.playerPrediction === this.roundStats[this.currentRound - 1].playerStitches) { + this.player.score += 10; // Extrapunkte für richtigen Tipp + } + + this.opponents.forEach((opponent, index) => { + if (predictions.opponentPredictions[index] === this.roundStats[this.currentRound - 1].opponentStitches[index]) { + opponent.score += 10; // Extrapunkte für richtigen Tipp + } + }); + + // Neue Runde starten oder Spiel beenden if (this.currentRound < 10) { setTimeout(() => this.startNewRound(), 500); } else { @@ -169,7 +260,7 @@ export class GameComponent implements OnInit { this.playedCards = []; this.leadCard = null; this.player.playedCard = null; - this.opponents.forEach(opponent => opponent.playedCard = null); + this.opponents.forEach(opponent => (opponent.playedCard = null)); } getCardsForRound(round: number): number { @@ -182,12 +273,10 @@ export class GameComponent implements OnInit { const maxScore = Math.max(...allPlayers.map(p => p.score)); const winners = allPlayers.filter(p => p.score === maxScore); - let result = winners.length > 1 ? "Unentschieden!" : - winners[0] === this.player ? "Sie haben gewonnen!" : - `Gegner ${winners[0].id} hat gewonnen!`; + let result = winners.length > 1 ? 'Unentschieden!' : winners[0] === this.player ? 'Sie haben gewonnen!' : `Gegner ${winners[0].id} hat gewonnen!`; let scoreMessage = `Endstand - Spieler: ${this.player.score}`; - this.opponents.forEach((opponent) => { + this.opponents.forEach(opponent => { scoreMessage += `, Gegner ${opponent.id}: ${opponent.score}`; }); @@ -196,4 +285,7 @@ export class GameComponent implements OnInit { this.currentRound = 0; this.player.score = 0; } -} \ No newline at end of file + tipAlreadySet(value: number | null | undefined) { + return value !== null; + } +}