Merge pull request 'Logic + TUI | 100% coverage' (#24) from player-logic into development
All checks were successful
Build and Test (KnockOutWhist) TeamCity build finished
All checks were successful
Build and Test (KnockOutWhist) TeamCity build finished
Reviewed-on: #24
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -120,3 +120,7 @@ hs_err_pid*
|
||||
/.idea/scala_compiler.xml
|
||||
/.idea/scala_settings.xml
|
||||
/.idea/vcs.xml
|
||||
/.idea/misc.xml
|
||||
/.idea/sbt.xml
|
||||
/.idea/.name
|
||||
/.idea/codeStyles/**
|
||||
|
||||
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
6
.idea/misc.xml
generated
6
.idea/misc.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_22" default="true" project-jdk-name="22" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
18
.idea/sbt.xml
generated
18
.idea/sbt.xml
generated
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ScalaSbtSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<SbtProjectSettings>
|
||||
<option name="converterVersion" value="2" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/project" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="sbtVersion" value="1.10.2" />
|
||||
</SbtProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
@@ -22,6 +22,8 @@ lazy val root = (project in file("."))
|
||||
libraryDependencies += "org.scalactic" %% "scalactic" % "3.2.18"
|
||||
libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.18" % "test"
|
||||
|
||||
Test / testOptions += Tests.Filter(_.equals("de.knockoutwhist.TestSequence"))
|
||||
|
||||
coverageEnabled := true
|
||||
coverageFailOnMinimum := true
|
||||
coverageMinimumStmtTotal := 85
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
package de.knockoutwhist
|
||||
|
||||
import de.knockoutwhist.cards.CardManager
|
||||
|
||||
import de.knockoutwhist.control.MatchControl
|
||||
import de.knockoutwhist.control.text.TextMatchControl
|
||||
|
||||
|
||||
object KnockOutWhist {
|
||||
|
||||
class KnockOutWhist {
|
||||
val matchControl: MatchControl = TextMatchControl
|
||||
/*
|
||||
Debug mode:
|
||||
|
||||
- Disables the random shuffle of the cards
|
||||
*/
|
||||
private[knockoutwhist] var DEBUG_MODE_VAR: Boolean = true
|
||||
|
||||
def DEBUG_MODE = DEBUG_MODE_VAR
|
||||
|
||||
}
|
||||
def main(args: Array[String]): Unit = {
|
||||
CardManager.shuffleAndReset()
|
||||
val hand1 = CardManager.createHand()
|
||||
val handtoString = hand1.renderAsString()
|
||||
handtoString.foreach(println)
|
||||
|
||||
|
||||
|
||||
if(!matchControl.initial()) throw new IllegalStateException("Game could not be started.")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
package de.knockoutwhist.cards
|
||||
|
||||
import de.knockoutwhist.cards.CardValue.Ten
|
||||
import de.knockoutwhist.cards.Suit
|
||||
|
||||
enum Suit(identifier: String):
|
||||
|
||||
def cardType(): String = identifier
|
||||
|
||||
|
||||
case Spades extends Suit("♠")
|
||||
case Hearts extends Suit("♥")
|
||||
@@ -32,29 +34,34 @@ enum CardValue(identifier: String):
|
||||
end CardValue
|
||||
|
||||
case class Card(cardValue: CardValue, suit: Suit) {
|
||||
|
||||
|
||||
def cardColour(suit: Suit): String = suit match {
|
||||
case Suit.Hearts | Suit.Diamonds => Console.RED
|
||||
case Suit.Clubs | Suit.Spades => Console.BLACK
|
||||
}
|
||||
|
||||
def renderAsString(): Vector[String] = {
|
||||
if(cardValue == Ten) {
|
||||
if (cardValue == Ten) {
|
||||
return Vector(
|
||||
s"┌─────────┐",
|
||||
s"│${cardValue.cardType()} │",
|
||||
s"│${cardColour(suit)}${Console.BOLD}${cardValue.cardType()}${Console.RESET} │",
|
||||
"│ │",
|
||||
s"│ ${suit.cardType()} │",
|
||||
s"│ ${cardColour(suit)}${Console.BOLD}${suit.cardType()}${Console.RESET} │",
|
||||
"│ │",
|
||||
s"│ ${cardValue.cardType()}│",
|
||||
s"│ ${cardColour(suit)}${Console.BOLD}${cardValue.cardType()}${Console.RESET}│",
|
||||
s"└─────────┘"
|
||||
)
|
||||
}
|
||||
Vector(
|
||||
s"┌─────────┐",
|
||||
s"│${cardValue.cardType()} │",
|
||||
s"│${cardColour(suit)}${Console.BOLD}${cardValue.cardType()}${Console.RESET} │",
|
||||
"│ │",
|
||||
s"│ ${suit.cardType()} │",
|
||||
s"│ ${cardColour(suit)}${Console.BOLD}${suit.cardType()}${Console.RESET} │",
|
||||
"│ │",
|
||||
s"│ ${cardValue.cardType()}│",
|
||||
s"│ ${cardColour(suit)}${Console.BOLD}${cardValue.cardType()}${Console.RESET}│",
|
||||
s"└─────────┘"
|
||||
)
|
||||
}
|
||||
|
||||
override def toString: String = s"$cardValue of $suit" //Combined String
|
||||
override def toString: String = s"$cardValue of $suit"
|
||||
//Combined String
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package de.knockoutwhist.cards
|
||||
|
||||
import de.knockoutwhist.KnockOutWhist
|
||||
|
||||
import scala.collection.mutable.ListBuffer
|
||||
import scala.util.Random
|
||||
|
||||
@@ -21,11 +23,20 @@ object CardManager {
|
||||
cardContainer = Random.shuffle(cardContainer)
|
||||
currentIdx = 0
|
||||
}
|
||||
|
||||
def resetOrder(): Unit = {
|
||||
cardContainer = cardContainer.sortBy(c => (c.suit.ordinal, c.cardValue.ordinal))
|
||||
currentIdx = 0
|
||||
}
|
||||
|
||||
def nextCard(): Card = {
|
||||
val card = cardContainer(currentIdx)
|
||||
currentIdx += 1
|
||||
card
|
||||
if (currentIdx + 1 > 51) {
|
||||
throw new IndexOutOfBoundsException("Trying to access card 53(out of bounds)")
|
||||
} else {
|
||||
currentIdx += 1
|
||||
card
|
||||
}
|
||||
}
|
||||
|
||||
def createHand(amount: Int = 7): Hand = {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package de.knockoutwhist.cards
|
||||
|
||||
import scala.collection.mutable.ListBuffer
|
||||
|
||||
case class Hand(cards: List[Card]) {
|
||||
|
||||
def removeCard(card: Card): Hand = {
|
||||
Hand(cards.filter(_ != card))
|
||||
//Hand(cards.filterNot(_ == card)) isch wurscht welches wir nehmen
|
||||
}
|
||||
|
||||
def hasSuit(suit: Suit): Boolean = {
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package de.knockoutwhist.cards
|
||||
|
||||
case class Player(name: String) {
|
||||
private var hand: Option[Hand] = None
|
||||
|
||||
def provideHand(hand: Hand): Boolean = {
|
||||
this.hand = Some(hand)
|
||||
true
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
24
src/main/scala/de/knockoutwhist/control/MatchControl.scala
Normal file
24
src/main/scala/de/knockoutwhist/control/MatchControl.scala
Normal file
@@ -0,0 +1,24 @@
|
||||
package de.knockoutwhist.control
|
||||
|
||||
import de.knockoutwhist.rounds.{Match, Round, Trick}
|
||||
|
||||
trait MatchControl {
|
||||
|
||||
def initial(): Boolean
|
||||
def start(): Unit
|
||||
def playerControl: PlayerControl
|
||||
|
||||
/**
|
||||
* Start the next round
|
||||
* @return the next round or null if the match is over
|
||||
*/
|
||||
def nextRound(matchImpl: Match): Round
|
||||
|
||||
/**
|
||||
* Start the next trick
|
||||
* @return the last trick or null if the round is over
|
||||
*/
|
||||
def nextTrick(roundImpl: Round): Trick
|
||||
|
||||
|
||||
}
|
||||
16
src/main/scala/de/knockoutwhist/control/PlayerControl.scala
Normal file
16
src/main/scala/de/knockoutwhist/control/PlayerControl.scala
Normal file
@@ -0,0 +1,16 @@
|
||||
package de.knockoutwhist.control
|
||||
|
||||
import de.knockoutwhist.cards.{Card, Suit}
|
||||
import de.knockoutwhist.player.Player
|
||||
import de.knockoutwhist.rounds.Round
|
||||
|
||||
trait PlayerControl {
|
||||
|
||||
def playCard(player: Player): Card
|
||||
def dogplayCard(player: Player, round: Round): Option[Card]
|
||||
def determineWinnerTie(players: List[Player]): Player
|
||||
def pickNextTrumpsuit(player: Player): Suit
|
||||
def showCards(player: Player): Boolean
|
||||
def showWon(player: Player, round: Round): String
|
||||
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
package de.knockoutwhist.control.text
|
||||
|
||||
import de.knockoutwhist.KnockOutWhist
|
||||
import de.knockoutwhist.cards.Card
|
||||
import de.knockoutwhist.control.{MatchControl, PlayerControl}
|
||||
import de.knockoutwhist.player.Player
|
||||
import de.knockoutwhist.rounds.{Match, Round, Trick}
|
||||
import de.knockoutwhist.utils.CustomPlayerQueue
|
||||
|
||||
import scala.compiletime.uninitialized
|
||||
import scala.io.StdIn
|
||||
import scala.util.Random
|
||||
|
||||
object TextMatchControl extends MatchControl {
|
||||
|
||||
private[control] var playerQueue: CustomPlayerQueue[Player] = uninitialized
|
||||
private var init = false
|
||||
|
||||
override def initial(): Boolean = {
|
||||
if(init) {
|
||||
println("The game is already running.")
|
||||
return false
|
||||
}
|
||||
init = true
|
||||
println("Welcome to Knockout Whist!")
|
||||
start()
|
||||
true
|
||||
}
|
||||
|
||||
override def start(): Unit = {
|
||||
while(true) { //Main Gameplay Loop
|
||||
val input = printMenu()
|
||||
input match {
|
||||
case "1" =>
|
||||
startMatch()
|
||||
case "2" =>
|
||||
println("Exiting the game.")
|
||||
return
|
||||
case _ =>
|
||||
println("Invalid input. Please try again.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private[control] def startMatch(): Player = {
|
||||
clearConsole()
|
||||
println("Starting a new match.")
|
||||
val players = enterPlayers()
|
||||
playerQueue = CustomPlayerQueue[Player](players, Random.nextInt(players.length))
|
||||
clearConsole()
|
||||
controlMatch()
|
||||
}
|
||||
|
||||
private[control] def enterPlayers(): Array[Player] = {
|
||||
println("Please enter the names of the players, separated by a comma.")
|
||||
val names = StdIn.readLine().split(",")
|
||||
if(names.length < 2) {
|
||||
println("Please enter at least two names.")
|
||||
return enterPlayers()
|
||||
}
|
||||
if(names.distinct.length != names.length) {
|
||||
println("Please enter unique names.")
|
||||
return enterPlayers()
|
||||
}
|
||||
if(names.count(_.trim.isBlank) > 0 || names.count(_.trim.length <= 2) > 0 || names.count(_.trim.length > 10) > 0) {
|
||||
println("Please enter valid names. Those can not be empty, shorter than 2 or longer then 10 characters.")
|
||||
return enterPlayers()
|
||||
}
|
||||
names.map(s => Player(s))
|
||||
}
|
||||
|
||||
private[control] def controlMatch(): Player = {
|
||||
val matchImpl = Match(playerQueue.toList)
|
||||
while (!matchImpl.isOver) {
|
||||
val roundImpl = controlRound(matchImpl)
|
||||
}
|
||||
clearConsole()
|
||||
println(s"The match is over. The winner is ${matchImpl.finalizeMatch().name}.")
|
||||
matchImpl.finalizeMatch()
|
||||
}
|
||||
|
||||
private[control] def controlRound(matchImpl: Match): Round = {
|
||||
val roundImpl = nextRound(matchImpl)
|
||||
clearConsole(10)
|
||||
println(s"Starting a new round. The trump suit is ${roundImpl.trumpSuit}.")
|
||||
clearConsole(2)
|
||||
while (!roundImpl.isOver) {
|
||||
controlTrick(roundImpl)
|
||||
}
|
||||
val (roundWinner, finalRound) = roundImpl.finalizeRound()
|
||||
println(s"${roundWinner.name} won the round.")
|
||||
if(!KnockOutWhist.DEBUG_MODE) Thread.sleep(5000L)
|
||||
if(finalRound.players_out.nonEmpty) {
|
||||
println("The following players are out of the game:")
|
||||
finalRound.players_out.foreach(p => {
|
||||
println(p.name)
|
||||
playerQueue.remove(p)
|
||||
})
|
||||
}
|
||||
playerQueue.resetAndSetStart(roundWinner)
|
||||
finalRound
|
||||
}
|
||||
|
||||
private[control] def controlTrick(round: Round): Trick = {
|
||||
val trick = nextTrick(round)
|
||||
for (player <- playerQueue) {
|
||||
clearConsole()
|
||||
println(printTrick(round))
|
||||
if (!player.doglife) {
|
||||
val rightCard = controlSuitplayed(trick, player)
|
||||
player.removeCard(rightCard)
|
||||
trick.playCard(rightCard, player)
|
||||
} else if (player.currentHand().exists(_.cards.nonEmpty)) {
|
||||
val card = playerControl.dogplayCard(player, round)
|
||||
if (card.isEmpty) {
|
||||
println(f"Player $player decided to not play his card")
|
||||
} else {
|
||||
player.removeCard(card.get)
|
||||
trick.playCard(card.get, player)
|
||||
}
|
||||
}
|
||||
}
|
||||
val (winner, finalTrick) = trick.wonTrick()
|
||||
clearConsole()
|
||||
println(printTrick(round))
|
||||
println(s"${winner.name} won the trick.")
|
||||
clearConsole(2)
|
||||
playerQueue.resetAndSetStart(winner)
|
||||
if(!KnockOutWhist.DEBUG_MODE) Thread.sleep(3000L)
|
||||
finalTrick
|
||||
}
|
||||
private[control] def controlSuitplayed(trick: Trick, player: Player): Card = {
|
||||
var card = playerControl.playCard(player)
|
||||
if (trick.get_first_card().isDefined) {
|
||||
while (!(trick.get_first_card().get.suit == card.suit)) {
|
||||
var hasSuit = false
|
||||
for (cardInHand <- player.currentHand().get.cards) {
|
||||
if (cardInHand.suit == trick.get_first_card().get.suit) {
|
||||
hasSuit = true
|
||||
}
|
||||
}
|
||||
if(!hasSuit) {
|
||||
return card
|
||||
}else {
|
||||
println(f"You have to play a card of suit: ${trick.get_first_card().get.suit}\n")
|
||||
card = playerControl.playCard(player)
|
||||
}
|
||||
}
|
||||
}
|
||||
card
|
||||
}
|
||||
|
||||
private[control] def printMenu(): String = {
|
||||
println("Please select an option:")
|
||||
println("1. Start a new match")
|
||||
println("2. Exit")
|
||||
StdIn.readLine()
|
||||
}
|
||||
|
||||
private[control] def printTrick(round: Round): String = {
|
||||
val sb = new StringBuilder()
|
||||
sb.append("Current Trick:\n")
|
||||
sb.append("Trump-Suit: " + round.trumpSuit + "\n")
|
||||
if(round.get_current_trick().get_first_card().isDefined) {
|
||||
sb.append(s"Suit to play: ${round.get_current_trick().get_first_card().get.suit}\n")
|
||||
}
|
||||
for((card, player) <- round.get_current_trick().cards) {
|
||||
sb.append(s"${player.name} played ${card.toString}\n")
|
||||
}
|
||||
sb.toString()
|
||||
}
|
||||
|
||||
private def clearConsole(lines: Int = 32): Int = {
|
||||
var l = 0
|
||||
for(_ <- 0 until lines) {
|
||||
println()
|
||||
l += 1
|
||||
}
|
||||
l
|
||||
}
|
||||
|
||||
override def playerControl: PlayerControl = {
|
||||
TextPlayerControl
|
||||
}
|
||||
|
||||
override def nextRound(matchImpl: Match): Round = {
|
||||
if(matchImpl.isOver) {
|
||||
println(s"The match is over. The winner is ${matchImpl.finalizeMatch().name}.")
|
||||
return null
|
||||
}
|
||||
matchImpl.create_round()
|
||||
}
|
||||
|
||||
override def nextTrick(roundImpl: Round): Trick = {
|
||||
if(roundImpl.isOver) {
|
||||
println("The round is over.")
|
||||
return null
|
||||
}
|
||||
roundImpl.create_trick()
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
package de.knockoutwhist.control.text
|
||||
|
||||
import de.knockoutwhist.KnockOutWhist
|
||||
import de.knockoutwhist.cards.{Card, CardManager, Suit}
|
||||
import de.knockoutwhist.control.PlayerControl
|
||||
import de.knockoutwhist.player.Player
|
||||
import de.knockoutwhist.rounds.Round
|
||||
|
||||
import scala.annotation.tailrec
|
||||
import scala.collection.mutable
|
||||
import scala.collection.mutable.ListBuffer
|
||||
import scala.io.StdIn.readLine
|
||||
import scala.util.control.Breaks.*
|
||||
|
||||
object TextPlayerControl extends PlayerControl {
|
||||
|
||||
override def playCard(player: Player): Card = {
|
||||
println("It's your turn, " + player.name + ".")
|
||||
if(!KnockOutWhist.DEBUG_MODE) Thread.sleep(3000L)
|
||||
println("Which card do you want to play?")
|
||||
showCards(player)
|
||||
try {
|
||||
val card = readLine().toInt-1
|
||||
val handCard = player.currentHand()
|
||||
if (handCard.isEmpty) {
|
||||
println("You don't have any cards.")
|
||||
throw new IllegalStateException("Trying to play a card without any cards.")
|
||||
} else if(card < 0 || card >= handCard.get.cards.length) {
|
||||
println("Please enter a valid number.")
|
||||
playCard(player)
|
||||
} else {
|
||||
handCard.get.cards(card)
|
||||
}
|
||||
} catch {
|
||||
case e: NumberFormatException =>
|
||||
println("Please enter a valid number.")
|
||||
playCard(player)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override def dogplayCard(player: Player, round: Round): Option[Card] = {
|
||||
println("It's your turn, " + player.name + ".")
|
||||
if (!KnockOutWhist.DEBUG_MODE) Thread.sleep(3000L)
|
||||
println("You are using your dog life. Do you want to play your final card now?")
|
||||
if(round.dogNeedsToPlay) {
|
||||
println("You have to play your final card this round!")
|
||||
println("Please enter y to play your final card.")
|
||||
}else {
|
||||
println("Please enter y/n to play your final card.")
|
||||
}
|
||||
|
||||
showCards(player)
|
||||
val card = readLine()
|
||||
val handCard = player.currentHand()
|
||||
if (handCard.isEmpty) {
|
||||
println("You don't have any cards.")
|
||||
throw new IllegalStateException("Trying to play a card without any cards.")
|
||||
} else if(card.equalsIgnoreCase("y")) {
|
||||
Some(handCard.get.cards.head)
|
||||
} else if (card.equalsIgnoreCase("n") && !round.dogNeedsToPlay) {
|
||||
None
|
||||
} else {
|
||||
println("Please enter y or n to play your final card.")
|
||||
dogplayCard(player, round)
|
||||
}
|
||||
}
|
||||
|
||||
override def determineWinnerTie(players: List[Player]): Player = {
|
||||
determineWinnerTieText(players, true)
|
||||
}
|
||||
|
||||
@tailrec
|
||||
private def determineWinnerTieText(players: List[Player], tieMessage: Boolean): Player = {
|
||||
if (!KnockOutWhist.DEBUG_MODE) CardManager.shuffleAndReset()
|
||||
if (tieMessage) println("It's a tie! Let's cut to determine the winner.")
|
||||
var currentStep = 0
|
||||
var remaining = CardManager.cardContainer.size - (players.length - 1)
|
||||
val cut: mutable.HashMap[Player, Card] = mutable.HashMap()
|
||||
for (player <- players) {
|
||||
var selCard: Card = null
|
||||
while (selCard == null) {
|
||||
println(s"${player.name} enter a number between 1 and $remaining.")
|
||||
try {
|
||||
val selected = readLine().toInt - 1
|
||||
if (selected >= 0 && selected < remaining) {
|
||||
selCard = CardManager.cardContainer(currentStep + selected)
|
||||
cut.put(player, selCard)
|
||||
currentStep += selected + 1
|
||||
remaining -= selected
|
||||
} else {
|
||||
println("Please enter a valid number.")
|
||||
}
|
||||
} catch {
|
||||
case e: NumberFormatException =>
|
||||
println("Please enter a valid number.")
|
||||
}
|
||||
}
|
||||
}
|
||||
println("The cards are:")
|
||||
val a: Array[String] = Array("", "", "", "", "", "", "", "")
|
||||
for ((player, card) <- cut) {
|
||||
val playerNameLength = player.name.length
|
||||
a(0) += " " + player.name + ":" + (" " * (playerNameLength - 1))
|
||||
val rendered = card.renderAsString()
|
||||
a(1) += " " + rendered(0)
|
||||
a(2) += " " + rendered(1)
|
||||
a(3) += " " + rendered(2)
|
||||
a(4) += " " + rendered(3)
|
||||
a(5) += " " + rendered(4)
|
||||
a(6) += " " + rendered(5)
|
||||
a(7) += " " + rendered(6)
|
||||
}
|
||||
a.foreach(println)
|
||||
|
||||
var currentHighest: Card = null
|
||||
val winner: ListBuffer[Player] = ListBuffer()
|
||||
for ((player, card) <- cut) {
|
||||
breakable {
|
||||
if (currentHighest == null) {
|
||||
currentHighest = card
|
||||
winner += player
|
||||
break
|
||||
}
|
||||
val compared = card.cardValue.ordinal.compareTo(currentHighest.cardValue.ordinal)
|
||||
if (compared > 0) {
|
||||
currentHighest = card
|
||||
winner.clear()
|
||||
winner += player
|
||||
} else if (compared == 0) {
|
||||
winner += player
|
||||
}
|
||||
}
|
||||
}
|
||||
if (winner.size == 1) {
|
||||
println(s"${winner.head.name} wins the cut!")
|
||||
return winner.head
|
||||
}
|
||||
println("It's a tie again! Let's cut again.")
|
||||
determineWinnerTieText(winner.toList, false)
|
||||
}
|
||||
|
||||
override def pickNextTrumpsuit(player: Player): Suit = {
|
||||
println("Which suit do you want to pick as the next trump suit?")
|
||||
println("1: Hearts")
|
||||
println("2: Diamonds")
|
||||
println("3: Clubs")
|
||||
println("4: Spades")
|
||||
println()
|
||||
|
||||
player.currentHand().get.renderAsString().foreach(println)
|
||||
|
||||
try {
|
||||
val suit = readLine().toInt
|
||||
suit match {
|
||||
case 1 => Suit.Hearts
|
||||
case 2 => Suit.Diamonds
|
||||
case 3 => Suit.Clubs
|
||||
case 4 => Suit.Spades
|
||||
case _ =>
|
||||
println("Please enter a valid number.")
|
||||
pickNextTrumpsuit(player)
|
||||
}
|
||||
} catch {
|
||||
case e: NumberFormatException =>
|
||||
println("Please enter a valid number.")
|
||||
pickNextTrumpsuit(player)
|
||||
}
|
||||
}
|
||||
|
||||
override def showCards(player: Player): Boolean = {
|
||||
val hand = player.currentHand()
|
||||
if (hand.isEmpty) {
|
||||
println("You don't have any cards.")
|
||||
return false
|
||||
}
|
||||
println("Your cards:")
|
||||
var rendered = hand.get.renderAsString()
|
||||
rendered ::= {
|
||||
var s = ""
|
||||
for (i <- hand.get.cards.indices) {
|
||||
s += s" ${i+1} " + " "
|
||||
}
|
||||
s
|
||||
}
|
||||
rendered.foreach(println)
|
||||
true
|
||||
}
|
||||
|
||||
override def showWon(player: Player, round: Round): String = {
|
||||
s"$player won this round."
|
||||
}
|
||||
|
||||
}
|
||||
32
src/main/scala/de/knockoutwhist/player/Player.scala
Normal file
32
src/main/scala/de/knockoutwhist/player/Player.scala
Normal file
@@ -0,0 +1,32 @@
|
||||
package de.knockoutwhist.player
|
||||
|
||||
import de.knockoutwhist.KnockOutWhist
|
||||
import de.knockoutwhist.cards.{Card, Hand, Suit}
|
||||
|
||||
import scala.collection.mutable.ListBuffer
|
||||
|
||||
case class Player(name: String) {
|
||||
private var hand: Option[Hand] = None
|
||||
|
||||
def currentHand(): Option[Hand] = hand
|
||||
var doglife: Boolean = false
|
||||
def provideHand(hand: Hand): Boolean = {
|
||||
this.hand = Some(hand)
|
||||
true
|
||||
}
|
||||
def pickTrumpsuit(): Suit = {
|
||||
KnockOutWhist.matchControl.playerControl.pickNextTrumpsuit(this)
|
||||
}
|
||||
def removeCard(card: Card): Int = {
|
||||
hand = Some(hand.get.removeCard(card))
|
||||
hand.get.cards.size
|
||||
}
|
||||
|
||||
override def toString: String = {
|
||||
name
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,3 +1,65 @@
|
||||
package de.knockoutwhist.rounds
|
||||
|
||||
case class Match()
|
||||
import de.knockoutwhist.KnockOutWhist
|
||||
import de.knockoutwhist.cards.CardManager
|
||||
import de.knockoutwhist.player.Player
|
||||
|
||||
import scala.collection.mutable.ListBuffer
|
||||
import de.knockoutwhist.utils.Implicits._
|
||||
|
||||
case class Match(totalplayers: List[Player], private[rounds] var number_of_cards: Int = 7) {
|
||||
|
||||
private[rounds] val roundlist: ListBuffer[Round] = ListBuffer[Round]()
|
||||
private var current_round: Option[Round] = None
|
||||
private[rounds] var dogLife = false
|
||||
|
||||
def create_round(): Round = {
|
||||
val remainingPlayer = roundlist.isEmpty ? totalplayers |: roundlist.last.remainingPlayers()
|
||||
provideCards(remainingPlayer)
|
||||
if (roundlist.isEmpty) {
|
||||
val random_trumpsuit = CardManager.nextCard().suit
|
||||
current_round = Some(new Round(random_trumpsuit, this, remainingPlayer, true))
|
||||
} else {
|
||||
val winner = roundlist.last.winner
|
||||
val trumpsuit = winner.pickTrumpsuit()
|
||||
|
||||
current_round = Some(new Round(trumpsuit, this, remainingPlayer, false))
|
||||
}
|
||||
number_of_cards -= 1
|
||||
current_round.get
|
||||
}
|
||||
|
||||
def isOver: Boolean = {
|
||||
if(roundlist.isEmpty) {
|
||||
false
|
||||
} else {
|
||||
roundlist.last.remainingPlayers().size == 1
|
||||
}
|
||||
}
|
||||
|
||||
private def provideCards(players: List[Player]): Int = {
|
||||
if(!KnockOutWhist.DEBUG_MODE) CardManager.shuffleAndReset()
|
||||
var hands = 0
|
||||
for (player <- players) {
|
||||
if(!player.doglife) {
|
||||
player.provideHand(CardManager.createHand(number_of_cards))
|
||||
} else {
|
||||
player.provideHand(CardManager.createHand(1))
|
||||
}
|
||||
hands += 1
|
||||
}
|
||||
hands
|
||||
}
|
||||
|
||||
def finalizeMatch(): Player = {
|
||||
if(!isOver) {
|
||||
throw new IllegalStateException("Match is not over yet.")
|
||||
}
|
||||
roundlist.last.remainingPlayers().head
|
||||
}
|
||||
|
||||
override def toString: String = {
|
||||
s"${totalplayers}, ${number_of_cards}"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,81 @@
|
||||
package de.knockoutwhist.rounds
|
||||
import de.knockoutwhist.rounds.Trick
|
||||
import de.knockoutwhist.cards.Suit
|
||||
import de.knockoutwhist.cards.Player
|
||||
import de.knockoutwhist.KnockOutWhist
|
||||
import de.knockoutwhist.cards.{CardManager, Suit}
|
||||
import de.knockoutwhist.player.Player
|
||||
import de.knockoutwhist.utils.Implicits._
|
||||
|
||||
import scala.collection.mutable
|
||||
import scala.collection.mutable.ListBuffer
|
||||
|
||||
case class Round(trumpSuit: Suit, cardAmount: Int, tricklist: ListBuffer[Trick], players_in: List[Player]) {
|
||||
// def create_trick(trumpSuit: Suit, players_in: List[Player]): Unit =
|
||||
// {
|
||||
//
|
||||
// }
|
||||
case class Round private[rounds](trumpSuit: Suit, matchImpl: Match, private[rounds] val tricklist: ListBuffer[Trick], players_in: List[Player], players_out: List[Player] = null, winner: Player = null, firstRound: Boolean) {
|
||||
def this(trumpSuit: Suit, matchImpl: Match, players_in: List[Player], firstRound: Boolean) = {
|
||||
this(trumpSuit, matchImpl, ListBuffer[Trick](), players_in, firstRound = firstRound)
|
||||
}
|
||||
|
||||
private var current_trick: Option[Trick] = None
|
||||
|
||||
def get_current_trick(): Trick = {
|
||||
current_trick.getOrElse(create_trick())
|
||||
}
|
||||
|
||||
def get_tricks(): List[Trick] = tricklist.toList
|
||||
|
||||
def create_trick(): Trick = {
|
||||
val trick = new Trick(this)
|
||||
current_trick = Some(trick)
|
||||
trick
|
||||
}
|
||||
|
||||
def isOver: Boolean = {
|
||||
players_in.map(_.currentHand()).count(_.get.cards.isEmpty) == players_in.size
|
||||
}
|
||||
|
||||
def dogNeedsToPlay: Boolean = {
|
||||
players_in.filter(!_.doglife).map(_.currentHand()).exists(_.get.cards.isEmpty)
|
||||
}
|
||||
|
||||
def finalizeRound(force: Boolean = false): (Player, Round) = {
|
||||
if(!force && tricklist.isEmpty)
|
||||
throw new IllegalStateException("No tricks played in this round")
|
||||
if(!force && !isOver)
|
||||
throw new IllegalStateException("Not all tricks were played in this round")
|
||||
val tricksMapped = tricklist
|
||||
.map(t => t.winner)
|
||||
.groupBy(identity).map((p, l) => (p, l.size)) //l.size = Anzahl gewonnener Tricks
|
||||
val winners = tricksMapped
|
||||
.filter((p, i) => i == tricksMapped.values.max)
|
||||
.keys
|
||||
|
||||
var playersOut = firstRound
|
||||
? List()
|
||||
|: players_in.filter(!tricksMapped.contains(_))
|
||||
|
||||
if(playersOut.nonEmpty && !matchImpl.dogLife) {
|
||||
matchImpl.dogLife = true
|
||||
playersOut.foreach(p => p.doglife = true)
|
||||
playersOut = List()
|
||||
}
|
||||
|
||||
tricksMapped.keys.foreach(p => {p.doglife = false})
|
||||
|
||||
val winner = (winners.size == 1)
|
||||
? winners.head
|
||||
|: KnockOutWhist.matchControl.playerControl.determineWinnerTie(winners.toList)
|
||||
|
||||
val finalRound = Round(trumpSuit, matchImpl, tricklist, players_in, playersOut, winner, firstRound)
|
||||
matchImpl.roundlist += finalRound
|
||||
(winner, finalRound)
|
||||
}
|
||||
|
||||
def remainingPlayers(): List[Player] = {
|
||||
if (players_out == null) {
|
||||
return players_in
|
||||
}
|
||||
players_in.filter(!players_out.contains(_))
|
||||
}
|
||||
override def toString: String = {
|
||||
s"$trumpSuit, $tricklist, $players_in, $players_out, $winner, $firstRound"
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
package de.knockoutwhist.rounds
|
||||
|
||||
import de.knockoutwhist.cards.{Card, Player}
|
||||
import de.knockoutwhist.cards.Card
|
||||
import de.knockoutwhist.cards.Suit
|
||||
import de.knockoutwhist.player.Player
|
||||
|
||||
import scala.collection.mutable
|
||||
|
||||
|
||||
case class Trick private(round: Round, cards: mutable.HashMap[Card, Player], winner: Player = null, finished: Boolean = false) {
|
||||
|
||||
def this(round: Round) = this(round, mutable.HashMap[Card, Player]())
|
||||
var first_card: Option[Suit] = None // statt als Parameter im Konstruktor
|
||||
def this(round: Round) = {
|
||||
this(round, mutable.HashMap[Card, Player]())
|
||||
}
|
||||
private var first_card: Option[Card] = None // statt als Parameter im Konstruktor
|
||||
|
||||
def get_first_card(): Option[Card] = first_card
|
||||
|
||||
/**
|
||||
* Play a card in the trick
|
||||
* @param card The card to play
|
||||
@@ -19,11 +25,11 @@ case class Trick private(round: Round, cards: mutable.HashMap[Card, Player], win
|
||||
if (finished) {
|
||||
throw new IllegalStateException("This trick is already finished")
|
||||
} else {
|
||||
if (cards.isEmpty) {
|
||||
first_card = Some(card.suit)
|
||||
if (first_card.isEmpty) {
|
||||
first_card = Some(card)
|
||||
cards += (card -> player)
|
||||
true
|
||||
} else if (card.suit == first_card.getOrElse(card.suit)) { // Wert aus Option extrahieren
|
||||
} else if (card.suit == first_card.getOrElse(card).suit) { // Wert aus Option extrahieren
|
||||
cards += (card -> player)
|
||||
true
|
||||
} else if (card.suit == round.trumpSuit) {
|
||||
@@ -41,12 +47,18 @@ case class Trick private(round: Round, cards: mutable.HashMap[Card, Player], win
|
||||
if (cards.keys.exists(_.suit == round.trumpSuit)) {
|
||||
cards.keys.filter(_.suit == round.trumpSuit).maxBy(_.cardValue.ordinal) //stream
|
||||
} else {
|
||||
cards.keys.filter(_.suit == first_card.getOrElse(Suit.Spades)).maxBy(_.cardValue.ordinal) //stream
|
||||
cards.keys.filter(_.suit == first_card.get.suit).maxBy(_.cardValue.ordinal) //stream
|
||||
}
|
||||
}
|
||||
val winningPlayer = cards(winningCard)
|
||||
(winningPlayer, Trick(round, cards, winningPlayer, true))
|
||||
}
|
||||
val finalTrick = Trick(round, cards, winningPlayer, true)
|
||||
round.tricklist += finalTrick
|
||||
(winningPlayer, finalTrick)
|
||||
}
|
||||
|
||||
override def toString: String = {
|
||||
s"$cards, $winner, $finished"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package de.knockoutwhist.utils
|
||||
|
||||
class CustomPlayerQueue[A] (protected var players: Array[A], val start: Int = 0) extends Iterable[A] {
|
||||
|
||||
private var current = start
|
||||
|
||||
def nextPlayer(): A = {
|
||||
val player = players(current)
|
||||
current = (current + 1) % players.length
|
||||
player
|
||||
}
|
||||
|
||||
def remove(player: A): Int = {
|
||||
players = players.filter(_ != player)
|
||||
players.size
|
||||
}
|
||||
|
||||
def resetAndSetStart(player: A): Boolean = {
|
||||
if(players.contains(player)) {
|
||||
current = players.indexOf(player)
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
override def toList: List[A] = players.toList
|
||||
|
||||
override def isEmpty: Boolean = players.isEmpty
|
||||
override def size: Int = players.length
|
||||
|
||||
|
||||
|
||||
def iterator: Iterator[A] = new Iterator[A] {
|
||||
private var index = 0
|
||||
def hasNext: Boolean = index < players.length
|
||||
def next(): A = {
|
||||
index += 1
|
||||
CustomPlayerQueue.this.nextPlayer()
|
||||
}
|
||||
}
|
||||
}
|
||||
23
src/main/scala/de/knockoutwhist/utils/Implicits.scala
Normal file
23
src/main/scala/de/knockoutwhist/utils/Implicits.scala
Normal file
@@ -0,0 +1,23 @@
|
||||
package de.knockoutwhist.utils
|
||||
|
||||
import scala.annotation.targetName
|
||||
|
||||
object Implicits {
|
||||
|
||||
implicit class Ternable(condition: Boolean) {
|
||||
@targetName("tern")
|
||||
def ?[T](ifTrue: => T): Option[T] = {
|
||||
if (condition) Some(ifTrue) else None
|
||||
}
|
||||
}
|
||||
|
||||
implicit class Colonable[T](ifFalse: => T) {
|
||||
@targetName("colon")
|
||||
def |:(intermediate: Option[T]): T =
|
||||
intermediate match {
|
||||
case Some(ifTrue) => ifTrue
|
||||
case None => ifFalse
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
22
src/test/scala/de/knockoutwhist/MainTests.scala
Normal file
22
src/test/scala/de/knockoutwhist/MainTests.scala
Normal file
@@ -0,0 +1,22 @@
|
||||
package de.knockoutwhist
|
||||
|
||||
import de.knockoutwhist.testutils.TestUtil
|
||||
import org.scalatest.funsuite.AnyFunSuite
|
||||
|
||||
class MainTests extends AnyFunSuite {
|
||||
|
||||
test("Main should be able to go to the main menu") {
|
||||
TestUtil.simulateInput("2\n") {
|
||||
KnockOutWhist.main(Array())
|
||||
}
|
||||
}
|
||||
|
||||
test("Main should be able to be executed twice") {
|
||||
TestUtil.simulateInput("2\n") {
|
||||
assertThrows[IllegalStateException] {
|
||||
KnockOutWhist.main(Array())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
24
src/test/scala/de/knockoutwhist/TestSequence.scala
Normal file
24
src/test/scala/de/knockoutwhist/TestSequence.scala
Normal file
@@ -0,0 +1,24 @@
|
||||
package de.knockoutwhist
|
||||
|
||||
import de.knockoutwhist.cards.{CardTests, DeckTests, HandTests}
|
||||
import de.knockoutwhist.control.text.{TextMatchControllerTests, TextPlayerControllerTests}
|
||||
import de.knockoutwhist.player.PlayerTests
|
||||
import de.knockoutwhist.rounds.{GameplayTests, MatchTests, TrickTests}
|
||||
import de.knockoutwhist.utils.{ImplicitTests, QueueTests}
|
||||
import org.scalatest.Sequential
|
||||
|
||||
class TestSequence extends Sequential(
|
||||
new GameplayTests(),
|
||||
new MainTests(),
|
||||
new MatchTests(),
|
||||
new TrickTests(),
|
||||
new QueueTests(),
|
||||
new ImplicitTests(),
|
||||
new PlayerTests(),
|
||||
new TextPlayerControllerTests(),
|
||||
new TextMatchControllerTests(),
|
||||
new CardTests(),
|
||||
new DeckTests(),
|
||||
new HandTests(),
|
||||
|
||||
) {}
|
||||
49
src/test/scala/de/knockoutwhist/cards/CardTests.scala
Normal file
49
src/test/scala/de/knockoutwhist/cards/CardTests.scala
Normal file
@@ -0,0 +1,49 @@
|
||||
package de.knockoutwhist.cards
|
||||
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
|
||||
class CardTests extends AnyWordSpec with Matchers{
|
||||
|
||||
"A card" should {
|
||||
"be displayed with correct value and Suit" in {
|
||||
val card = Card(CardValue.Ace, Suit.Spades)
|
||||
val e = "Ace of Spades"
|
||||
card.toString.equals(e) shouldBe true
|
||||
}
|
||||
"can be rendered" in {
|
||||
val card = Card(CardValue.Ace, Suit.Spades)
|
||||
val expectedResult = Vector[String](
|
||||
"┌─────────┐",
|
||||
s"│${Console.BLACK}${Console.BOLD}A${Console.RESET} │",
|
||||
"│ │",
|
||||
s"│ ${Console.BLACK}${Console.BOLD}♠${Console.RESET} │",
|
||||
"│ │",
|
||||
s"│ ${Console.BLACK}${Console.BOLD}A${Console.RESET}│",
|
||||
"└─────────┘"
|
||||
)
|
||||
card.renderAsString() shouldBe expectedResult
|
||||
}
|
||||
"can be rendered for CardValue Ten" in {
|
||||
val card = Card(CardValue.Ten, Suit.Spades)
|
||||
val expectedResult = Vector[String](
|
||||
"┌─────────┐",
|
||||
s"│${Console.BLACK}${Console.BOLD}10${Console.RESET} │",
|
||||
"│ │",
|
||||
s"│ ${Console.BLACK}${Console.BOLD}♠${Console.RESET} │",
|
||||
"│ │",
|
||||
s"│ ${Console.BLACK}${Console.BOLD}10${Console.RESET}│",
|
||||
"└─────────┘"
|
||||
)
|
||||
card.renderAsString() shouldBe expectedResult
|
||||
}
|
||||
"be able to reset the order" in {
|
||||
CardManager.shuffleAndReset()
|
||||
CardManager.resetOrder()
|
||||
val card = CardManager.nextCard()
|
||||
card.suit shouldBe Suit.Spades
|
||||
card.cardValue shouldBe CardValue.Two
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +1,9 @@
|
||||
package de.knockoutwhist.cards
|
||||
|
||||
import de.knockoutwhist.rounds.{Round, Trick}
|
||||
import org.scalatest.matchers.must.Matchers
|
||||
import org.scalatest.matchers.should.Matchers.{should, shouldBe}
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
|
||||
import scala.collection.mutable
|
||||
import scala.collection.mutable.ListBuffer
|
||||
|
||||
class DeckTests extends AnyWordSpec with Matchers{
|
||||
|
||||
"A deck" should {
|
||||
@@ -52,192 +48,14 @@ class DeckTests extends AnyWordSpec with Matchers{
|
||||
val hand = CardManager.createHand(2)
|
||||
hand.cards should have size 2
|
||||
}
|
||||
}
|
||||
"A card" should {
|
||||
"be displayed with correct value and Suit" in {
|
||||
val card = Card(CardValue.Ace, Suit.Spades)
|
||||
val e = "Ace of Spades"
|
||||
card.toString.equals(e) shouldBe true
|
||||
}
|
||||
"can be rendered" in {
|
||||
val card = Card(CardValue.Ace, Suit.Spades)
|
||||
val expectedResult = Vector[String](
|
||||
"┌─────────┐",
|
||||
"│A │",
|
||||
"│ │",
|
||||
"│ ♠ │",
|
||||
"│ │",
|
||||
"│ A│",
|
||||
"└─────────┘"
|
||||
)
|
||||
card.renderAsString() shouldBe expectedResult
|
||||
}
|
||||
"can be rendered for CardValue Ten" in {
|
||||
val card = Card(CardValue.Ten, Suit.Spades)
|
||||
val expectedResult = Vector[String](
|
||||
"┌─────────┐",
|
||||
"│10 │",
|
||||
"│ │",
|
||||
"│ ♠ │",
|
||||
"│ │",
|
||||
"│ 10│",
|
||||
"└─────────┘"
|
||||
)
|
||||
card.renderAsString() shouldBe expectedResult
|
||||
}
|
||||
}
|
||||
"A player" should {
|
||||
"be able to remove cards from its hand" in {
|
||||
val handholder = ListBuffer[Card]()
|
||||
handholder.addOne(Card(CardValue.Ace, Suit.Spades))
|
||||
val hand = Hand(handholder.toList)
|
||||
val removedhand = hand.removeCard(Card(CardValue.Ace, Suit.Spades))
|
||||
removedhand.cards should have size 0
|
||||
}
|
||||
"be able to see, if he has a certain suit" in {
|
||||
val handholder = ListBuffer[Card]()
|
||||
handholder.addOne(Card(CardValue.Ace, Suit.Spades))
|
||||
val hand = Hand(handholder.toList)
|
||||
hand.hasSuit(Suit.Spades) shouldBe true
|
||||
}
|
||||
"be able to see, if he has a certain value" in {
|
||||
val handholder = ListBuffer[Card]()
|
||||
handholder.addOne(Card(CardValue.Ace, Suit.Spades))
|
||||
val hand = Hand(handholder.toList)
|
||||
hand.hasValue(CardValue.Ace) shouldBe true
|
||||
}
|
||||
"be able to see, if he has a card of Trumpsuit" in {
|
||||
val handholder = ListBuffer[Card]()
|
||||
handholder.addOne(Card(CardValue.Ace, Suit.Spades))
|
||||
val hand = Hand(handholder.toList)
|
||||
hand.hasTrumpSuit(Suit.Spades) shouldBe true
|
||||
}
|
||||
"be able to render his hand" in {
|
||||
val handholder = ListBuffer[Card]()
|
||||
handholder.addOne(Card(CardValue.Ace, Suit.Spades))
|
||||
handholder.addOne(Card(CardValue.Queen, Suit.Diamonds))
|
||||
val hand = Hand(handholder.toList)
|
||||
val expectedResult = List(
|
||||
"┌─────────┐ ┌─────────┐",
|
||||
"│A │ │Q │",
|
||||
"│ │ │ │",
|
||||
"│ ♠ │ │ ♦ │",
|
||||
"│ │ │ │",
|
||||
"│ A│ │ Q│",
|
||||
"└─────────┘ └─────────┘"
|
||||
)
|
||||
hand.renderAsString() shouldBe expectedResult
|
||||
}
|
||||
}
|
||||
"The playCard() Function" should {
|
||||
"be true for the first card played in a trick" in {
|
||||
val playerlist = List(Player("Gunter"))
|
||||
val player = Player("Gunter")
|
||||
val tricks_played: ListBuffer[Trick] = ListBuffer.empty[Trick]
|
||||
val round = Round(Suit.Spades, 7, tricks_played, playerlist)
|
||||
val card = Card(CardValue.Ace, Suit.Spades)
|
||||
val trick = new Trick(round)
|
||||
trick.playCard(card, player) shouldBe true
|
||||
}
|
||||
"be true if the suit matches the first card played" in {
|
||||
val player = Player("Gunter")
|
||||
val player2 = Player("Peter")
|
||||
val playerlist = List(player, player2)
|
||||
val tricks_played: ListBuffer[Trick] = ListBuffer.empty[Trick]
|
||||
val round = Round(Suit.Diamonds, 7, tricks_played, playerlist)
|
||||
val card = Card(CardValue.Two, Suit.Spades)
|
||||
val card2 = Card(CardValue.Ace, Suit.Spades)
|
||||
val trick = new Trick(round)
|
||||
trick.playCard(card, player)
|
||||
trick.playCard(card2, player2) shouldBe true
|
||||
}
|
||||
"be true if the card matches the trump-card" in {
|
||||
val player = Player("Gunter")
|
||||
val player2 = Player("Peter")
|
||||
val playerlist = List(player, player2)
|
||||
val tricks_played: ListBuffer[Trick] = ListBuffer.empty[Trick]
|
||||
val round = Round(Suit.Diamonds, 7, tricks_played, playerlist)
|
||||
val card = Card(CardValue.Ace, Suit.Spades)
|
||||
val card2 = Card(CardValue.Two, Suit.Diamonds)
|
||||
val trick = new Trick(round)
|
||||
trick.playCard(card, player)
|
||||
trick.playCard(card2, player2) shouldBe true
|
||||
}
|
||||
"be false if the card doesn't match the suit of the trump-card + first-card" in {
|
||||
val player = Player("Gunter")
|
||||
val player2 = Player("Peter")
|
||||
val playerlist = List(player, player2)
|
||||
val tricks_played: ListBuffer[Trick] = ListBuffer.empty[Trick]
|
||||
val round = Round(Suit.Diamonds, 7, tricks_played, playerlist)
|
||||
val card = Card(CardValue.Ace, Suit.Spades)
|
||||
val card2 = Card(CardValue.Two, Suit.Clubs)
|
||||
val trick = new Trick(round)
|
||||
trick.playCard(card, player)
|
||||
trick.playCard(card2, player2) shouldBe false
|
||||
}
|
||||
}
|
||||
"A trick" should {
|
||||
"be able to tell who won the trick" in {
|
||||
val playerlist = List(Player("Gunter"))
|
||||
val player = Player("Gunter")
|
||||
val tricks_played: ListBuffer[Trick] = ListBuffer.empty[Trick]
|
||||
val round = Round(Suit.Spades, 7, tricks_played, playerlist)
|
||||
val card = Card(CardValue.Ace, Suit.Spades)
|
||||
val trick = new Trick(round)
|
||||
|
||||
trick.playCard(card, player)
|
||||
|
||||
val won = trick.wonTrick()
|
||||
|
||||
won(0) shouldBe player
|
||||
won(1).cards should equal(trick.cards)
|
||||
won(1).winner should equal(player)
|
||||
won(1).winner should equal(won(0))
|
||||
}
|
||||
"throw a IllegalStateException if it is already finished" in {
|
||||
val playerlist = List(Player("Gunter"))
|
||||
val player = Player("Gunter")
|
||||
val tricks_played: ListBuffer[Trick] = ListBuffer.empty[Trick]
|
||||
val round = Round(Suit.Spades, 7, tricks_played, playerlist)
|
||||
val card = Card(CardValue.Ace, Suit.Spades)
|
||||
val trick = new Trick(round)
|
||||
trick.playCard(card, player)
|
||||
|
||||
val won = trick.wonTrick()
|
||||
assertThrows[IllegalStateException] { //If exception is thrown, assertThrows returns succeeded
|
||||
won(1).playCard(card, player)
|
||||
"throw an exception if you request more then 52 cards without shuffling" in {
|
||||
assertThrows[IndexOutOfBoundsException] {
|
||||
for (_ <- 1 to 53) {
|
||||
CardManager.nextCard()
|
||||
}
|
||||
}
|
||||
}
|
||||
"filter the cards by suit correctly if no trump was played" in {
|
||||
val player = Player("Gunter")
|
||||
val player2 = Player("Peter")
|
||||
val playerlist = List(player, player2)
|
||||
val tricks_played: ListBuffer[Trick] = ListBuffer.empty[Trick]
|
||||
val round = Round(Suit.Hearts, 7, tricks_played, playerlist)
|
||||
val card = Card(CardValue.Ace, Suit.Spades)
|
||||
val card2 = Card(CardValue.Ten, Suit.Spades)
|
||||
val trick = new Trick(round)
|
||||
trick.playCard(card, player)
|
||||
trick.playCard(card2, player2)
|
||||
val won = trick.wonTrick()
|
||||
won(0) shouldBe player
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
"A player" should {
|
||||
"be able to have a hand" in {
|
||||
val card = Card(CardValue.Ace, Suit.Spades)
|
||||
val card2 = Card(CardValue.Ten, Suit.Spades)
|
||||
val card3 = Card(CardValue.Ten, Suit.Diamonds)
|
||||
val listCard = List(card, card2, card3)
|
||||
val testhand = Hand(listCard)
|
||||
val player = Player("Gunter")
|
||||
player.provideHand(testhand) shouldBe true
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
55
src/test/scala/de/knockoutwhist/cards/HandTests.scala
Normal file
55
src/test/scala/de/knockoutwhist/cards/HandTests.scala
Normal file
@@ -0,0 +1,55 @@
|
||||
package de.knockoutwhist.cards
|
||||
|
||||
import de.knockoutwhist.cards.{Card, CardValue, Hand, Suit}
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
|
||||
import scala.collection.mutable.ListBuffer
|
||||
|
||||
class HandTests extends AnyWordSpec with Matchers {
|
||||
|
||||
"The hand" should {
|
||||
"be able to remove cards from its hand" in {
|
||||
val handholder = ListBuffer[Card]()
|
||||
handholder.addOne(Card(CardValue.Ace, Suit.Spades))
|
||||
val hand = Hand(handholder.toList)
|
||||
val removedhand = hand.removeCard(Card(CardValue.Ace, Suit.Spades))
|
||||
removedhand.cards should have size 0
|
||||
}
|
||||
"be able to see, if he has a certain suit" in {
|
||||
val handholder = ListBuffer[Card]()
|
||||
handholder.addOne(Card(CardValue.Ace, Suit.Spades))
|
||||
val hand = Hand(handholder.toList)
|
||||
hand.hasSuit(Suit.Spades) shouldBe true
|
||||
}
|
||||
"be able to see, if he has a certain value" in {
|
||||
val handholder = ListBuffer[Card]()
|
||||
handholder.addOne(Card(CardValue.Ace, Suit.Spades))
|
||||
val hand = Hand(handholder.toList)
|
||||
hand.hasValue(CardValue.Ace) shouldBe true
|
||||
}
|
||||
"be able to see, if he has a card of Trumpsuit" in {
|
||||
val handholder = ListBuffer[Card]()
|
||||
handholder.addOne(Card(CardValue.Ace, Suit.Spades))
|
||||
val hand = Hand(handholder.toList)
|
||||
hand.hasTrumpSuit(Suit.Spades) shouldBe true
|
||||
}
|
||||
"be able to render his hand" in {
|
||||
val handholder = ListBuffer[Card]()
|
||||
handholder.addOne(Card(CardValue.Ace, Suit.Spades))
|
||||
handholder.addOne(Card(CardValue.Queen, Suit.Diamonds))
|
||||
val hand = Hand(handholder.toList)
|
||||
val expectedResult = List(
|
||||
"┌─────────┐ ┌─────────┐",
|
||||
s"│${Console.BLACK}${Console.BOLD}A${Console.RESET} │ │${Console.RED}${Console.BOLD}Q${Console.RESET} │",
|
||||
"│ │ │ │",
|
||||
s"│ ${Console.BLACK}${Console.BOLD}♠${Console.RESET} │ │ ${Console.RED}${Console.BOLD}♦${Console.RESET} │",
|
||||
"│ │ │ │",
|
||||
s"│ ${Console.BLACK}${Console.BOLD}A${Console.RESET}│ │ ${Console.RED}${Console.BOLD}Q${Console.RESET}│",
|
||||
"└─────────┘ └─────────┘"
|
||||
)
|
||||
hand.renderAsString() shouldBe expectedResult
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
package de.knockoutwhist.control.text
|
||||
|
||||
import de.knockoutwhist.cards.CardManager
|
||||
import de.knockoutwhist.cards.CardValue.Ace
|
||||
import de.knockoutwhist.cards.Suit.Hearts
|
||||
import de.knockoutwhist.cards.{Card, CardValue, Hand, Suit}
|
||||
import de.knockoutwhist.player.Player
|
||||
import de.knockoutwhist.rounds.{Match, Round, Trick}
|
||||
import de.knockoutwhist.testutils.TestUtil
|
||||
import de.knockoutwhist.utils.CustomPlayerQueue
|
||||
import org.scalatest.matchers.must.Matchers
|
||||
import org.scalatest.matchers.should.Matchers.{should, shouldBe}
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
|
||||
class TextMatchControllerTests extends AnyWordSpec with Matchers {
|
||||
"The start function" should {
|
||||
"throw no exception" in {
|
||||
TestUtil.cancelOut() {
|
||||
TestUtil.simulateInput("a\n2\n") {
|
||||
TextMatchControl.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"The enter players function" should {
|
||||
"throw no exception" in {
|
||||
TestUtil.cancelOut() {
|
||||
TestUtil.simulateInput("foo,bar\n") {
|
||||
TextMatchControl.enterPlayers() should be (List(Player("foo"), Player("bar")))
|
||||
}
|
||||
}
|
||||
}
|
||||
"not accept less than 2 players" in {
|
||||
TestUtil.cancelOut() {
|
||||
TestUtil.simulateInput("foo\nbar,foo2\n") {
|
||||
TextMatchControl.enterPlayers() should be (List(Player("bar"), Player("foo2")))
|
||||
}
|
||||
}
|
||||
}
|
||||
"not accept players with the same name" in {
|
||||
TestUtil.cancelOut() {
|
||||
TestUtil.simulateInput("foo,foo\nbar,foo\n") {
|
||||
TextMatchControl.enterPlayers() should be (List(Player("bar"), Player("foo")))
|
||||
}
|
||||
}
|
||||
}
|
||||
"not accept player names less than 2 or greater than 10 characters" in {
|
||||
TestUtil.cancelOut() {
|
||||
TestUtil.simulateInput("f,b\nbarrrrrrrrrrrrrrrrr,foooooooooooooooooooo\nbar,foo\n") {
|
||||
TextMatchControl.enterPlayers() should be (List(Player("bar"), Player("foo")))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"The control round function" should {
|
||||
"throw no exception and return a winner" in {
|
||||
val players = List(Player("foo"), Player("bar"))
|
||||
val matchImpl = Match(players, 1)
|
||||
TestUtil.disableDebugMode()
|
||||
TextMatchControl.playerQueue = CustomPlayerQueue[Player](players.toArray[Player], 0)
|
||||
TestUtil.cancelOut() {
|
||||
TestUtil.simulateInput("1\n1\n1\n") {
|
||||
TextMatchControl.controlRound(matchImpl).winner should be (players.head).or(be (players(1)))
|
||||
}
|
||||
}
|
||||
}
|
||||
"throw no exception and return a winner if both players stay in" in {
|
||||
val players = List(Player("foo"), Player("bar"))
|
||||
val matchImpl = Match(players)
|
||||
TestUtil.enableDebugMode()
|
||||
CardManager.shuffleAndReset()
|
||||
CardManager.resetOrder()
|
||||
|
||||
TextMatchControl.playerQueue = CustomPlayerQueue[Player](players.toArray[Player], 0)
|
||||
TestUtil.cancelOut() {
|
||||
TestUtil.simulateInput("1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n") {
|
||||
TextMatchControl.controlRound(matchImpl).winner should be(players.head).or(be(players(1)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"The next round function" should {
|
||||
"return null if the match is over" in {
|
||||
val players = List(Player("foo"))
|
||||
val matchImpl = Match(players, 2)
|
||||
TestUtil.enableDebugMode()
|
||||
TextMatchControl.playerQueue = CustomPlayerQueue[Player](players.toArray[Player], 0)
|
||||
TestUtil.cancelOut() {
|
||||
TestUtil.simulateInput("1\n1\n1\n") {
|
||||
TextMatchControl.controlRound(matchImpl)
|
||||
TextMatchControl.nextRound(matchImpl) should be (null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"The next trick function" should {
|
||||
"return null if the round is over" in {
|
||||
val players = List(Player("foo"))
|
||||
val matchImpl = Match(players, 2)
|
||||
TestUtil.enableDebugMode()
|
||||
TextMatchControl.playerQueue = CustomPlayerQueue[Player](players.toArray[Player], 0)
|
||||
TestUtil.cancelOut() {
|
||||
TestUtil.simulateInput("1\n1\n1\n") {
|
||||
val round = TextMatchControl.controlRound(matchImpl)
|
||||
TextMatchControl.nextTrick(round) should be (null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"The controlSuit function" should {
|
||||
"check if a player can play from the correct suit but doesnt" in {
|
||||
val player1 = Player("Gunter")
|
||||
val player2 = Player("Peter")
|
||||
val players = List(player1, player2)
|
||||
val hand = Hand(List(Card(CardValue.Ten, Suit.Spades),Card(CardValue.Two, Suit.Hearts)))
|
||||
player1.provideHand(hand)
|
||||
val matchImpl = Match(players, 2)
|
||||
val round = new Round(Suit.Clubs, matchImpl, players, false)
|
||||
val trick = new Trick(round)
|
||||
trick.playCard(Card(Ace, Suit.Hearts), player2)
|
||||
TestUtil.enableDebugMode()
|
||||
TextMatchControl.playerQueue = CustomPlayerQueue[Player](players.toArray[Player], 0)
|
||||
TestUtil.cancelOut() {
|
||||
TestUtil.simulateInput("1\n2\n") {
|
||||
val card = TextMatchControl.controlSuitplayed(trick, player1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"The control Trick function" should {
|
||||
"return the other player if the dog decides not to play" in {
|
||||
val foo = Player("foo")
|
||||
foo.doglife = true
|
||||
foo.provideHand(CardManager.createHand(1))
|
||||
val bar = Player("bar")
|
||||
bar.provideHand(CardManager.createHand(3))
|
||||
val players = List(foo, bar)
|
||||
val matchImpl = Match(players, 2)
|
||||
TestUtil.enableDebugMode()
|
||||
TextMatchControl.playerQueue = CustomPlayerQueue[Player](players.toArray[Player], 0)
|
||||
val round = new Round(Hearts,matchImpl,players,false)
|
||||
TestUtil.cancelOut() {
|
||||
TestUtil.simulateInput("n\n1\n") {
|
||||
val finalTrick = TextMatchControl.controlTrick(round)
|
||||
finalTrick.winner should be(bar)
|
||||
}
|
||||
}
|
||||
}
|
||||
"return the dog if he wins" in {
|
||||
TestUtil.enableDebugMode()
|
||||
CardManager.resetOrder()
|
||||
for (i <- 0 to 12) {
|
||||
CardManager.nextCard()
|
||||
}
|
||||
val foo = Player("foo")
|
||||
foo.doglife = true
|
||||
foo.provideHand(CardManager.createHand(1))
|
||||
val bar = Player("bar")
|
||||
bar.provideHand(CardManager.createHand(3))
|
||||
val players = List(foo, bar)
|
||||
val matchImpl = Match(players, 2)
|
||||
TextMatchControl.playerQueue = CustomPlayerQueue[Player](players.toArray[Player], 0)
|
||||
val round = new Round(foo.currentHand().get.cards.head.suit, matchImpl, players, false)
|
||||
TestUtil.cancelOut() {
|
||||
TestUtil.simulateInput("y\n1\n") {
|
||||
val finalTrick = TextMatchControl.controlTrick(round)
|
||||
finalTrick.winner should be(bar)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
package de.knockoutwhist.control.text
|
||||
|
||||
import de.knockoutwhist.cards.{CardManager, Hand}
|
||||
import de.knockoutwhist.cards.Suit._
|
||||
import de.knockoutwhist.player.Player
|
||||
import de.knockoutwhist.rounds.Round
|
||||
import de.knockoutwhist.testutils.TestUtil
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
|
||||
class TextPlayerControllerTests extends AnyWordSpec with Matchers {
|
||||
|
||||
"The text player controller play function" should {
|
||||
CardManager.shuffleAndReset()
|
||||
TestUtil.cancelOut() {
|
||||
"throw an exception of the player has no hand" in {
|
||||
assertThrows[IllegalStateException] {
|
||||
TestUtil.simulateInput("1\n") {
|
||||
TextPlayerControl.playCard(Player("Foo"))
|
||||
}
|
||||
}
|
||||
}
|
||||
"ask again on an invalid input" in {
|
||||
val player = Player("Foo")
|
||||
CardManager.shuffleAndReset()
|
||||
val hand = CardManager.createHand(1)
|
||||
player.provideHand(hand)
|
||||
val card = TestUtil.simulateInput("0\na\n1\n") {
|
||||
TextPlayerControl.playCard(player)
|
||||
}
|
||||
card should be(hand.cards.head)
|
||||
}
|
||||
"provide the card the player selected" in {
|
||||
val player = Player("Foo")
|
||||
CardManager.shuffleAndReset()
|
||||
val hand = CardManager.createHand(1)
|
||||
player.provideHand(hand)
|
||||
val card = TestUtil.simulateInput("1\n") {
|
||||
TextPlayerControl.playCard(player)
|
||||
}
|
||||
card should be(hand.cards.head)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"The text player controller dogplay function" should {
|
||||
val player = Player("Bar")
|
||||
CardManager.shuffleAndReset()
|
||||
val hand = CardManager.createHand(2)
|
||||
player.provideHand(hand)
|
||||
val round = new Round(Spades, null, List(player), false)
|
||||
TestUtil.cancelOut() {
|
||||
"throw an exception of the player has no hand" in {
|
||||
assertThrows[IllegalStateException] {
|
||||
TestUtil.simulateInput("y\n") {
|
||||
TestUtil.disableDebugMode()
|
||||
TextPlayerControl.dogplayCard(Player("Foo"), round)
|
||||
}
|
||||
}
|
||||
}
|
||||
"ask again on an invalid input" in {
|
||||
TestUtil.enableDebugMode()
|
||||
val player = Player("Foo")
|
||||
CardManager.shuffleAndReset()
|
||||
val hand = CardManager.createHand(1)
|
||||
player.provideHand(hand)
|
||||
val card = TestUtil.simulateInput("a\ny\n") {
|
||||
TextPlayerControl.dogplayCard(player, round)
|
||||
}
|
||||
card should be(Some(hand.cards.head))
|
||||
}
|
||||
"provide the card the player selected" in {
|
||||
TestUtil.enableDebugMode()
|
||||
val player = Player("Foo")
|
||||
CardManager.shuffleAndReset()
|
||||
val hand = CardManager.createHand(1)
|
||||
player.provideHand(hand)
|
||||
val card = TestUtil.simulateInput("y\n") {
|
||||
TextPlayerControl.dogplayCard(player, round)
|
||||
}
|
||||
card should be(Some(hand.cards.head))
|
||||
}
|
||||
"allow the dog to not play this trick" in {
|
||||
TestUtil.enableDebugMode()
|
||||
val player = Player("Foo")
|
||||
CardManager.shuffleAndReset()
|
||||
val hand = CardManager.createHand(1)
|
||||
player.provideHand(hand)
|
||||
val card = TestUtil.simulateInput("n\n") {
|
||||
TextPlayerControl.dogplayCard(player, round)
|
||||
}
|
||||
card should be(None)
|
||||
}
|
||||
"force the dog to play in the last round" in {
|
||||
TestUtil.enableDebugMode()
|
||||
val player1 = Player("Foo")
|
||||
CardManager.shuffleAndReset()
|
||||
player1.provideHand(CardManager.createHand(1))
|
||||
player1.doglife = true
|
||||
val player2 = Player("Bar")
|
||||
player2.provideHand(Hand(List()))
|
||||
val round2 = new Round(Spades, null, List(player1,player2), true)
|
||||
val card = TestUtil.simulateInput("n\ny\n") {
|
||||
TextPlayerControl.dogplayCard(player1, round2)
|
||||
}
|
||||
card should be(Some(player1.currentHand().get.cards.head))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"The text player controller determineWinnerTie function" should {
|
||||
TestUtil.cancelOut() {
|
||||
"return the player with the highest card" in {
|
||||
TestUtil.disableDebugMode()
|
||||
val player1 = Player("Foo")
|
||||
val player2 = Player("Bar")
|
||||
val players = List(player1, player2)
|
||||
val winner = TestUtil.simulateInput("1\n2\n") {
|
||||
TextPlayerControl.determineWinnerTie(players)
|
||||
}
|
||||
winner should be(player2).or(be(player1))
|
||||
}
|
||||
"return the player with the highest card after a tie" in {
|
||||
TestUtil.enableDebugMode()
|
||||
CardManager.resetOrder()
|
||||
val player1 = Player("Foo")
|
||||
val player2 = Player("Bar")
|
||||
val players = List(player1, player2)
|
||||
val winner = TestUtil.simulateInput("1\n13\n5\n1\n") {
|
||||
TextPlayerControl.determineWinnerTie(players)
|
||||
}
|
||||
winner should be(player2)
|
||||
}
|
||||
"return the player with the highest card after a tie (winner first)" in {
|
||||
TestUtil.enableDebugMode()
|
||||
CardManager.resetOrder()
|
||||
val player1 = Player("Foo")
|
||||
val player2 = Player("Bar")
|
||||
val players = List(player1, player2)
|
||||
val winner = TestUtil.simulateInput("13\n1\n") {
|
||||
TextPlayerControl.determineWinnerTie(players)
|
||||
}
|
||||
winner should be(player1)
|
||||
}
|
||||
"ask again on an invalid input" in {
|
||||
TestUtil.enableDebugMode()
|
||||
CardManager.resetOrder()
|
||||
val player1 = Player("Foo")
|
||||
val player2 = Player("Bar")
|
||||
val players = List(player1, player2)
|
||||
val winner = TestUtil.simulateInput("a\n200\n1\n2\n") {
|
||||
TextPlayerControl.determineWinnerTie(players)
|
||||
}
|
||||
winner should be(player2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"The text player controller pickNextTrumpsuit function" should {
|
||||
TestUtil.cancelOut() {
|
||||
"return the suit the player selected (Spades)" in {
|
||||
TestUtil.disableDebugMode()
|
||||
val player = Player("Foo")
|
||||
player.provideHand(CardManager.createHand(4))
|
||||
val suit = TestUtil.simulateInput("4\n") {
|
||||
TextPlayerControl.pickNextTrumpsuit(player)
|
||||
}
|
||||
suit should be(Spades)
|
||||
}
|
||||
"return the suit the player selected (Hearts)" in {
|
||||
TestUtil.disableDebugMode()
|
||||
val player = Player("Foo")
|
||||
player.provideHand(CardManager.createHand(4))
|
||||
val suit = TestUtil.simulateInput("1\n") {
|
||||
TextPlayerControl.pickNextTrumpsuit(player)
|
||||
}
|
||||
suit should be(Hearts)
|
||||
}
|
||||
"return the suit the player selected (Diamonds)" in {
|
||||
TestUtil.disableDebugMode()
|
||||
val player = Player("Foo")
|
||||
player.provideHand(CardManager.createHand(4))
|
||||
val suit = TestUtil.simulateInput("2\n") {
|
||||
TextPlayerControl.pickNextTrumpsuit(player)
|
||||
}
|
||||
suit should be(Diamonds)
|
||||
}
|
||||
"return the suit the player selected (Clubs)" in {
|
||||
TestUtil.disableDebugMode()
|
||||
val player = Player("Foo")
|
||||
player.provideHand(CardManager.createHand(4))
|
||||
val suit = TestUtil.simulateInput("3\n") {
|
||||
TextPlayerControl.pickNextTrumpsuit(player)
|
||||
}
|
||||
suit should be(Clubs)
|
||||
}
|
||||
"ask again on an invalid input" in {
|
||||
TestUtil.enableDebugMode()
|
||||
val player = Player("Foo")
|
||||
player.provideHand(CardManager.createHand(4))
|
||||
val suit = TestUtil.simulateInput("a\n10\n1\n") {
|
||||
TextPlayerControl.pickNextTrumpsuit(player)
|
||||
}
|
||||
suit should be(Hearts)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"The text player controller showCards function" should {
|
||||
TestUtil.cancelOut() {
|
||||
"return true if the player wants to show their cards" in {
|
||||
TestUtil.disableDebugMode()
|
||||
val player = Player("Foo")
|
||||
player.provideHand(CardManager.createHand(4))
|
||||
TextPlayerControl.showCards(player) should be(true)
|
||||
}
|
||||
"return false if the player does not want to show their cards" in {
|
||||
TestUtil.disableDebugMode()
|
||||
val player = Player("Foo")
|
||||
TextPlayerControl.showCards(player) should be(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"The text player controller showWon function" should {
|
||||
TestUtil.cancelOut() {
|
||||
"print the winner of the match" in {
|
||||
TestUtil.disableDebugMode()
|
||||
val player = Player("Foo")
|
||||
TextPlayerControl.showWon(player, null) should be("Foo won this round.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
32
src/test/scala/de/knockoutwhist/player/PlayerTests.scala
Normal file
32
src/test/scala/de/knockoutwhist/player/PlayerTests.scala
Normal file
@@ -0,0 +1,32 @@
|
||||
package de.knockoutwhist.player
|
||||
|
||||
import de.knockoutwhist.cards.{Card, CardValue, Hand, Suit}
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
|
||||
class PlayerTests extends AnyWordSpec with Matchers {
|
||||
|
||||
"A player" should {
|
||||
"be able to have a hand" in {
|
||||
val card = Card(CardValue.Ace, Suit.Spades)
|
||||
val card2 = Card(CardValue.Ten, Suit.Spades)
|
||||
val card3 = Card(CardValue.Ten, Suit.Diamonds)
|
||||
val listCard = List(card, card2, card3)
|
||||
val testhand = Hand(listCard)
|
||||
val player = Player("Gunter")
|
||||
player.provideHand(testhand) shouldBe true
|
||||
}
|
||||
"be able to remove a Card" in {
|
||||
val card = Card(CardValue.Ace, Suit.Spades)
|
||||
val card2 = Card(CardValue.Ten, Suit.Spades)
|
||||
val card3 = Card(CardValue.Ten, Suit.Diamonds)
|
||||
val listCard = List(card, card2, card3)
|
||||
val testhand = Hand(listCard)
|
||||
val player = Player("Gunter")
|
||||
player.provideHand(testhand)
|
||||
player.removeCard(card) shouldBe 2
|
||||
player.currentHand().get.cards should be (List(card2, card3))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
28
src/test/scala/de/knockoutwhist/rounds/GameplayTests.scala
Normal file
28
src/test/scala/de/knockoutwhist/rounds/GameplayTests.scala
Normal file
@@ -0,0 +1,28 @@
|
||||
package de.knockoutwhist.rounds
|
||||
|
||||
import de.knockoutwhist.cards.CardManager
|
||||
import de.knockoutwhist.control.text.TextMatchControl
|
||||
import de.knockoutwhist.testutils.TestUtil
|
||||
import org.scalatest.matchers.must.Matchers
|
||||
import org.scalatest.matchers.should.Matchers.{should, shouldBe}
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
|
||||
import scala.List
|
||||
|
||||
|
||||
class GameplayTests extends AnyWordSpec with Matchers {
|
||||
"The Match Control" must {
|
||||
"not throw an exception" in {
|
||||
TestUtil.enableDebugMode()
|
||||
CardManager.shuffleAndReset()
|
||||
CardManager.resetOrder()
|
||||
TestUtil.cancelOut() {
|
||||
TestUtil.simulateInput("1\nLeon,Janis\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\ny\n1\n1\n1\n2\n") {
|
||||
TextMatchControl.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
151
src/test/scala/de/knockoutwhist/rounds/MatchTests.scala
Normal file
151
src/test/scala/de/knockoutwhist/rounds/MatchTests.scala
Normal file
@@ -0,0 +1,151 @@
|
||||
package de.knockoutwhist.rounds
|
||||
|
||||
import de.knockoutwhist.KnockOutWhist
|
||||
import de.knockoutwhist.cards.{Card, CardManager, CardValue, Suit}
|
||||
import de.knockoutwhist.player.Player
|
||||
import de.knockoutwhist.testutils.TestUtil
|
||||
import org.scalatest.matchers.must.Matchers
|
||||
import org.scalatest.matchers.should.Matchers.{should, shouldBe}
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
|
||||
import scala.List
|
||||
import scala.collection.mutable.ListBuffer
|
||||
|
||||
|
||||
class MatchTests extends AnyWordSpec with Matchers{
|
||||
|
||||
"A Match" should {
|
||||
TestUtil.cancelOut() {
|
||||
TestUtil.disableDebugMode()
|
||||
val player1 = Player("Gunter")
|
||||
val player2 = Player("Peter")
|
||||
val player_list = List(player1, player2)
|
||||
val match1 = Match(player_list)
|
||||
val round1 = match1.create_round()
|
||||
val trumpsuit = round1.trumpSuit
|
||||
val trick1 = round1.create_trick()
|
||||
val playedcard1 = TestUtil.simulateInput("1\n") {
|
||||
KnockOutWhist.matchControl.playerControl.playCard(player1)
|
||||
}
|
||||
trick1.playCard(playedcard1, player1)
|
||||
val playedcard2 = TestUtil.simulateInput("1\n") {
|
||||
KnockOutWhist.matchControl.playerControl.playCard(player2)
|
||||
}
|
||||
trick1.playCard(playedcard2, player2)
|
||||
"return the players ingame in players_remaining" in {
|
||||
round1.remainingPlayers() should be(player_list)
|
||||
}
|
||||
val rtrick1 = trick1.wonTrick()
|
||||
round1.finalizeRound(true)
|
||||
val round2 = TestUtil.simulateInput("1\n") {
|
||||
match1.create_round()
|
||||
}
|
||||
TestUtil.enableDebugMode()
|
||||
var trick2: Trick = null
|
||||
"should be able to create a trick with requesting the current trick" in {
|
||||
trick2 = round2.get_current_trick()
|
||||
}
|
||||
if (trick2 == null) {
|
||||
trick2 = round2.get_current_trick()
|
||||
}
|
||||
val playedcard3 = TestUtil.simulateInput("1\n") {
|
||||
KnockOutWhist.matchControl.playerControl.playCard(player1)
|
||||
}
|
||||
trick1.playCard(playedcard3, player1)
|
||||
val playedcard4 = TestUtil.simulateInput("1\n") {
|
||||
KnockOutWhist.matchControl.playerControl.playCard(player2)
|
||||
}
|
||||
trick2.playCard(playedcard4, player2)
|
||||
"be able to return the current trick of the round" in {
|
||||
round2.get_current_trick() should be(trick2)
|
||||
}
|
||||
val rtrick2 = trick2.wonTrick()
|
||||
"return false if the round isn't over" in {
|
||||
round2.isOver shouldBe false
|
||||
}
|
||||
"be able to return all the tricks of the round" in {
|
||||
round1.get_tricks() should be(List(rtrick1._2))
|
||||
}
|
||||
"be able to tell if a dog needs to play" in {
|
||||
round2.dogNeedsToPlay shouldBe false
|
||||
}
|
||||
"error out if a round is finalized without all tricks played" in {
|
||||
assertThrows[IllegalStateException] {
|
||||
round2.finalizeRound()
|
||||
}
|
||||
}
|
||||
round2.finalizeRound(true)
|
||||
val round3 = TestUtil.simulateInput("1\n") {
|
||||
match1.create_round()
|
||||
}
|
||||
val trick3 = round3.create_trick()
|
||||
val playedcard5 = TestUtil.simulateInput("1\n") {
|
||||
KnockOutWhist.matchControl.playerControl.playCard(player1)
|
||||
}
|
||||
trick1.playCard(playedcard5, player1)
|
||||
val playedcard6 = TestUtil.simulateInput("1\n") {
|
||||
KnockOutWhist.matchControl.playerControl.playCard(player2)
|
||||
}
|
||||
trick3.playCard(playedcard6, player2)
|
||||
trick3.wonTrick()
|
||||
"throw an exception if a match gets finalized before it is finished" in {
|
||||
assertThrows[IllegalStateException] { //If exception is thrown, assertThrows returns succeeded
|
||||
match1.finalizeMatch()
|
||||
}
|
||||
}
|
||||
"be able to create a random trumpsuit for first round" in {
|
||||
round2.trumpSuit shouldBe Suit.Hearts
|
||||
}
|
||||
"return false when no round has been completed" in {
|
||||
CardManager.shuffleAndReset()
|
||||
val match3 = Match(List(Player("Gunter")))
|
||||
match3.create_round()
|
||||
match3.isOver shouldBe false
|
||||
}
|
||||
"return true if one player is remaining after a round has been played" in {
|
||||
round3.finalizeRound(true)
|
||||
match1.isOver shouldBe true
|
||||
}
|
||||
val round4 = TestUtil.simulateInput("1\n") {
|
||||
match1.create_round()
|
||||
}
|
||||
val trick4 = round4.create_trick()
|
||||
val playedcard7 = Card(CardValue.Ace, Suit.Hearts)
|
||||
val playedcard8 = Card(CardValue.Two, Suit.Hearts)
|
||||
trick4.playCard(playedcard7, player1)
|
||||
trick4.playCard(playedcard8, player2)
|
||||
trick4.wonTrick()
|
||||
|
||||
val trick5 = round4.create_trick()
|
||||
trick5.playCard(playedcard8, player1)
|
||||
trick5.playCard(playedcard7, player2)
|
||||
trick5.wonTrick()
|
||||
CardManager.shuffleAndReset()
|
||||
val roundResult = TestUtil.simulateInput("1\n13\n") {
|
||||
round4.finalizeRound(true)
|
||||
}
|
||||
|
||||
val round5 = TestUtil.simulateInput("1\n") {
|
||||
match1.create_round()
|
||||
}
|
||||
"error out if a round is finalized without any tricks played" in {
|
||||
assertThrows[IllegalStateException] {
|
||||
round5.finalizeRound()
|
||||
}
|
||||
}
|
||||
"be able to finalize a round" in {
|
||||
roundResult._1 should be(player1).or(be(player2))
|
||||
}
|
||||
|
||||
"provide a toString for the rounds" in {
|
||||
round5.toString should be(s"${Suit.Hearts}, ${ListBuffer()}, $player_list, null, null, false")
|
||||
}
|
||||
"show the winner of the match when it has ended" in {
|
||||
match1.finalizeMatch() shouldBe Player("Peter")
|
||||
}
|
||||
"have a working toString Method" in {
|
||||
match1.toString shouldBe "List(Gunter, Peter), 2"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
129
src/test/scala/de/knockoutwhist/rounds/TrickTests.scala
Normal file
129
src/test/scala/de/knockoutwhist/rounds/TrickTests.scala
Normal file
@@ -0,0 +1,129 @@
|
||||
package de.knockoutwhist.rounds
|
||||
|
||||
import de.knockoutwhist.cards.{Card, CardValue, Suit}
|
||||
import de.knockoutwhist.player.Player
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
|
||||
class TrickTests extends AnyWordSpec with Matchers {
|
||||
|
||||
"A trick" should {
|
||||
"be able to return the first card after it was played" in {
|
||||
val player = Player("Gunter")
|
||||
val player2 = Player("Peter")
|
||||
val playerlist = List(player, player2)
|
||||
val round = new Round(Suit.Diamonds, Match(playerlist), playerlist, false)
|
||||
val card = Card(CardValue.Ace, Suit.Spades)
|
||||
val card2 = Card(CardValue.Two, Suit.Clubs)
|
||||
val trick = new Trick(round)
|
||||
trick.playCard(card, player)
|
||||
trick.get_first_card().isEmpty shouldBe false
|
||||
trick.get_first_card().get shouldBe card
|
||||
}
|
||||
"be able to return no first card when none was played" in {
|
||||
val player = Player("Gunter")
|
||||
val player2 = Player("Peter")
|
||||
val playerlist = List(player, player2)
|
||||
val round = new Round(Suit.Diamonds, Match(playerlist), playerlist, false)
|
||||
val trick = new Trick(round)
|
||||
trick.get_first_card().isEmpty shouldBe true
|
||||
}
|
||||
"be able to tell who won the trick" in {
|
||||
val playerlist = List(Player("Gunter"))
|
||||
val player = Player("Gunter")
|
||||
val round = new Round(Suit.Spades, Match(playerlist), playerlist, false)
|
||||
val card = Card(CardValue.Ace, Suit.Spades)
|
||||
val trick = new Trick(round)
|
||||
|
||||
trick.playCard(card, player)
|
||||
|
||||
val won = trick.wonTrick()
|
||||
|
||||
won(0) shouldBe player
|
||||
won(1).cards should equal(trick.cards)
|
||||
won(1).winner should equal(player)
|
||||
won(1).winner should equal(won(0))
|
||||
}
|
||||
"throw a IllegalStateException if it is already finished" in {
|
||||
val playerlist = List(Player("Gunter"))
|
||||
val player = Player("Gunter")
|
||||
val round = new Round(Suit.Spades, Match(playerlist), playerlist, false)
|
||||
val card = Card(CardValue.Ace, Suit.Spades)
|
||||
val trick = new Trick(round)
|
||||
trick.playCard(card, player)
|
||||
|
||||
val won = trick.wonTrick()
|
||||
assertThrows[IllegalStateException] { //If exception is thrown, assertThrows returns succeeded
|
||||
won(1).playCard(card, player)
|
||||
}
|
||||
}
|
||||
"filter the cards by suit correctly if no trump was played" in {
|
||||
val player = Player("Gunter")
|
||||
val player2 = Player("Peter")
|
||||
val playerlist = List(player, player2)
|
||||
val round = new Round(Suit.Hearts, Match(playerlist), playerlist, false)
|
||||
val card = Card(CardValue.Ace, Suit.Spades)
|
||||
val card2 = Card(CardValue.Ten, Suit.Spades)
|
||||
val trick = new Trick(round)
|
||||
trick.playCard(card, player)
|
||||
trick.playCard(card2, player2)
|
||||
val won = trick.wonTrick()
|
||||
won(0) shouldBe player
|
||||
|
||||
}
|
||||
"return true for the first card played in a trick" in {
|
||||
val playerlist = List(Player("Gunter"))
|
||||
val player = Player("Gunter")
|
||||
val round = new Round(Suit.Spades, Match(playerlist), playerlist, false)
|
||||
val card = Card(CardValue.Ace, Suit.Spades)
|
||||
val trick = new Trick(round)
|
||||
trick.playCard(card, player) shouldBe true
|
||||
}
|
||||
"return true if the suit matches the first card played" in {
|
||||
val player = Player("Gunter")
|
||||
val player2 = Player("Peter")
|
||||
val playerlist = List(player, player2)
|
||||
val round = new Round(Suit.Diamonds, Match(playerlist), playerlist, false)
|
||||
val card = Card(CardValue.Two, Suit.Spades)
|
||||
val card2 = Card(CardValue.Ace, Suit.Spades)
|
||||
val trick = round.create_trick()
|
||||
trick.playCard(card, player)
|
||||
trick.playCard(card2, player2) shouldBe true
|
||||
}
|
||||
"return true if the card matches the trump-card" in {
|
||||
val player = Player("Gunter")
|
||||
val player2 = Player("Peter")
|
||||
val playerlist = List(player, player2)
|
||||
val round = new Round(Suit.Diamonds, Match(playerlist), playerlist, false)
|
||||
val card = Card(CardValue.Ace, Suit.Spades)
|
||||
val card2 = Card(CardValue.Two, Suit.Diamonds)
|
||||
val trick = new Trick(round)
|
||||
trick.playCard(card, player)
|
||||
trick.playCard(card2, player2) shouldBe true
|
||||
}
|
||||
"return false if the card doesn't match the suit of the trump-card + first-card" in {
|
||||
val player = Player("Gunter")
|
||||
val player2 = Player("Peter")
|
||||
val playerlist = List(player, player2)
|
||||
val round = new Round(Suit.Diamonds, Match(playerlist), playerlist, false)
|
||||
val card = Card(CardValue.Ace, Suit.Spades)
|
||||
val card2 = Card(CardValue.Two, Suit.Clubs)
|
||||
val trick = new Trick(round)
|
||||
trick.playCard(card, player)
|
||||
trick.playCard(card2, player2) shouldBe false
|
||||
}
|
||||
"have a working to string" in {
|
||||
val player = Player("Gunter")
|
||||
val player2 = Player("Peter")
|
||||
val playerlist = List(player, player2)
|
||||
val round = new Round(Suit.Diamonds, Match(playerlist), playerlist, false)
|
||||
val card = Card(CardValue.Ace, Suit.Spades)
|
||||
val card2 = Card(CardValue.Two, Suit.Clubs)
|
||||
val trick = new Trick(round)
|
||||
trick.playCard(card, player)
|
||||
trick.playCard(card2, player2)
|
||||
trick.toString() shouldBe s"${trick.cards}, ${null}, ${false}"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
30
src/test/scala/de/knockoutwhist/testutils/TestUtil.scala
Normal file
30
src/test/scala/de/knockoutwhist/testutils/TestUtil.scala
Normal file
@@ -0,0 +1,30 @@
|
||||
package de.knockoutwhist.testutils
|
||||
|
||||
import de.knockoutwhist.KnockOutWhist
|
||||
|
||||
import java.io.{ByteArrayInputStream, OutputStream}
|
||||
|
||||
|
||||
object TestUtil {
|
||||
|
||||
def simulateInput[T](input: String)(block: => T): T = {
|
||||
Console.withIn(new ByteArrayInputStream(input.getBytes())) {
|
||||
block
|
||||
}
|
||||
}
|
||||
|
||||
def cancelOut[T]()(block: => T): T = {
|
||||
Console.withOut((b: Int) => {}) {
|
||||
block
|
||||
}
|
||||
}
|
||||
|
||||
def enableDebugMode(): Unit = {
|
||||
KnockOutWhist.DEBUG_MODE_VAR = true
|
||||
}
|
||||
|
||||
def disableDebugMode(): Unit = {
|
||||
KnockOutWhist.DEBUG_MODE_VAR = false
|
||||
}
|
||||
|
||||
}
|
||||
22
src/test/scala/de/knockoutwhist/utils/ImplicitTests.scala
Normal file
22
src/test/scala/de/knockoutwhist/utils/ImplicitTests.scala
Normal file
@@ -0,0 +1,22 @@
|
||||
package de.knockoutwhist.utils
|
||||
|
||||
import de.knockoutwhist.utils.Implicits.*
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
|
||||
class ImplicitTests extends AnyWordSpec with Matchers {
|
||||
"The ternary operator" should {
|
||||
"return the left if the condition is met" in {
|
||||
1 should be (true ? 1 |: 2)
|
||||
}
|
||||
"return the right if the condition is not met" in {
|
||||
2 should be (false ? 1 |: 2)
|
||||
}
|
||||
"return None if the condition is not met" in {
|
||||
None should be (false ? 1)
|
||||
}
|
||||
"return an Option if the condition is met" in {
|
||||
Some(1) should be (true ? 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
73
src/test/scala/de/knockoutwhist/utils/QueueTests.scala
Normal file
73
src/test/scala/de/knockoutwhist/utils/QueueTests.scala
Normal file
@@ -0,0 +1,73 @@
|
||||
package de.knockoutwhist.utils
|
||||
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
|
||||
class QueueTests extends AnyWordSpec with Matchers {
|
||||
"A queue" should {
|
||||
|
||||
"return the next player" in {
|
||||
val queue = new CustomPlayerQueue[Int](Array(1, 2, 3, 4, 5))
|
||||
queue.nextPlayer() should be(1)
|
||||
queue.nextPlayer() should be(2)
|
||||
queue.nextPlayer() should be(3)
|
||||
queue.nextPlayer() should be(4)
|
||||
queue.nextPlayer() should be(5)
|
||||
queue.nextPlayer() should be(1)
|
||||
}
|
||||
"remove a player" in {
|
||||
val queue = new CustomPlayerQueue[Int](Array(1, 2, 3, 4, 5))
|
||||
queue.remove(3) should be(4)
|
||||
queue.nextPlayer() should be(1)
|
||||
queue.nextPlayer() should be(2)
|
||||
queue.nextPlayer() should be(4)
|
||||
queue.nextPlayer() should be(5)
|
||||
}
|
||||
"reset and set start" in {
|
||||
val queue = new CustomPlayerQueue[Int](Array(1, 2, 3, 4, 5))
|
||||
queue.resetAndSetStart(5) should be(true)
|
||||
queue.nextPlayer() should be(5)
|
||||
queue.nextPlayer() should be(1)
|
||||
queue.nextPlayer() should be(2)
|
||||
queue.nextPlayer() should be(3)
|
||||
queue.nextPlayer() should be(4)
|
||||
}
|
||||
"reset and set start from an invalid number" in {
|
||||
val queue = new CustomPlayerQueue[Int](Array(1, 2, 3, 4, 5))
|
||||
queue.resetAndSetStart(6) should be(false)
|
||||
queue.nextPlayer() should be(1)
|
||||
queue.nextPlayer() should be(2)
|
||||
queue.nextPlayer() should be(3)
|
||||
queue.nextPlayer() should be(4)
|
||||
queue.nextPlayer() should be(5)
|
||||
}
|
||||
"return a list" in {
|
||||
val queue = new CustomPlayerQueue[Int](Array(1, 2, 3, 4, 5))
|
||||
queue.toList should be(List(1, 2, 3, 4, 5))
|
||||
}
|
||||
"be empty" in {
|
||||
val queue = new CustomPlayerQueue[Int](Array(1, 4, 5))
|
||||
queue.isEmpty should be(false)
|
||||
queue.remove(1)
|
||||
queue.remove(4)
|
||||
queue.remove(5)
|
||||
queue.isEmpty should be(true)
|
||||
}
|
||||
"return the size" in {
|
||||
var queue = new CustomPlayerQueue[Int](Array())
|
||||
queue.size should be(0)
|
||||
queue = new CustomPlayerQueue[Int](Array(1, 2, 3, 4, 5))
|
||||
queue.size should be(5)
|
||||
}
|
||||
"iterate over the queue" in {
|
||||
val queue = new CustomPlayerQueue[Int](Array(1, 2, 3, 4, 5))
|
||||
val iterator = queue.iterator
|
||||
iterator.next() should be(1)
|
||||
iterator.next() should be(2)
|
||||
iterator.next() should be(3)
|
||||
iterator.next() should be(4)
|
||||
iterator.next() should be(5)
|
||||
iterator.hasNext should be(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user