mirror of
https://github.com/Vale54321/schafkopf-bot.git
synced 2025-12-16 19:59:33 +01:00
added cmd playing mode
This commit is contained in:
122
Backend/schafkopf-client/src/main/kotlin/CmdSchafkopfMessager.kt
Normal file
122
Backend/schafkopf-client/src/main/kotlin/CmdSchafkopfMessager.kt
Normal file
@@ -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<Card>) {
|
||||
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<String> {
|
||||
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<Card>) {
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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<Player>, 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<Card>)
|
||||
}
|
||||
@@ -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.
|
||||
}
|
||||
21
Backend/schafkopf-shared/src/main/kotlin/card/CardList.kt
Normal file
21
Backend/schafkopf-shared/src/main/kotlin/card/CardList.kt
Normal file
@@ -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<Card>
|
||||
|
||||
fun indexOf(card: Card): Int
|
||||
operator fun contains(card: Card): Boolean
|
||||
fun size(): Int
|
||||
fun print()
|
||||
fun asSortedCardList(type: GameType): SortedCardList
|
||||
}
|
||||
36
Backend/schafkopf-shared/src/main/kotlin/card/CardToolkit.kt
Normal file
36
Backend/schafkopf-shared/src/main/kotlin/card/CardToolkit.kt
Normal file
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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),
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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<Card>
|
||||
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<Card> = 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.
|
||||
}
|
||||
38
Backend/schafkopf-shared/src/main/kotlin/player/NPCPlayer.kt
Normal file
38
Backend/schafkopf-shared/src/main/kotlin/player/NPCPlayer.kt
Normal file
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
35
Backend/schafkopf-shared/src/main/kotlin/player/Player.kt
Normal file
35
Backend/schafkopf-shared/src/main/kotlin/player/Player.kt
Normal file
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
25
Backend/schafkopf-shared/src/test/kotlin/CardToolkitTest.kt
Normal file
25
Backend/schafkopf-shared/src/test/kotlin/CardToolkitTest.kt
Normal file
@@ -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))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user