diff --git a/uno/index.html b/uno/index.html index ab8adb8..08768cd 100644 --- a/uno/index.html +++ b/uno/index.html @@ -3,13 +3,14 @@ Uno +

- - + + \ No newline at end of file diff --git a/uno/web/Game.js b/uno/web/Game.js new file mode 100644 index 0000000..1b13fe2 --- /dev/null +++ b/uno/web/Game.js @@ -0,0 +1,259 @@ +//Imports +import Card from "./cards/Card.js"; +import ChooseColor from "./cards/special/ChooseColor.js"; +import Skip from "./cards/special/Skip.js"; +import PlusAmount from "./cards/special/PlusAmount.js"; +import Reverse from "./cards/special/Reverse.js"; +import Player from "./Player.js"; +import {CARD_COLORS} from "./uno.js"; + +//Um generatePool zu exportieren, muss es in eine Klasse konvertiert werden +export default class Game { + + //Erstellt ein Spiel mit SpielerAnzahl und Array mit Regeln, initialisiert dann das Spiel + constructor(playerAmount, rules) { + + this._cardOnDeck = null; //Karte die auf dem Tisch liegt + this._currentPlayer = -1; //Aktueller Spieler Index im Player Array + this._direction = 1; //Spielrichtung + this._players = []; //Array mit allen Spielern drin + this._cardPool = []; //Pool aus Karten + + this._playerAmount = playerAmount; //Anzahl der Spieler + this._rules = rules; //Array mit Regeln für das Spiel + + } + + //Richtet das Spiel ein + initGame(){ + + //CardPool wird generiert + this._cardPool = this.generatePool(); + + //Spieler werden erstellt + this.createPlayers(this._playerAmount); + + } + + //Startet das Spiel + start(){ + if(this._currentPlayer !== -1) return; + + //Wenn das Spiel noch nicht initialisiert wurde, initialisiere es + if (this._cardPool.length === 0 || this._players.length === 0) + this.initGame(); + + + let firstCardIndex = 0; + let boolFirstSpecial = false; + + if (this._rules !== null){ + if('startCards' in this.rules) + for (let i = 0; i < this.players.length; i++) + this.players[i].drawCard(this.rules.startCards); + + if('firstPlaySpecial' in this.rules) + boolFirstSpecial = this.rules.firstPlaySpecial; + + + + + } + + if (!boolFirstSpecial){ + for (let i = 0; i < this.cardPool.length; i++){ + if (!(this.cardPool[i].name === 'R' || this.cardPool[i].name === 'S' + || this.cardPool[i].name === 'CC' || this.cardPool[i].name === '+2' + || this.cardPool[i].name === '+4')){ + firstCardIndex = i; + break; + } + } + } + + //Die Erste Karte wird auf den Tisch gelegt + this._cardOnDeck = this._cardPool[firstCardIndex]; + this._cardPool.splice(firstCardIndex,1); + + //Karten Funktion der Karte auf dem Deck ausführen + this.cardOnDeck.putSelf(); + + } + + // + gameLoop(){ + + } + + //Gibt ein Array zurück mit allen Karten, die in einem Uno Spiel sind + generatePool(){ + + //Array wird erstellt, welches später zurückgegeben wird und alle Karten beinhaltet + let pool = []; + + //Pool aus Karten generieren + for (let k = 0; k < 2; k++) { + + //Special Karten werden hinzugefügt + for (let j = 1; j < (CARD_COLORS.length); j++) { + + pool.push(new Reverse(CARD_COLORS[j], this)); // 8x Reverse + pool.push(new PlusAmount(this, CARD_COLORS[j])); // 8x +2 + pool.push(new Skip(CARD_COLORS[j], this)); // 8x Skip + + if (k === 0) { + + pool.push(new ChooseColor(this)); // 4x ChooseColor + pool.push(new PlusAmount(this)); // 4x +4 + + } + + //Normale Karten werden hinzugefügt + for (let i = 0; i <= 9; i++) { + + if (k === 1 && i === 0) continue; + pool.push(new Card(i, CARD_COLORS[j], this)); // 76x (2x 4x 1-9 + 4x 0) + + } + + } + + } + + //Mischt das Array + pool.sort(()=> Math.random() - 0.5); + + //Array mit Karten wird zurückgegeben + return pool; + } + + //Fügt die Spieler hinzu + createPlayers(playerAmount){ + + //Erstelle so viele Spieler, wie bei Erstellung des Spiels übergeben wurden + for (let i = 0; i < playerAmount; i++){ + this._players.push(new Player("Player" + (i + 1), this)); + } + + } + + //Beendet den Zug des aktuellen Spielers und beginnt den Zug des nächsten Spielers + nextTurn(){ + + //Testet, ob Spiel Gewonnen + for (let i = 0; i < this.players.length; i++){ + if(this.players[i].hand.length <= 0){ + + //Breche den Loop ab + return; + } + } + + //Wenn Zug nicht der Erste vom ganzen Spiel + if(this.currentPlayer !== -1){ + + //Aktuellen Spieler kann, darf nicht mehr Spielen + this.players[this.currentPlayer].canPlay = false; + + } + + //nächster Spieler wird gesetzt + this.currentPlayer = this.nextPlayer(); + + //Aktualisiere das Deck des aktuellen Spielers, welche Karten er legen kann + this.refreshCanPutCard(); + + } + + //Testet alle Karten des aktuellen Spielers in seiner Hand, ob er sie legen kann + refreshCanPutCard(){ + //Deck des aktuellen Spielers + let currentPlayerCards = this.players[this.currentPlayer].hand; + + //Gehe alle Karten vom Deck durch + for(let i = 0; i < currentPlayerCards.length; i++){ + + //Wenn Farbe oder Zahl gleich oder eine Karte, die keine Farbe hat + if(this._cardOnDeck.name.toString() === currentPlayerCards[i].name.toString() || + this._cardPool._color === currentPlayerCards[i].color || + currentPlayerCards[i].color === CARD_COLORS[0] || + this.cardOnDeck.color === CARD_COLORS[0]) { + + //Aktualisiere den Wert der Karte, sodass sie gelegt werden kann + this._players[this._currentPlayer].hand[i].canPut = true; + + //Der Spieler kann nun Karten legen + this._players[this._currentPlayer].canPlay = true; + + } else { + + //Sonst setze den Wert der Karte so, dass sie nicht gelegt werden kann + this._players[this._currentPlayer].hand[i].canPut = false; + + } + + } + + } + + //Errechne, wer der nächste Spieler ist + nextPlayer(){ + if(this.currentPlayer === -1) + return 0; + + //Anhand der Spielrichtung errechnen + if(this._direction === 1) + return (this._currentPlayer === this._players.length - 1) ? 0 : this._currentPlayer + 1; //bei normaler Richtung + else + return (this._currentPlayer === 0) ? this._players.length - 1 : this._currentPlayer - 1; //bei Invertierter Richtung + + } + + //Gib den Pool mit allen UnoKarten zurück + get cardPool(){ + return this._cardPool; + } + + //Gibt das Array mit allen Spielern des Spiels zurück + get players(){ + return this._players; + } + + //Gibt die aktuelle Karte auf dem Tisch zurück + get cardOnDeck(){ + return this._cardOnDeck; + } + + //Setzt die aktuelle Karte auf dem Tisch + set cardOnDeck(card){ + this._cardOnDeck = card; + } + + //Gibt den Index des aktuellen Spielers im players Array zurück + get currentPlayer(){ + return this._currentPlayer; + } + + //Gibt das Objekt des aktuellen Spielers zurück + get currentPlayerInstanz(){ + return this._players[this.currentPlayer]; + } + + set currentPlayer(player){ + this._currentPlayer = player + } + + //Gibt die aktuelle Ricktung zurück 1 = normal 2 = Invertiert + get direction(){ + return this._direction; + } + + set direction(direction){ + this._direction = direction; + } + + get rules(){ + return this._rules; + } + +} \ No newline at end of file diff --git a/uno/web/Player.js b/uno/web/Player.js new file mode 100644 index 0000000..edcd63d --- /dev/null +++ b/uno/web/Player.js @@ -0,0 +1,98 @@ +//Klasse Player für Spieler einer Uno Runde +import {CARD_COLORS} from "./uno.js"; + +export default class Player { + + //Erstellt ein Spieler mit einem Namen und dem Spiel, in dem er teilnimmt + constructor(name, gameInstanz) { + + this._game = gameInstanz; //Spiel, worin der Spieler ist + this._name = name; //Name des Spielers + this._turn = false; //Ob Spieler gerade am Zug + this._hand = []; //Deck des Spielers + this._canPlay = false //Ob spieler gerade Karte legen kann + + } + + //Lässt den Spieler eine Anzahl "amount" an Karten ziehen + drawCard(amount){ + + //Ziehe so viele Karten, wie amount übergeben wurde + for (let i = 0; i < amount; i++){ + + //Füge die erste Karte aus cardPool der Hand des Spielers hinzu + this._hand.push(this._game.cardPool[0]); + //Lösche die erste Karte aus cardPool + this._game.cardPool.splice(0, 1); + + } + + if(amount === 1) + this._game.nextTurn(); + + } + + //Lässt den Spieler eine Karte in seiner Hand legen + //Parameter: Index vom Deck des Spielers, wo die Karte liegt + putCard(index){ + //Karte muss hinterlegt haben, dass sie gelegt werden kann + if(!this._hand[index].canPut) return; + if(this._turn === false) return; + + //Wenn eine Karte auf dem Tisch liegt + if(this._game.cardOnDeck != null){ + + //Wenn eine "NONE" Color Karte gelegt wurde, resette die Farbe auf "NONE" + if(this._game.cardOnDeck.name === "CC" || this._game.cardOnDeck.name === "+4") + this._game.cardOnDeck.color = CARD_COLORS[0]; + + //Füge die Karte dem Pool wieder hinzu + this._game.cardPool.push(this._game.cardOnDeck); + } + + //Karte in der Hand wird auf den Tisch gelegt + this._game.cardOnDeck = this._hand[index]; + + //Karte wird aus dem Deck des Spielers entfernt + this._hand.splice(index, 1); + + //führe Funktion der Karte aus + this._game.cardOnDeck.putSelf(); + } + + selectColor(){ + + //Todo: Spieler Möglichkeit geben Farbe zu wählen, nicht random + return CARD_COLORS[Math.floor(Math.random() * 4) + 1]; + } + + //Gibt den Namen eines Spielers zurück + get name() { + return this._name; + } + + //Gibt zurück, ob der Spieler am Zug ist + get turn(){ + return this._turn; + } + + //Setzt, dass der Spieler gerade am Zug ist oder nicht + set turn(bool){ + this._turn = bool; + } + + //Gibt zurück, ob der Spieler eine Karte legen kann + get canPlay(){ + return this._canPlay; + } + + set canPlay(bool){ + this._canPlay = bool; + } + + //Gibt das SpielerDeck zurück + get hand(){ + return this._hand; + } + +} \ No newline at end of file diff --git a/uno/web/cards/Card.js b/uno/web/cards/Card.js new file mode 100644 index 0000000..5a936c5 --- /dev/null +++ b/uno/web/cards/Card.js @@ -0,0 +1,59 @@ + +//Klasse Card für die UnoKarten +export default class Card { + + //Konstruktor für das Erstellen einer Karte + constructor(name, color, gameInstanz, ) { + + this._game = gameInstanz; + this._onScreen = false; //Die Karte wird bei Erstellung noch nicht auf dem Bildschirm angezeigt + this._canPut = false; //Die Karte kann bei Erstellung nicht gelegt werden + this._name = name; //Name der Karte (z.B. 0,1...,9,+2,+4,CC,R,S) + this._color = color; //Farbe der Karte (CARD_COLORS) + + } + + //Logik beim Legen einer Karte (wird für alle Karten ausgeführt) + putSelf(){ + + //Nächster Spieler am Zug + this.game.nextTurn(); + + } + + //Gibt den Namen der Karte zurück + get name() { + return this._name; + } + + //Gibt zurück, ob die Karte gelegt werden kann + get canPut() { + return this._canPut; + } + + //Gibt die Farbe der Karte zurück + get color() { + return this._color; + } + + //Setzt die Farbe der Karte + set color(color) { + this._color = color; + } + + //Gibt zurück ob die Karte sich auf dem Bildschirm befindet + get onScreen() { + return this._onScreen; + } + + //Gibt die Instanz vom Game zurück + get game(){ + return this._game; + } + + //Setzt, ob die Karte gelegt werden kann, oder nicht + set canPut(bool){ + this._canPut = bool; + } + +} \ No newline at end of file diff --git a/uno/web/cards/special/ChooseColor.js b/uno/web/cards/special/ChooseColor.js new file mode 100644 index 0000000..ce2711b --- /dev/null +++ b/uno/web/cards/special/ChooseColor.js @@ -0,0 +1,31 @@ +//Imports +import Card from "../Card.js"; +import {CARD_COLORS} from "../../uno.js"; + +//Klasse ChooseColor für FarbWahlKarten +export default class ChooseColor extends Card { + + //Konstruktor für das Erstellen einer ChooseColor-Karte + constructor(gameInstanz) { + + //An Konstruktor von Cards weitergeben + super("CC", CARD_COLORS[0], gameInstanz); + + } + + //Führt eigene Logik aus (Wählt farbe aus) + putSelf() { + + if(this.game.currentPlayer === -1) { + //Setzt die Farbe der Karte auf eine Random Farbe + this.color = CARD_COLORS[Math.floor(Math.random() * 4) + 1]; + } + else{ + //lässt den Spieler eine Farbe wählen + this._color = this.game.players[this.game.currentPlayer].selectColor(); + } + //Logik von Card.js ausführen + super.putSelf(); + } + +} \ No newline at end of file diff --git a/uno/web/cards/special/PlusAmount.js b/uno/web/cards/special/PlusAmount.js new file mode 100644 index 0000000..01fcfcd --- /dev/null +++ b/uno/web/cards/special/PlusAmount.js @@ -0,0 +1,43 @@ +//Imports +import Card from "../Card.js"; +import {CARD_COLORS} from "../../uno.js"; + +//Klasse PlusAmount für Karten, die den nächsten Spieler ziehen lassen +export default class PlusAmount extends Card { + + //Konstruktor für das Erstellen einer PlusAmount-Karte (+4/+2) + constructor(gameInstanz, color = CARD_COLORS[0]) { + + //An Konstruktor von Cards weitergeben + super((color === CARD_COLORS[0]) ? "+4" : "+2", color, gameInstanz); + + //Wenn keine Farbe beim Konstruktor übergeben wird, plus = 4, sonst plus = 2 + if (color === CARD_COLORS[0]) this._plus = 4; else this._plus = 2; + + } + + //Führt eigene Logik aus (+Amount Karten für den nächsten Spieler) + putSelf() { + + //Todo: Karten Stapeln Regel + //lässt den nächsten Spieler den PlusAmount der Karte ziehen + this.game.players[this.game.nextPlayer()].drawCard(this._plus); + + if(this._plus === 4){ + + if(this.game.currentPlayer === -1) + this.color = CARD_COLORS[Math.floor(Math.random() * 4) + 1]; + else + this._color = this.game.players[this.game.currentPlayer].selectColor(); + } + + //Logik von Card.js ausführen + super.putSelf(); + } + + //Gibt den PlusWert der Karte zurück + get plus() { + return this._plus; + } + +} \ No newline at end of file diff --git a/uno/web/cards/special/Reverse.js b/uno/web/cards/special/Reverse.js new file mode 100644 index 0000000..2521bb9 --- /dev/null +++ b/uno/web/cards/special/Reverse.js @@ -0,0 +1,25 @@ +//Imports +import Card from "../Card.js"; + +//Klasse Reverse für Karten, die die Spielrichtung ändern +export default class Reverse extends Card { + + //Konstruktor für das Erstellen einer Reverse-Karte + constructor(color, gameInstanz) { + + //An Konstruktor von Cards weitergeben + super("R", color, gameInstanz); + + } + + //Führt eigene Logik aus (Wechselt die Spielrichtung des Spiels) + putSelf() { + + //Spielrichtung wechseln + this.game.direction = this.game.direction % 2 + 1; // Setzt bei direction = 1 auf 2 und 2 auf 1 + + //Logik von Card.js ausführen + super.putSelf(); + } + +} \ No newline at end of file diff --git a/uno/web/cards/special/Skip.js b/uno/web/cards/special/Skip.js new file mode 100644 index 0000000..baa1202 --- /dev/null +++ b/uno/web/cards/special/Skip.js @@ -0,0 +1,25 @@ +//Imports +import Card from "../Card.js"; + +//Klasse Skip für Karten, die den nächsten Spieler überspringen +export default class Skip extends Card { + + //Konstruktor für das Erstellen einer Skip-Karte + constructor(color, gameInstanz) { + + //An Konstruktor von Cards weitergeben + super("S", color, gameInstanz); + + } + + //Führt Logik der Karte aus (den nächsten Spieler überspringen) + putSelf() { + + //Der nächste Spieler wird auf currentPlayer gesetzt -> Überspringt diesen Spieler, weil beim nächsten Zug wieder nächster SPieler + this.game.currentPlayer = this.game.nextPlayer(); + + //Logik von Card.js ausführen + super.putSelf(); + } + +} \ No newline at end of file diff --git a/uno/web/uno.js b/uno/web/uno.js new file mode 100644 index 0000000..81432cb --- /dev/null +++ b/uno/web/uno.js @@ -0,0 +1,18 @@ +//Legt mögliche Farben fest, "NONE" sind Auswahlkarten +import Game from "./Game.js"; + +export const CARD_COLORS = ["NONE", "BLUE", "GREEN", "RED", "YELLOW"]; + +console.log("ewew") + +let rules = { + startCards: 5, + firstPlaySpecial: true, +} + +let game = new Game(2, rules); +game.start(); + +console.log(game.currentPlayer + game.cardOnDeck.name +""); + +