WORK IN PROGRESS. If I find the time ideally i'd like to develop a PLAY2.x app using AKKA actors to orchestrate the poker game. Would be a very nice exercise. :)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package patterns | |
object PokerGame { | |
sealed trait Suit | |
case object Clubs extends Suit | |
case object Diamonds extends Suit | |
case object Hearts extends Suit | |
case object Spades extends Suit | |
sealed trait Rank | |
case object Jack extends Rank | |
case object Queen extends Rank | |
case object King extends Rank | |
case object Ace extends Rank | |
case class Numeric(value: Int) extends Rank | |
sealed trait Color | |
case object Red extends Color | |
case object Black extends Color | |
sealed trait Value | |
case object StraightFlush extends Value | |
case object FourOfKind extends Value | |
case object FullHouse extends Value | |
case object Flush extends Value | |
case object Straight extends Value | |
case object ThreeOfKind extends Value | |
case object TwoPair extends Value | |
case object Pair extends Value | |
case class HighCard(value: Int) extends Value | |
type Card = (Suit, Rank) | |
type Hand = (Card, Card, Card, Card, Card) | |
val D1 = (Diamonds, Numeric(1)) | |
val D2 = (Diamonds, Numeric(2)) | |
val D3 = (Diamonds, Numeric(3)) | |
val D4 = (Diamonds, Numeric(4)) | |
val D5 = (Diamonds, Numeric(5)) | |
val D6 = (Diamonds, Numeric(6)) | |
val D7 = (Diamonds, Numeric(7)) | |
val D8 = (Diamonds, Numeric(8)) | |
val D9 = (Diamonds, Numeric(9)) | |
val D10 = (Diamonds, Numeric(10)) | |
val DJ = (Diamonds, Jack) | |
val DQ = (Diamonds, Queen) | |
val DK = (Diamonds, King) | |
val DA = (Diamonds, Ace) | |
val S1 = (Spades, Numeric(1)) | |
val S2 = (Spades, Numeric(2)) | |
val S3 = (Spades, Numeric(3)) | |
val S4 = (Spades, Numeric(4)) | |
val S5 = (Spades, Numeric(5)) | |
val S6 = (Spades, Numeric(6)) | |
val S7 = (Spades, Numeric(7)) | |
val S8 = (Spades, Numeric(8)) | |
val S9 = (Spades, Numeric(9)) | |
val S10 = (Spades, Numeric(10)) | |
val SJ = (Spades, Jack) | |
val SQ = (Spades, Queen) | |
val SK = (Spades, King) | |
val SA = (Spades, Ace) | |
val H1 = (Hearts, Numeric(1)) | |
val H2 = (Hearts, Numeric(2)) | |
val H3 = (Hearts, Numeric(3)) | |
val H4 = (Hearts, Numeric(4)) | |
val H5 = (Hearts, Numeric(5)) | |
val H6 = (Hearts, Numeric(6)) | |
val H7 = (Hearts, Numeric(7)) | |
val H8 = (Hearts, Numeric(8)) | |
val H9 = (Hearts, Numeric(9)) | |
val H10 = (Hearts, Numeric(10)) | |
val HJ = (Hearts, Jack) | |
val HQ = (Hearts, Queen) | |
val HK = (Hearts, King) | |
val HA = (Hearts, Ace) | |
val C1 = (Clubs, Numeric(1)) | |
val C2 = (Clubs, Numeric(2)) | |
val C3 = (Clubs, Numeric(3)) | |
val C4 = (Clubs, Numeric(4)) | |
val C5 = (Clubs, Numeric(5)) | |
val C6 = (Clubs, Numeric(6)) | |
val C7 = (Clubs, Numeric(7)) | |
val C8 = (Clubs, Numeric(8)) | |
val C9 = (Clubs, Numeric(9)) | |
val C10 = (Clubs, Numeric(10)) | |
val CJ = (Clubs, Jack) | |
val CQ = (Clubs, Queen) | |
val CK = (Clubs, King) | |
val CA = (Clubs, Ace) | |
def valueOf(rank: Rank): Int = rank match { | |
case Ace => 14 | |
case King => 13 | |
case Queen => 12 | |
case Jack => 11 | |
case Numeric(n) => n | |
} | |
def colorOf(suit: Suit): Color = suit match { | |
case Clubs => Black | |
case Spades => Black | |
case _ => Red | |
} | |
def toRanks(hand: Hand): List[Rank] = { | |
val ((suit1, rank1), (suit2, rank2), (suit3, rank3), (suit4, rank4), (suit5, rank5)) = hand | |
List(rank1, rank2, rank3, rank4, rank5) | |
} | |
def toSuites(hand: Hand): List[Suit] = { | |
val ((suit1, rank1), (suit2, rank2), (suit3, rank3), (suit4, rank4), (suit5, rank5)) = hand | |
List(suit1, suit2, suit3, suit4, suit5) | |
} | |
def toColors(hand: Hand): List[Color] = toSuites(hand).map(colorOf _) | |
def toRankValues(hand: Hand): List[Int] = toRanks(hand).map(valueOf _) | |
def toRankSizes(hand: Hand): List[Int] = | |
toRanks(hand).groupBy(identity).map { case (rank, listofranks) => listofranks.size } .toList | |
def isSameSuit(hand: Hand): Boolean = toSuites(hand).forall(_ == hand._1._1) | |
def isStraightFlush(hand: Hand): Boolean = isSameSuit(hand) && isStraight(hand) | |
def isFourOfKind(hand: Hand): Boolean = toRankSizes(hand).exists(_ >= 4) | |
def isFullHouse(hand: Hand): Boolean = { | |
val rankSizes = toRankSizes(hand) | |
rankSizes.exists(_ == 2) && rankSizes.exists(_ == 3) | |
} | |
def isFlush(hand: Hand): Boolean = isSameSuit(hand) | |
def isStraight(hand: Hand): Boolean = { | |
val rankValues = toRankValues(hand) | |
val minimumRankValue = rankValues.min | |
rankValues.toSet == minimumRankValue.to(minimumRankValue + 4).toSet | |
} | |
def isThreeOfKind(hand: Hand): Boolean = toRankSizes(hand).exists(_ >= 3) | |
def isTwoPair(hand: Hand): Boolean = toRankSizes(hand).filter(_ >= 2).size == 2 | |
def isPair(hand: Hand): Boolean = toRankSizes(hand).exists(_ >= 2) | |
def evaluate(hand: Hand): Value = | |
if (isStraightFlush(hand)) StraightFlush | |
else if (isFourOfKind(hand)) FourOfKind | |
else if (isFullHouse(hand)) FullHouse | |
else if (isFlush(hand)) Flush | |
else if (isStraight(hand)) Straight | |
else if (isThreeOfKind(hand)) ThreeOfKind | |
else if (isTwoPair(hand)) TwoPair | |
else if (isPair(hand)) Pair | |
else HighCard(toRankValues(hand).sorted.reverse.toList(0)) | |
/** for unit testing | |
val straightflush = (D10, DJ, DQ, DK, DA) | |
val fourofkind = (H10, HQ, C10, S10, D10) | |
val fullhouse = (H10, D10, SJ, C10, CJ) | |
val flush = (D3, D5, D8, DJ, DA) | |
val straight = (D6,H4, C3, H5, S7) | |
val threeofkind = (H10, HQ, CK, S10, D10) | |
val twopair = (H10, HQ, CK, S10, DQ) | |
val pair = (H9, HQ, CK, S10, D10) | |
val highcard = (HK, S5, S2, C7, D9) | |
val test1 = evaluate(straightflush) == StraightFlush | |
val test2 = evaluate(fourofkind) == FourOfKind | |
val test3 = evaluate(fullhouse) == FullHouse | |
val test4 = evaluate(flush) == Flush | |
val test5 = evaluate(straight) == Straight | |
val test6 = evaluate(threeofkind) == ThreeOfKind | |
val test7 = evaluate(twopair) == TwoPair | |
val test8 = evaluate(pair) == Pair | |
val test9 = evaluate(highcard) == HighCard(13) | |
**/ | |
} |
You entirely go with our expectation and the range of our information.poker online
ReplyDeleteWow, absolutely fantastic blog. I am very glad to have such useful information.
ReplyDeleteหนังสงคราม