Guessing eingebaut

This commit is contained in:
Andreas Knuth 2024-09-18 19:38:49 +02:00
parent 7428faa138
commit 5cc62433bd
3 changed files with 194 additions and 29 deletions

View File

@ -6,6 +6,20 @@
</div>
@if (gameStarted) {
<div class="tip-phase">
<div>
<label>Dein Tipp:</label>
<input type="number" [(ngModel)]="roundPredictions[currentRound - 1].playerPrediction" [class.active]="currentTipPlayerIndex === 0" [disabled]="currentTipPlayerIndex !== 0" />
</div>
<div *ngFor="let opponent of opponents; let i = index">
<label>Gegner {{ i + 1 }} Tipp:</label>
<input type="number" [(ngModel)]="roundPredictions[currentRound - 1].opponentPredictions[i]" disabled />
</div>
<button *ngIf="currentTipPlayerIndex === 0" (click)="submitPlayerTip()">Tipp abgeben</button>
</div>
<div class="opponents-area">
@for (opponent of opponents; track opponent; let i = $index) {
<div class="opponent-hand">
@ -30,7 +44,7 @@
}
</div>
<div class="game-info">
<div class="score">Spieler: {{ player.score }} @for (opponent of opponents; track opponent; let i = $index) { | Gegner {{ i + 1 }}: {{ opponent.score }} } | Runde: {{ currentRound }}/10</div>
<!-- <div class="score">Spieler: {{ player.score }} @for (opponent of opponents; track opponent; let i = $index) { | Gegner {{ i + 1 }}: {{ opponent.score }} } | Runde: {{ currentRound }}/10</div> -->
<button (click)="startNewRound()" [disabled]="player.hand.length > 0 || currentRound > 10">Nächste Runde</button>
<!-- Tabelle für die Stiche pro Runde -->
<table class="round-stats">
@ -42,10 +56,18 @@
</tr>
</thead>
<tbody>
<tr *ngFor="let stat of roundStats">
<td>{{ stat.round }}</td>
<td>{{ stat.playerStitches }}</td>
<td *ngFor="let stitches of stat.opponentStitches">{{ stitches }}</td>
<tr *ngFor="let stat of roundStats; let i = index">
<td class="round-value">{{ stat.round }}</td>
<td [ngClass]="{ alreadyTipped: tipAlreadySet(roundPredictions[stat.round - 1]?.playerPrediction) }">
<span class="tip-value">{{ roundPredictions[stat.round - 1]?.playerPrediction === null ? '-' : roundPredictions[stat.round - 1]?.playerPrediction }}/{{ stat.playerStitches }}</span>
<span class="stitch-value">{{ player.score }}</span>
</td>
@for(opponentTip of roundPredictions[stat.round - 1]?.opponentPredictions; track opponentTip; let j = $index){
<td [ngClass]="{ alreadyTipped: tipAlreadySet(opponentTip) }">
<span class="tip-value">{{ opponentTip === null ? '-' : opponentTip }}/{{ stat.opponentStitches[j] }}</span>
<span class="stitch-value">{{ opponents[j].score }}</span>
</td>
}
</tr>
</tbody>
</table>

View File

@ -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;
}

View File

@ -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<number | null>;
}
@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);
// 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() {
@ -136,7 +213,7 @@ export class GameComponent implements OnInit {
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,
@ -152,7 +229,21 @@ export class GameComponent implements OnInit {
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;
}
tipAlreadySet(value: number | null | undefined) {
return value !== null;
}
}