Anpassungen bzgl. Stich-Anzeige und Kartenreihenfolge auf dem Stapel
This commit is contained in:
parent
929eeb15e6
commit
7428faa138
|
|
@ -0,0 +1,45 @@
|
|||
{
|
||||
"env": {
|
||||
"es2021": true,
|
||||
"browser": true
|
||||
},
|
||||
"extends": [
|
||||
"airbnb-base",
|
||||
"airbnb-typescript",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"eslint-config-prettier",
|
||||
"plugin:cypress/recommended"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 12,
|
||||
"sourceType": "module",
|
||||
"project": ["./tsconfig.json"]
|
||||
},
|
||||
"plugins": ["@typescript-eslint"],
|
||||
"rules": {
|
||||
"import/no-unresolved": ["off"],
|
||||
"import/prefer-default-export": ["off"],
|
||||
"no-useless-constructor": "off",
|
||||
"@typescript-eslint/no-useless-constructor": ["error"],
|
||||
"@typescript-eslint/lines-between-class-members": ["off"],
|
||||
"no-param-reassign": ["off"],
|
||||
"max-classes-per-file": ["off"],
|
||||
"no-shadow": ["off"],
|
||||
"class-methods-use-this": ["off"],
|
||||
"react/jsx-filename-extension": ["off"],
|
||||
"import/no-cycle": ["off"],
|
||||
"radix": ["off"],
|
||||
"no-promise-executor-return": ["off"],
|
||||
"@typescript-eslint/naming-convention": [
|
||||
"error",
|
||||
{
|
||||
"selector": "enumMember",
|
||||
"format": ["UPPER_CASE", "PascalCase"]
|
||||
}
|
||||
],
|
||||
"no-restricted-syntax": ["error", "ForInStatement", "LabeledStatement", "WithStatement"],
|
||||
"spaced-comment": ["off"],
|
||||
"import/no-extraneous-dependencies": ["error", { "devDependencies": true }]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"arrowParens": "avoid",
|
||||
"embeddedLanguageFormatting": "auto",
|
||||
"htmlWhitespaceSensitivity": "css",
|
||||
"insertPragma": false,
|
||||
"jsxBracketSameLine": false,
|
||||
"jsxSingleQuote": false,
|
||||
"printWidth": 220,
|
||||
"proseWrap": "always",
|
||||
"quoteProps": "as-needed",
|
||||
"requirePragma": false,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "all",
|
||||
"useTabs": false,
|
||||
"vueIndentScriptAndStyle": false
|
||||
}
|
||||
|
|
@ -10,11 +10,18 @@
|
|||
"url": "http://localhost:4200/"
|
||||
},
|
||||
{
|
||||
"name": "ng test",
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "npm: test",
|
||||
"url": "http://localhost:9876/debug.html"
|
||||
"name": "Debug Tests",
|
||||
"url": "http://localhost:9876/debug.html",
|
||||
"webRoot": "${workspaceFolder}",
|
||||
"sourceMaps": true,
|
||||
"sourceMapPathOverrides": {
|
||||
"webpack:/*": "${webRoot}/*"
|
||||
},
|
||||
"runtimeArgs": [
|
||||
"--headless"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"editor.suggestSelection": "first",
|
||||
"vsintellicode.modify.editor.suggestSelection": "automaticallyOverrodeDefaultValue",
|
||||
"explorer.confirmDelete": false,
|
||||
"typescript.updateImportsOnFileMove.enabled": "always",
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[html]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "vscode.json-language-features"
|
||||
},
|
||||
"[scss]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[jsonc]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"editor.formatOnSave": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.organizeImports": "explicit"
|
||||
},
|
||||
"prettier.printWidth": 240,
|
||||
"git.autofetch": false,
|
||||
"git.autorefresh": true
|
||||
}
|
||||
|
||||
|
|
@ -67,7 +67,6 @@ import { CommonModule } from '@angular/common';
|
|||
color: green;
|
||||
font-weight: bold;
|
||||
font-size: 24px;
|
||||
z-index: 2;
|
||||
}
|
||||
.logo.top {
|
||||
top: 20%;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
export interface Card {
|
||||
number: number;
|
||||
color: string;
|
||||
playable?: boolean;
|
||||
}
|
||||
|
||||
// card.service.ts
|
||||
|
|
|
|||
|
|
@ -1,49 +0,0 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CardBackComponent } from './card-back.component';
|
||||
import { CardFrontComponent } from './card-front.component';
|
||||
import { Card, CardService } from './card.service';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-deck',
|
||||
standalone: true,
|
||||
imports: [CommonModule, CardFrontComponent, CardBackComponent],
|
||||
template: `
|
||||
<div class="deck">
|
||||
<div *ngFor="let card of deck; let i = index" (click)="flipCard(i)">
|
||||
<app-card-front *ngIf="flippedCards[i]" [number]="card.number" [color]="card.color"></app-card-front>
|
||||
<app-card-back *ngIf="!flippedCards[i]"></app-card-back>
|
||||
</div>
|
||||
</div>
|
||||
<button (click)="shuffleDeck()">Mischen</button>
|
||||
`,
|
||||
styles: [`
|
||||
.deck {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
`]
|
||||
})
|
||||
export class DeckComponent implements OnInit {
|
||||
deck: Card[] = [];
|
||||
flippedCards: boolean[] = [];
|
||||
|
||||
constructor(private cardService: CardService) {}
|
||||
|
||||
ngOnInit() {
|
||||
// this.deck = this.cardService.getDeck();
|
||||
// this.flippedCards = new Array(this.deck.length).fill(false);
|
||||
}
|
||||
|
||||
// flipCard(index: number) {
|
||||
// this.flippedCards[index] = !this.flippedCards[index];
|
||||
// }
|
||||
|
||||
// shuffleDeck() {
|
||||
// this.cardService.shuffleDeck();
|
||||
// this.deck = this.cardService.getDeck();
|
||||
// this.flippedCards = new Array(this.deck.length).fill(false);
|
||||
// }
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
import { Card, CardService } from './card.service';
|
||||
import { Player } from './game.component';
|
||||
|
||||
|
||||
export class GameRuleEngine {
|
||||
private trumpColor: string = 'red';
|
||||
|
||||
constructor(private cardService: CardService) {}
|
||||
|
||||
determineStartingPlayer(roundNumber: number, playerCount: number): number {
|
||||
return (roundNumber - 1) % playerCount;
|
||||
}
|
||||
|
||||
determineWinner(playedCards: Card[], players: Player[]): Player {
|
||||
let winningCard:Card = playedCards[0];
|
||||
const leadColor = playedCards[0].color;
|
||||
|
||||
for (let i = 1; i < playedCards.length; i++) {
|
||||
if (this.isWinningCard(playedCards[i], winningCard, leadColor)) {
|
||||
winningCard=playedCards[i]
|
||||
}
|
||||
}
|
||||
|
||||
return players.find(p=>p.playedCard?.color===winningCard.color && p.playedCard.number===winningCard.number) ||players[0]
|
||||
}
|
||||
|
||||
private isWinningCard(card: Card, currentWinningCard: Card, leadColor: string): boolean {
|
||||
// Wenn beide Karten Trumpf sind, gewinnt die höhere
|
||||
if (card.color === this.trumpColor && currentWinningCard.color === this.trumpColor) {
|
||||
return card.number > currentWinningCard.number;
|
||||
}
|
||||
|
||||
// Wenn nur die neue Karte Trumpf ist, gewinnt sie
|
||||
if (card.color === this.trumpColor && currentWinningCard.color !== this.trumpColor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Wenn die aktuelle Gewinnerkarte Trumpf ist, kann keine andere Farbe gewinnen
|
||||
if (currentWinningCard.color === this.trumpColor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Wenn keine der Karten Trumpf ist, gewinnt die höhere Karte der Ausgangsfarbe
|
||||
if (card.color === leadColor && currentWinningCard.color === leadColor) {
|
||||
return card.number > currentWinningCard.number;
|
||||
}
|
||||
|
||||
// Wenn nur die neue Karte die Ausgangsfarbe hat, gewinnt sie
|
||||
if (card.color === leadColor && currentWinningCard.color !== leadColor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// In allen anderen Fällen gewinnt die neue Karte nicht
|
||||
return false;
|
||||
}
|
||||
|
||||
canPlayCard(card: Card, hand: Card[], leadCard: Card | null): boolean {
|
||||
if (!leadCard) return true; // Erste Karte des Stichs
|
||||
if (card.color === leadCard.color) return true; // Gleiche Farbe wie die Ausgangskarte
|
||||
return !hand.some(c => c.color === leadCard.color); // Keine Karte der Ausgangsfarbe in der Hand
|
||||
}
|
||||
|
||||
getPlayableCards(hand: Card[], leadCard: Card | null): Card[] {
|
||||
if (!leadCard) return hand;
|
||||
const sameColorCards = hand.filter(card => card.color === leadCard.color);
|
||||
return sameColorCards.length > 0 ? sameColorCards : hand;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
<div class="game">
|
||||
<div class="game-setup" *ngIf="!gameStarted">
|
||||
<label for="opponentCount">Anzahl der Gegner (1-3):</label>
|
||||
<input type="number" id="opponentCount" [(ngModel)]="numberOfOpponents" min="1" max="3" />
|
||||
<button (click)="startGame()">Spiel starten</button>
|
||||
</div>
|
||||
|
||||
@if (gameStarted) {
|
||||
<div class="opponents-area">
|
||||
@for (opponent of opponents; track opponent; let i = $index) {
|
||||
<div class="opponent-hand">
|
||||
@for (card of opponent.hand; track card; let cardIndex = $index) {
|
||||
<app-card-back [style.left.px]="cardIndex * 30" class="stacked-card"> </app-card-back>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="play-area">
|
||||
<div class="played-cards">
|
||||
@for (playedCard of playedCards; track playedCard; let i = $index) { @if(i===0){
|
||||
<app-card-front *ngIf="playedCard" [number]="playedCard.number" [color]="playedCard.color" class="player-played-card"> </app-card-front>
|
||||
} @if(i>0){
|
||||
<app-card-front [number]="playedCard.number" [color]="playedCard.color" [style.top.px]="i * 30" [style.left.px]="i * 30" class="opponent-played-card"> </app-card-front>
|
||||
} }
|
||||
</div>
|
||||
</div>
|
||||
<div class="player-hand">
|
||||
@for (card of player.hand; track card; let i = $index) {
|
||||
<app-card-front [number]="card.number" [color]="card.color" (click)="playCard(i)" [class.disabled]="player.playedCard"> </app-card-front>
|
||||
}
|
||||
</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>
|
||||
<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">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Runde</th>
|
||||
<th>Spieler</th>
|
||||
<th *ngFor="let opponent of opponents">Gegner {{ opponent.id }}</th>
|
||||
</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>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
.game {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
.game-setup {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.opponents-area {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
min-height: 320px;
|
||||
}
|
||||
.opponent-hand {
|
||||
position: relative;
|
||||
width: 200px;
|
||||
height: 280px;
|
||||
}
|
||||
.stacked-card {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
}
|
||||
.player-hand {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
min-height: 320px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.play-area {
|
||||
flex: 1 1 auto;
|
||||
min-height: 200px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.played-cards {
|
||||
position: relative;
|
||||
width: 140px;
|
||||
height: 200px;
|
||||
}
|
||||
.player-played-card {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
.opponent-played-card {
|
||||
position: absolute;
|
||||
}
|
||||
.disabled {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
.game-info {
|
||||
height: 10%;
|
||||
min-height: 80px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
}
|
||||
.score {
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
}
|
||||
.round-stats {
|
||||
position: fixed;
|
||||
right: 20px;
|
||||
top: 20px;
|
||||
width: 250px;
|
||||
background-color: #f9f9f9;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
font-size: 14px;
|
||||
z-index: 100;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.round-stats th,
|
||||
.round-stats td {
|
||||
padding: 8px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.round-stats thead {
|
||||
background-color: #f1f1f1;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.round-stats tbody tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
|
@ -1,112 +1,64 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { CardFrontComponent } from './card-front.component';
|
||||
import { CardBackComponent } from './card-back.component';
|
||||
import { CardService, Card } from './card.service';
|
||||
import { GameRuleEngine } from './game-rule-engine';
|
||||
|
||||
export interface Player {
|
||||
id: number;
|
||||
hand: Card[];
|
||||
playedCard: Card | null;
|
||||
score: number;
|
||||
}
|
||||
interface RoundStats {
|
||||
round: number;
|
||||
playerStitches: number;
|
||||
opponentStitches: number[];
|
||||
}
|
||||
@Component({
|
||||
selector: 'app-game',
|
||||
standalone: true,
|
||||
imports: [CommonModule, CardFrontComponent, CardBackComponent],
|
||||
template: `
|
||||
<div class="game">
|
||||
<div class="opponent-hand">
|
||||
<app-card-back *ngFor="let card of opponentHand"></app-card-back>
|
||||
</div>
|
||||
<div class="play-area">
|
||||
<div class="played-cards" *ngIf="playerPlayedCard || opponentPlayedCard">
|
||||
<app-card-front *ngIf="playerPlayedCard" [number]="playerPlayedCard.number" [color]="playerPlayedCard.color" class="player-played-card"></app-card-front>
|
||||
<app-card-front *ngIf="opponentPlayedCard" [number]="opponentPlayedCard.number" [color]="opponentPlayedCard.color" class="opponent-played-card"></app-card-front>
|
||||
</div>
|
||||
</div>
|
||||
<div class="player-hand">
|
||||
<app-card-front *ngFor="let card of playerHand; let i = index"
|
||||
[number]="card.number"
|
||||
[color]="card.color"
|
||||
(click)="playCard(i)"
|
||||
[class.disabled]="playerPlayedCard">
|
||||
</app-card-front>
|
||||
</div>
|
||||
<div class="game-info">
|
||||
<div class="score">
|
||||
Spieler: {{playerScore}} | Gegner: {{opponentScore}} | Runde: {{currentRound}}/10
|
||||
</div>
|
||||
<button (click)="startNewRound()" [disabled]="playerHand.length > 0 || currentRound > 10">Nächste Runde</button>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
styles: [`
|
||||
.game {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
.opponent-hand, .player-hand {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
min-height: 320px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.play-area {
|
||||
flex: 1 1 auto;
|
||||
min-height: 200px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.played-cards {
|
||||
position: relative;
|
||||
width: 140px;
|
||||
height: 200px;
|
||||
}
|
||||
.player-played-card {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
.opponent-played-card {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
.disabled {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
.game-info {
|
||||
height: 10%;
|
||||
min-height: 80px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
}
|
||||
.score {
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
}
|
||||
`]
|
||||
imports: [CommonModule, FormsModule, CardFrontComponent, CardBackComponent],
|
||||
templateUrl: './game.component.html',
|
||||
styleUrls: ['./game.component.scss']
|
||||
})
|
||||
export class GameComponent implements OnInit {
|
||||
playerHand: Card[] = [];
|
||||
opponentHand: Card[] = [];
|
||||
playerPlayedCard: Card | null = null;
|
||||
opponentPlayedCard: Card | null = null;
|
||||
playerScore: number = 0;
|
||||
opponentScore: number = 0;
|
||||
player: Player = { id: 0, hand: [], playedCard: null, score: 0 };
|
||||
opponents: Player[] = [];
|
||||
currentRound: number = 0;
|
||||
numberOfOpponents: number = 1;
|
||||
gameStarted: boolean = false;
|
||||
currentPlayerIndex: number = 0;
|
||||
playedCards: Card[] = [];
|
||||
leadCard: Card | null = null;
|
||||
roundStats: RoundStats[] = [];
|
||||
private ruleEngine: GameRuleEngine;
|
||||
|
||||
constructor(private cardService: CardService) {}
|
||||
constructor(private cardService: CardService) {
|
||||
this.ruleEngine = new GameRuleEngine(cardService);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
ngOnInit() {}
|
||||
|
||||
startGame() {
|
||||
if (this.numberOfOpponents < 1 || this.numberOfOpponents > 3) {
|
||||
alert("Bitte wählen Sie 1 bis 3 Gegner.");
|
||||
return;
|
||||
}
|
||||
this.gameStarted = true;
|
||||
this.initializePlayers();
|
||||
this.startNewRound();
|
||||
}
|
||||
|
||||
initializePlayers() {
|
||||
this.opponents = [];
|
||||
for (let i = 0; i < this.numberOfOpponents; i++) {
|
||||
this.opponents.push({ id: i + 1, hand: [], playedCard: null, score: 0 });
|
||||
}
|
||||
}
|
||||
|
||||
startNewRound() {
|
||||
if (this.currentRound >= 10) {
|
||||
this.endGame();
|
||||
|
|
@ -117,10 +69,107 @@ export class GameComponent implements OnInit {
|
|||
const cardsForThisRound = this.getCardsForRound(this.currentRound);
|
||||
|
||||
this.cardService.shuffleDeck();
|
||||
this.playerHand = this.cardService.drawCards(cardsForThisRound);
|
||||
this.opponentHand = this.cardService.drawCards(cardsForThisRound);
|
||||
this.playerPlayedCard = null;
|
||||
this.opponentPlayedCard = null;
|
||||
this.player.hand = this.cardService.drawCards(cardsForThisRound);
|
||||
this.opponents.forEach(opponent => {
|
||||
opponent.hand = this.cardService.drawCards(cardsForThisRound);
|
||||
});
|
||||
|
||||
this.resetPlayedCards();
|
||||
this.currentPlayerIndex = this.ruleEngine.determineStartingPlayer(this.currentRound, this.opponents.length + 1);
|
||||
this.playTrick();
|
||||
}
|
||||
|
||||
playTrick() {
|
||||
if (this.currentPlayerIndex === 0) {
|
||||
// Player's turn
|
||||
this.enablePlayableCards();
|
||||
} else {
|
||||
// Opponent's turn
|
||||
setTimeout(() => this.playOpponentCard(), 1000);
|
||||
}
|
||||
}
|
||||
|
||||
enablePlayableCards() {
|
||||
const playableCards = this.ruleEngine.getPlayableCards(this.player.hand, this.leadCard);
|
||||
this.player.hand.forEach(card => {
|
||||
card.playable = playableCards.includes(card);
|
||||
});
|
||||
}
|
||||
|
||||
playCard(index: number) {
|
||||
const card = this.player.hand[index];
|
||||
if (!card.playable) return;
|
||||
|
||||
this.player.playedCard = this.player.hand.splice(index, 1)[0];
|
||||
this.playedCards.push(this.player.playedCard);
|
||||
//this.playedCards.unshift(this.player.playedCard); // Füge die Karte an den Anfang anstatt ans Ende hinzu
|
||||
if (!this.leadCard) this.leadCard = this.player.playedCard;
|
||||
|
||||
this.moveToNextPlayer();
|
||||
}
|
||||
|
||||
playOpponentCard() {
|
||||
const opponent = this.opponents[this.currentPlayerIndex - 1];
|
||||
const playableCards = this.ruleEngine.getPlayableCards(opponent.hand, this.leadCard);
|
||||
const randomIndex = Math.floor(Math.random() * playableCards.length);
|
||||
opponent.playedCard = playableCards[randomIndex];
|
||||
opponent.hand = opponent.hand.filter(card => card !== opponent.playedCard);
|
||||
this.playedCards.push(opponent.playedCard);
|
||||
//this.playedCards.unshift(opponent.playedCard); // Füge die Karte an den Anfang anstatt ans Ende hinzu
|
||||
if (!this.leadCard) this.leadCard = opponent.playedCard;
|
||||
|
||||
this.moveToNextPlayer();
|
||||
}
|
||||
|
||||
moveToNextPlayer() {
|
||||
if (this.playedCards.length === this.opponents.length + 1) {
|
||||
// All players have played their cards
|
||||
setTimeout(() => this.evaluateTrick(), 1000);
|
||||
} else {
|
||||
this.currentPlayerIndex = (this.currentPlayerIndex + 1) % (this.opponents.length + 1);
|
||||
this.playTrick();
|
||||
}
|
||||
}
|
||||
|
||||
evaluateTrick() {
|
||||
const allPlayers = [this.player, ...this.opponents];
|
||||
const winner = this.ruleEngine.determineWinner(this.playedCards, allPlayers);
|
||||
winner.score++;
|
||||
|
||||
// Neue Logik, um Stiche zu speichern
|
||||
if (!this.roundStats[this.currentRound - 1]) {
|
||||
this.roundStats[this.currentRound - 1] = {
|
||||
round: this.currentRound,
|
||||
playerStitches: 0,
|
||||
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]++;
|
||||
}
|
||||
|
||||
if (this.player.hand.length === 0) {
|
||||
if (this.currentRound < 10) {
|
||||
setTimeout(() => this.startNewRound(), 500);
|
||||
} else {
|
||||
this.endGame();
|
||||
}
|
||||
} else {
|
||||
this.resetPlayedCards();
|
||||
this.currentPlayerIndex = allPlayers.indexOf(winner);
|
||||
this.playTrick();
|
||||
}
|
||||
}
|
||||
|
||||
resetPlayedCards() {
|
||||
this.playedCards = [];
|
||||
this.leadCard = null;
|
||||
this.player.playedCard = null;
|
||||
this.opponents.forEach(opponent => opponent.playedCard = null);
|
||||
}
|
||||
|
||||
getCardsForRound(round: number): number {
|
||||
|
|
@ -128,57 +177,23 @@ export class GameComponent implements OnInit {
|
|||
return 11 - round;
|
||||
}
|
||||
|
||||
playCard(index: number) {
|
||||
if (this.playerPlayedCard) return;
|
||||
|
||||
this.playerPlayedCard = this.playerHand.splice(index, 1)[0];
|
||||
setTimeout(() => this.opponentPlay(), 1000);
|
||||
}
|
||||
|
||||
opponentPlay() {
|
||||
if (this.opponentHand.length === 0) return;
|
||||
|
||||
const randomIndex = Math.floor(Math.random() * this.opponentHand.length);
|
||||
this.opponentPlayedCard = this.opponentHand.splice(randomIndex, 1)[0];
|
||||
|
||||
setTimeout(() => this.evaluatePlay(), 1000);
|
||||
}
|
||||
|
||||
evaluatePlay() {
|
||||
if (!this.playerPlayedCard || !this.opponentPlayedCard) return;
|
||||
|
||||
const result = this.cardService.compareCards(this.playerPlayedCard, this.opponentPlayedCard);
|
||||
if (result > 0) {
|
||||
this.playerScore++;
|
||||
} else if (result < 0) {
|
||||
this.opponentScore++;
|
||||
}
|
||||
|
||||
if (this.playerHand.length === 0) {
|
||||
if (this.currentRound < 10) {
|
||||
setTimeout(() => {
|
||||
alert(`Runde ${this.currentRound} beendet! Spieler: ${this.playerScore}, Gegner: ${this.opponentScore}`);
|
||||
this.playerPlayedCard = null;
|
||||
this.opponentPlayedCard = null;
|
||||
}, 500);
|
||||
} else {
|
||||
this.endGame();
|
||||
}
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
this.playerPlayedCard = null;
|
||||
this.opponentPlayedCard = null;
|
||||
}, 1500);
|
||||
}
|
||||
}
|
||||
|
||||
endGame() {
|
||||
let result = "Unentschieden!";
|
||||
if (this.playerScore > this.opponentScore) {
|
||||
result = "Sie haben gewonnen!";
|
||||
} else if (this.playerScore < this.opponentScore) {
|
||||
result = "Der Gegner hat gewonnen!";
|
||||
}
|
||||
alert(`Spiel beendet! ${result}\nEndstand - Spieler: ${this.playerScore}, Gegner: ${this.opponentScore}`);
|
||||
const allPlayers = [this.player, ...this.opponents];
|
||||
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 scoreMessage = `Endstand - Spieler: ${this.player.score}`;
|
||||
this.opponents.forEach((opponent) => {
|
||||
scoreMessage += `, Gegner ${opponent.id}: ${opponent.score}`;
|
||||
});
|
||||
|
||||
alert(`Spiel beendet! ${result}\n${scoreMessage}`);
|
||||
this.gameStarted = false;
|
||||
this.currentRound = 0;
|
||||
this.player.score = 0;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue