diff --git a/Backend/schafkopf-client/src/main/kotlin/CmdSchafkopfMessager.kt b/Backend/schafkopf-client/src/main/kotlin/CmdSchafkopfMessager.kt new file mode 100644 index 0000000..713f68d --- /dev/null +++ b/Backend/schafkopf-client/src/main/kotlin/CmdSchafkopfMessager.kt @@ -0,0 +1,122 @@ +import de.heiserer.CmdPlayer +import de.heiserer.SchafkopfMessager +import de.heiserer.cards.Card +import de.heiserer.cards.CardColor +import de.heiserer.cards.CardSymbol +import de.heiserer.player.Player + +class CmdSchafkopfMessager: SchafkopfMessager { + override fun sendPlayerTurn(player: Player) { + if(player !is CmdPlayer){ + clearConsole() + } + + println("${player.getName()} ist am Zug") + Thread.sleep(1000) + } + + override fun sendPlayerWonTrick(player: Player) { + println("${player.getName()} hat den Stich gewonnen.") + println() + } + + override fun sendPlayerWonGame(player: Player) { + TODO("Not yet implemented") + } + + override fun sendCardPlayed(player: Player, card: Card) { + println("${player.getName()} hat ${card.displayName} gespielt.") + } + + override fun sendTableCards(cards: List) { + println("Tischkarten:") + CmdCard.printCards(cards) + + Thread.sleep(3000) + } + + + + class CmdCard(card: Card){ + private val symbolMap = mapOf( + CardSymbol.SIEBEN to "7", + CardSymbol.ACHT to "8", + CardSymbol.NEUN to "9", + CardSymbol.ZEHN to "10", + CardSymbol.OBER to "O", + CardSymbol.UNTER to "U", + CardSymbol.KOENIG to "K", + CardSymbol.ASS to "A" + ) + + private val colorMap = mapOf( + CardColor.HERZ to "♥", + CardColor.SCHELL to "♦", + CardColor.EICHEL to "♣", + CardColor.BLATT to "♠" + ) + + private val symbol = symbolMap[card.symbol]?: "?" + private val color = colorMap[card.color]?: "?" + private val colorName = card.color.displayName + private val symbolName = card.symbol.displayName + + private val cardWidth = 13 + + private val symbolLine = "│ ${symbol.padEnd(cardWidth-5)}$symbol │" + private val colorLine = "│ ${color.padEnd(cardWidth-5)}$color │" + + private val cardLines = listOf( + "┌───────────┐", + symbolLine, + colorLine, + "│${colorName.padCenter(cardWidth-2)}│", + "│${symbolName.padCenter(cardWidth-2)}│", + colorLine, + symbolLine, + "└───────────┘" + + ) + + fun print(){ + cardLines.forEach { + println(it) + } + } + + fun getCardLines(): List { + return cardLines + } + + private fun String.padCenter(totalWidth: Int, padChar: Char = ' '): String { + if (this.length >= totalWidth) return this + val padding = totalWidth - this.length + val padStart = this.length + padding / 2 + return this.padStart(padStart, padChar).padEnd(totalWidth, padChar) + } + + companion object { + fun printCards(cards: List) { + val lastCardLines = CmdCard(cards.last()).getCardLines() + + val cardLines = cards.map { CmdCard(it).getCardLines() } + + // Loop through the indices of the lines that are present in all cards + for (i in lastCardLines.indices) { + // For other lines, print up to the first 5 characters + var line = cardLines.joinToString(" ") { it[i].take(5) } + line += lastCardLines[i].drop(5) + println(line) + } + } + } + + } + + fun clearConsole() { + for (i in 1..100) { + println() + } + } + +} \ No newline at end of file diff --git a/Backend/schafkopf-client/src/main/kotlin/de/heiserer/CmdPlayer.kt b/Backend/schafkopf-client/src/main/kotlin/de/heiserer/CmdPlayer.kt new file mode 100644 index 0000000..232343c --- /dev/null +++ b/Backend/schafkopf-client/src/main/kotlin/de/heiserer/CmdPlayer.kt @@ -0,0 +1,60 @@ +package de.heiserer + +import de.heiserer.cards.* +import de.heiserer.player.Player +import java.util.* + + +class CmdPlayer(name: String) : Player(name) { + private val scanner = Scanner(System.`in`) + + override fun playCard(tableCards: UnsortedCardList, gameType: GameType): Card { + val cardsCopy = cards.getCopyOfCards() + + println("Available cards:") + CmdSchafkopfMessager.CmdCard.printCards(cardsCopy) + + // Print cards with their respective index + cardsCopy.forEachIndexed { index, card -> + println("(${index + 1}) ${card.name}") // Prints card with index starting from 1 + } + + // Prompt the user to enter a card number + println("Please enter the number of the card you want to play:") + + val userInput = scanner.nextLine() + val cardToPlay = getCardByUserInput(userInput, tableCards, gameType) + + return cards.remove(cardToPlay) + } + + private fun getCardByUserInput( + userInput: String, + tableCards: UnsortedCardList, + gameType: GameType + ): Card { + val cardsCopy = cards.getCopyOfCards() + return try { + // Convert user input to an integer and adjust for zero-based index + val cardIndex = userInput.toInt() - 1 + + // Ensure the index is within bounds + if (cardIndex in cardsCopy.indices) { + cardsCopy[cardIndex] // Return the selected card + if(validateCard(cardsCopy[cardIndex], tableCards, gameType)){ + cardsCopy[cardIndex] + } else { + println("Invalid card. Please try again.") + playCard(tableCards, gameType) // Retry if the card is invalid + } + } else { + println("Invalid card number. Please try again.") + playCard(tableCards, gameType) // Retry if the input was invalid + } + } catch (e: NumberFormatException) { + println("Invalid input. Please enter a number.") + playCard(tableCards, gameType) // Retry on invalid input + } + } + +} \ No newline at end of file diff --git a/Backend/schafkopf-client/src/main/kotlin/de/heiserer/SchafkopfClient.kt b/Backend/schafkopf-client/src/main/kotlin/de/heiserer/SchafkopfClient.kt index b246dae..44ed069 100644 --- a/Backend/schafkopf-client/src/main/kotlin/de/heiserer/SchafkopfClient.kt +++ b/Backend/schafkopf-client/src/main/kotlin/de/heiserer/SchafkopfClient.kt @@ -1,12 +1,14 @@ package de.heiserer +import CmdSchafkopfMessager +import de.heiserer.player.NPCPlayer import de.heiserer.plugins.* import io.ktor.server.application.* import io.ktor.server.engine.* import io.ktor.server.netty.* fun main() { - val test = SchafkopfGameController() + val test = SchafkopfGameController(listOf(NPCPlayer("NPC 1"), NPCPlayer("NPC 2"), CmdPlayer("Dev"), NPCPlayer("NPC 4")), CmdSchafkopfMessager()) test.playRound() diff --git a/Backend/schafkopf-shared/src/main/kotlin/SchafkopfGameController.kt b/Backend/schafkopf-shared/src/main/kotlin/SchafkopfGameController.kt index f893c11..5e8e854 100644 --- a/Backend/schafkopf-shared/src/main/kotlin/SchafkopfGameController.kt +++ b/Backend/schafkopf-shared/src/main/kotlin/SchafkopfGameController.kt @@ -1,7 +1,10 @@ package de.heiserer -class SchafkopfGameController { - private val players = listOf(NPCPlayer("NPC 1"), NPCPlayer("NPC 2"), NPCPlayer("NPC 3"), NPCPlayer("NPC 4")) +import de.heiserer.cards.* +import de.heiserer.player.Player + +class SchafkopfGameController(palyers: List, private val messager: SchafkopfMessager) { + private val players = palyers private lateinit var gameType: GameType private val playedCards: CardList = UnsortedCardList() @@ -16,6 +19,7 @@ class SchafkopfGameController { for(i in 0 until 8){ startingPlayer = playTrick(startingPlayer) + messager.sendPlayerWonTrick(startingPlayer) } } @@ -24,15 +28,17 @@ class SchafkopfGameController { for(i in 0 until 4){ val currentPlayer = calculatePlayerOffset(startingPlayer, i) - currentPlayer.printName() - + messager.sendPlayerTurn(currentPlayer) val card = currentPlayer.playCard(tableCards, gameType) + messager.sendCardPlayed(currentPlayer, card) tableCards.add(card) + messager.sendTableCards(tableCards.getCopyOfCards()) } - tableCards.print() + playedCards.add(tableCards) - return startingPlayer + val trickOffset = CardToolkit.whoTricks(gameType, tableCards) + return calculatePlayerOffset(startingPlayer, trickOffset) } private fun calculatePlayerOffset(startingPlayer: Player, i: Int): Player = players[(players.indexOf(startingPlayer) + i) % 4] @@ -52,62 +58,3 @@ class SchafkopfGameController { } } } - -abstract class Player(private var name: String){ - protected var cards: SortedCardList = SortedCardList(GameType.SAU_SPIEL) - - fun serveCards(cards: UnsortedCardList){ - this.cards = cards.asSortedCardList(GameType.SAU_SPIEL) - } - - fun sortCards(gameType: GameType){ - cards = cards.asSortedCardList(gameType) - println("Spieler $name hat folgende Karten sortiert:") - cards.print() - println() - println("Trumpf:") - cards.getTrumpf().print() - println() - println("Farbe:") - cards.getCardsWithoutTrumpf().print() - println() - } - - abstract fun playCard(tableCards: UnsortedCardList, gameType: GameType): Card - - fun printName(){ - println(name) - } -} - -class NPCPlayer(name: String) : Player(name){ - override fun playCard(tableCards: UnsortedCardList, gameType: GameType): Card { - if(tableCards.size() == 0){ - println("Erster Spieler") - val card = cards.removeLast() - println("Spielt ${card.displayName}") - println() - return card - } - - val firstCard = tableCards.get(0) - if(cards.farbFreiOrTrumpf(firstCard, gameType)){ - println("farbFrei Or Trumpf") - return playTrumpf() - } - } - - private fun playTrumpf(): Card { - val trumpf = cards.getTrumpf() - if (trumpf.size() > 0) { - println("play Trumpf") - val card = trumpf.removeLast() - println("Spielt ${card.displayName}") - println() - return cards.remove(card) - } else { - println("abspatzen") - return cards.removeFirst() - } - } -} \ No newline at end of file diff --git a/Backend/schafkopf-shared/src/main/kotlin/SchafkopfMessager.kt b/Backend/schafkopf-shared/src/main/kotlin/SchafkopfMessager.kt new file mode 100644 index 0000000..5687e1e --- /dev/null +++ b/Backend/schafkopf-shared/src/main/kotlin/SchafkopfMessager.kt @@ -0,0 +1,12 @@ +package de.heiserer + +import de.heiserer.cards.Card +import de.heiserer.player.Player + +interface SchafkopfMessager { + fun sendPlayerTurn(player: Player) + fun sendPlayerWonTrick(player: Player) + fun sendPlayerWonGame(player: Player) + fun sendCardPlayed(player: Player, card: Card) + fun sendTableCards(cards: List) +} \ No newline at end of file diff --git a/Backend/schafkopf-shared/src/main/kotlin/card/CardErrors.kt b/Backend/schafkopf-shared/src/main/kotlin/card/CardErrors.kt new file mode 100644 index 0000000..4630355 --- /dev/null +++ b/Backend/schafkopf-shared/src/main/kotlin/card/CardErrors.kt @@ -0,0 +1,6 @@ +package de.heiserer.cards + +class CardAlreadyAddedException(message: String, val card: Card) : RuntimeException(message) { + + // You can add additional constructors or methods if needed, but for now, this is sufficient to handle the scenario of adding a card that's already in the list. +} \ No newline at end of file diff --git a/Backend/schafkopf-shared/src/main/kotlin/card/CardList.kt b/Backend/schafkopf-shared/src/main/kotlin/card/CardList.kt new file mode 100644 index 0000000..4dea15e --- /dev/null +++ b/Backend/schafkopf-shared/src/main/kotlin/card/CardList.kt @@ -0,0 +1,21 @@ +package de.heiserer.cards + +interface CardList { + fun add(card: Card) + fun add(cards: CardList) + + fun remove(card: Card): Card + fun remove(cards: CardList) + fun removeLast(): Card + fun removeFirst(): Card + + fun get(index: Int): Card + fun getLast(): Card + fun getCopyOfCards(): List + + fun indexOf(card: Card): Int + operator fun contains(card: Card): Boolean + fun size(): Int + fun print() + fun asSortedCardList(type: GameType): SortedCardList +} \ No newline at end of file diff --git a/Backend/schafkopf-shared/src/main/kotlin/card/CardToolkit.kt b/Backend/schafkopf-shared/src/main/kotlin/card/CardToolkit.kt new file mode 100644 index 0000000..c6dffe7 --- /dev/null +++ b/Backend/schafkopf-shared/src/main/kotlin/card/CardToolkit.kt @@ -0,0 +1,36 @@ +package de.heiserer.cards + +class CardToolkit private constructor(private val gameType: GameType) { + private val sortedCardList = UnsortedCardList(true).asSortedCardList(gameType) + + fun isTrumpf(card: Card): Boolean = card in sortedCardList.getTrumpf().getCopyOfCards() + + fun whoTricks(cards: CardList): Int { + if(cards.size() != 4){ + throw IllegalArgumentException("Es müssen 4 Karten auf dem Tisch liegen.") + } + + val sortedCards = cards.asSortedCardList(gameType) + + if(sortedCards.getTrumpf().size() > 0){ + return cards.indexOf(sortedCards.getTrumpf().getLast()) + } else { + val firstColor = cards.get(0).color + val colorCards = sortedCards.getCardsWithoutTrumpf(firstColor) + + return cards.indexOf(colorCards.getLast()) + } + } + + companion object { + fun isTrumpf(gameType: GameType, card: Card): Boolean { + val toolkit = CardToolkit(gameType) + return toolkit.isTrumpf(card) + } + + fun whoTricks(gameType: GameType, cards: CardList): Int { + val toolkit = CardToolkit(gameType) + return toolkit.whoTricks(cards) + } + } +} \ No newline at end of file diff --git a/Backend/schafkopf-shared/src/main/kotlin/Schafkopfkarte.kt b/Backend/schafkopf-shared/src/main/kotlin/card/Schafkopfkarte.kt similarity index 92% rename from Backend/schafkopf-shared/src/main/kotlin/Schafkopfkarte.kt rename to Backend/schafkopf-shared/src/main/kotlin/card/Schafkopfkarte.kt index 416e1f6..2823d58 100644 --- a/Backend/schafkopf-shared/src/main/kotlin/Schafkopfkarte.kt +++ b/Backend/schafkopf-shared/src/main/kotlin/card/Schafkopfkarte.kt @@ -1,9 +1,9 @@ -package de.heiserer +package de.heiserer.cards enum class Card(val color: CardColor, val symbol: CardSymbol) { SCHELL_7(CardColor.SCHELL, CardSymbol.SIEBEN), SCHELL_8(CardColor.SCHELL, CardSymbol.ACHT), - SCHELL_9(CardColor.SCHELL, CardSymbol.NINE), + SCHELL_9(CardColor.SCHELL, CardSymbol.NEUN), SCHELL_U(CardColor.SCHELL, CardSymbol.UNTER), SCHELL_O(CardColor.SCHELL, CardSymbol.OBER), SCHELL_K(CardColor.SCHELL, CardSymbol.KOENIG), @@ -11,7 +11,7 @@ enum class Card(val color: CardColor, val symbol: CardSymbol) { SCHELL_A(CardColor.SCHELL, CardSymbol.ASS), HERZ_7(CardColor.HERZ, CardSymbol.SIEBEN), HERZ_8(CardColor.HERZ, CardSymbol.ACHT), - HERZ_9(CardColor.HERZ, CardSymbol.NINE), + HERZ_9(CardColor.HERZ, CardSymbol.NEUN), HERZ_U(CardColor.HERZ, CardSymbol.UNTER), HERZ_O(CardColor.HERZ, CardSymbol.OBER), HERZ_K(CardColor.HERZ, CardSymbol.KOENIG), @@ -19,7 +19,7 @@ enum class Card(val color: CardColor, val symbol: CardSymbol) { HERZ_A(CardColor.HERZ, CardSymbol.ASS), BLATT_7(CardColor.BLATT, CardSymbol.SIEBEN), BLATT_8(CardColor.BLATT, CardSymbol.ACHT), - BLATT_9(CardColor.BLATT, CardSymbol.NINE), + BLATT_9(CardColor.BLATT, CardSymbol.NEUN), BLATT_U(CardColor.BLATT, CardSymbol.UNTER), BLATT_O(CardColor.BLATT, CardSymbol.OBER), BLATT_K(CardColor.BLATT, CardSymbol.KOENIG), @@ -27,7 +27,7 @@ enum class Card(val color: CardColor, val symbol: CardSymbol) { BLATT_A(CardColor.BLATT, CardSymbol.ASS), EICHEL_7(CardColor.EICHEL, CardSymbol.SIEBEN), EICHEL_8(CardColor.EICHEL, CardSymbol.ACHT), - EICHEL_9(CardColor.EICHEL, CardSymbol.NINE), + EICHEL_9(CardColor.EICHEL, CardSymbol.NEUN), EICHEL_U(CardColor.EICHEL, CardSymbol.UNTER), EICHEL_O(CardColor.EICHEL, CardSymbol.OBER), EICHEL_K(CardColor.EICHEL, CardSymbol.KOENIG), @@ -49,7 +49,7 @@ enum class CardColor(val order: Int, val displayName: String) { enum class CardSymbol(val order: Int, val displayName: String, val value: Int) { SIEBEN(0,"7", 0), ACHT(1,"8", 0), - NINE(2,"9", 0), + NEUN(2,"9", 0), UNTER(3,"Unter", 2), OBER(4,"Ober", 3), KOENIG(5,"König", 4), diff --git a/Backend/schafkopf-shared/src/main/kotlin/card/SortedCardList.kt b/Backend/schafkopf-shared/src/main/kotlin/card/SortedCardList.kt new file mode 100644 index 0000000..d92d0b0 --- /dev/null +++ b/Backend/schafkopf-shared/src/main/kotlin/card/SortedCardList.kt @@ -0,0 +1,41 @@ +package de.heiserer.cards + +class SortedCardList(private val gameType: GameType, withAllCards: Boolean = false) : UnsortedCardList(withAllCards) { + override fun add(card: Card) { + super.add(card) + sort() + } + + fun getCardsWithoutTrumpf(color: CardColor? = null): SortedCardList { + val cardsWithoutTrumpf = SortedCardList(gameType) + + color?.let { cardsWithoutTrumpf.add(get(it)) }?: cardsWithoutTrumpf.add(this) + try { + cardsWithoutTrumpf.remove(getTrumpf()) + } catch (_: IllegalArgumentException) { + } + + return cardsWithoutTrumpf + } + + fun getTrumpf(): SortedCardList { + val trumpf = SortedCardList(gameType) + + gameType.symbol?.let { + trumpf.add(get(it)) + } ?: run { + trumpf.add(get(CardSymbol.OBER)) + trumpf.add(get(CardSymbol.UNTER)) + } + + gameType.color?.let { + try{ trumpf.add(get(it)) } catch (_: CardAlreadyAddedException) {} + } + + return trumpf + } + + private fun sort() { + super.sortInternal(gameType.symbol, gameType.color) + } +} \ No newline at end of file diff --git a/Backend/schafkopf-shared/src/main/kotlin/UnsortedCardList.kt b/Backend/schafkopf-shared/src/main/kotlin/card/UnsortedCardList.kt similarity index 63% rename from Backend/schafkopf-shared/src/main/kotlin/UnsortedCardList.kt rename to Backend/schafkopf-shared/src/main/kotlin/card/UnsortedCardList.kt index 60576f7..4253e50 100644 --- a/Backend/schafkopf-shared/src/main/kotlin/UnsortedCardList.kt +++ b/Backend/schafkopf-shared/src/main/kotlin/card/UnsortedCardList.kt @@ -1,18 +1,4 @@ -package de.heiserer - -interface CardList { - fun add(card: Card) - fun add(cards: CardList) - fun remove(card: Card): Card - fun remove(cards: CardList) - fun removeLast(): Card - fun get(index: Int): Card - fun getCopyOfCards(): List - fun size(): Int - fun print() - fun asSortedCardList(type: GameType): SortedCardList - fun removeFirst(): Card -} +package de.heiserer.cards open class UnsortedCardList(withAllCards: Boolean = false): CardList { private val cards: MutableList = if(withAllCards){ @@ -21,6 +7,10 @@ open class UnsortedCardList(withAllCards: Boolean = false): CardList { mutableListOf() } + override operator fun contains(card: Card): Boolean { + return cards.contains(card) + } + override fun add(card: Card) { if (card !in cards) { cards.add(card) @@ -60,6 +50,10 @@ open class UnsortedCardList(withAllCards: Boolean = false): CardList { return cards.removeLast() } + override fun indexOf(card: Card): Int { + return cards.indexOf(card) + } + override fun get(index: Int): Card { if(index < 0 || index >= cards.size){ throw IllegalArgumentException("Index $index is out of bounds.") @@ -67,6 +61,10 @@ open class UnsortedCardList(withAllCards: Boolean = false): CardList { return cards[index] } + override fun getLast(): Card { + return cards[cards.size - 1] + } + protected fun get(color: CardColor): CardList { val list = UnsortedCardList() cards.forEach { card -> @@ -129,52 +127,3 @@ open class UnsortedCardList(withAllCards: Boolean = false): CardList { }.thenComparing(compareBy({ it.color.order }, { it.symbol.order }))) } } - -class SortedCardList(private val gameType: GameType, withAllCards: Boolean = false) : UnsortedCardList(withAllCards) { - private fun sort() { - super.sortInternal(gameType.symbol, gameType.color) - } - - fun getCardsWithoutTrumpf(color: CardColor? = null): SortedCardList { - val cardsWithoutTrumpf = SortedCardList(gameType) - - color?.let { cardsWithoutTrumpf.add(get(it)) }?: cardsWithoutTrumpf.add(this) - try { - cardsWithoutTrumpf.remove(getTrumpf()) - } catch (_: IllegalArgumentException) { - } - - return cardsWithoutTrumpf - } - - fun getTrumpf():SortedCardList { - val trumpf = SortedCardList(gameType) - - gameType.symbol?.let { - trumpf.add(get(it)) - } ?: run { - trumpf.add(get(CardSymbol.OBER)) - trumpf.add(get(CardSymbol.UNTER)) - } - - gameType.color?.let { try{ - trumpf.add(get(it)) - } catch (_: CardAlreadyAddedException) {} - } - - return trumpf - } - - fun farbFreiOrTrumpf(firstCard: Card, gameType: GameType) = - firstCard.color == gameType.color || getCardsWithoutTrumpf(gameType.color).size() == 0 - - override fun add(card: Card) { - super.add(card) - sort() - } -} - -class CardAlreadyAddedException(message: String, val card: Card) : RuntimeException(message) { - - // You can add additional constructors or methods if needed, but for now, this is sufficient to handle the scenario of adding a card that's already in the list. -} \ No newline at end of file diff --git a/Backend/schafkopf-shared/src/main/kotlin/player/NPCPlayer.kt b/Backend/schafkopf-shared/src/main/kotlin/player/NPCPlayer.kt new file mode 100644 index 0000000..4d70198 --- /dev/null +++ b/Backend/schafkopf-shared/src/main/kotlin/player/NPCPlayer.kt @@ -0,0 +1,38 @@ +package de.heiserer.player + +import de.heiserer.cards.* + +class NPCPlayer(name: String) : Player(name){ + override fun playCard(tableCards: UnsortedCardList, gameType: GameType): Card { + if(tableCards.size() == 0){ + return playTrumpf() + } + + val firstCard = tableCards.get(0) + return if(CardToolkit.isTrumpf(gameType, firstCard)){ + playTrumpf() + } else { + playColor(firstCard.color) + } + } + + private fun playTrumpf(): Card { + val trumpfCards = cards.getTrumpf() + if (trumpfCards.size() > 0) { + val card = trumpfCards.removeLast() + return cards.remove(card) + } else { + return cards.removeFirst() + } + } + + private fun playColor(color: CardColor): Card { + val colorCards = cards.getCardsWithoutTrumpf(color) + if (colorCards.size() > 0) { + val card = colorCards.removeLast() + return cards.remove(card) + } else { + return cards.removeFirst() + } + } +} \ No newline at end of file diff --git a/Backend/schafkopf-shared/src/main/kotlin/player/Player.kt b/Backend/schafkopf-shared/src/main/kotlin/player/Player.kt new file mode 100644 index 0000000..6d860af --- /dev/null +++ b/Backend/schafkopf-shared/src/main/kotlin/player/Player.kt @@ -0,0 +1,35 @@ +package de.heiserer.player + +import de.heiserer.cards.* + +abstract class Player(private var name: String){ + protected var cards: SortedCardList = SortedCardList(GameType.SAU_SPIEL) + + fun serveCards(cards: UnsortedCardList){ + this.cards = cards.asSortedCardList(GameType.SAU_SPIEL) + } + + fun sortCards(gameType: GameType){ + cards = cards.asSortedCardList(gameType) + } + + abstract fun playCard(tableCards: UnsortedCardList, gameType: GameType): Card + + fun getName(): String{ + return name + } + + protected fun validateCard(card: Card, tableCards: UnsortedCardList, gameType: GameType): Boolean{ + if(tableCards.size() == 0){ + return true + } + + val firstCard = tableCards.get(0) + + return if(CardToolkit.isTrumpf(gameType, firstCard)){ + CardToolkit.isTrumpf(gameType, card) || cards.getTrumpf().size() == 0 + } else { + card.color == firstCard.color || cards.getCardsWithoutTrumpf(firstCard.color).size() == 0 + } + } +} \ No newline at end of file diff --git a/Backend/schafkopf-shared/src/test/kotlin/CardListTest.kt b/Backend/schafkopf-shared/src/test/kotlin/CardListTest.kt index a59dbcd..bf65a6f 100644 --- a/Backend/schafkopf-shared/src/test/kotlin/CardListTest.kt +++ b/Backend/schafkopf-shared/src/test/kotlin/CardListTest.kt @@ -1,4 +1,7 @@ -import de.heiserer.* +import de.heiserer.cards.Card +import de.heiserer.cards.CardColor +import de.heiserer.cards.GameType +import de.heiserer.cards.UnsortedCardList import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest diff --git a/Backend/schafkopf-shared/src/test/kotlin/CardToolkitTest.kt b/Backend/schafkopf-shared/src/test/kotlin/CardToolkitTest.kt new file mode 100644 index 0000000..9f72a96 --- /dev/null +++ b/Backend/schafkopf-shared/src/test/kotlin/CardToolkitTest.kt @@ -0,0 +1,25 @@ +import de.heiserer.cards.* +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test + +class CardToolkitTest { + @Test + fun `test isTrumpf`() { + // ASSERT AND ACT + assertEquals(true, CardToolkit.isTrumpf(GameType.SAU_SPIEL, Card.HERZ_O)) + assertEquals(false, CardToolkit.isTrumpf(GameType.SAU_SPIEL, Card.SCHELL_7)) + } + + @Test + fun whoTricks() { + // ARRANGE + val cards = UnsortedCardList() + cards.add(Card.SCHELL_7) + cards.add(Card.SCHELL_8) + cards.add(Card.SCHELL_K) + cards.add(Card.SCHELL_O) + + // ASSERT AND ACT + assertEquals(3, CardToolkit.whoTricks(GameType.SAU_SPIEL, cards)) + } +}