We start off with the hand represented as a string such as "2H 3H 4H 5H 6H". This is pretty useless so we need to parse it into a data structure we can reason about. Something like
class PokerHand {
PokerHand(String cards) {
}
Iterable<Card> getCards() {
}
}
where
class Card {
Rank rank
Suit suit
}
Suit is a simple enum
enum Suit {
HEARTS, SPADES, DIAMONDS, CLUBS
}
Rank is also an enum
enum Rank {
final int value
ONE(1), TWO(2),...,ACE(14)
Rank(int value) {
this.value = value
}
}
Through the PokerHand
class we can easily iterate over the hand and get the suit and numerical value of each card.
Comparing one hand with another can be done in two steps
- Figure out which category (pair, 2 pairs, flush, straight, etc.) each hand belongs to
- If they're in different categories, the hand in the higher category wins
- If they're in the same category use a compareTo method that compares two hands in the same category
So we need an interface
interface HandCategory<E extends HandCategory<E>> extends Comparable<E> {
boolean isValid()
Category getCategory()
}
and an implementation for each category, e.g.
class SinglePair implements HandCategory<SinglePair> {
private hand
SinglePair(PokerHand hand) {
this.hand = hand
}
boolean isValid() {
// iterate over the cards and return true if it contains a single pair
}
Category getCategory() {
Category.SINGLE_PAIR
}
int compareTo(SinglePair otherSinglePair) {
// for this implementation we just need to figure out which pair is highest, or if they're the same,
// who has the highest "other" card
}
}
where Category is an enum that encapsulates the ranking of the cateogries
enum Category {
private int value
HIGH_CARD(1), SINGLE_PAIR(2), TWO_PAIRS(3),
Category(int value) {
this.value = valuee
}
int getCategoryRank() {
this.value
}
}
and then we have a factory class that returns the correct HandCategory implementation for a PokerHand
@Singleton
class HandCategoryFactory {
HandCategory getHandCategory(PokerHand hand) {
// starting with the highest category implementation class (straight flush) find the first class for which
// isValid return true
HandCategory handCategory = new StraightFlush(hand)
if (handCategory.isValid()) {
return handCategory
}
// etc.
}
}
So now that we have a HandCategory for each hand, the process of comparing them is very simple
HandCategory player = // get from factory
HandCategory opponent = // get from factory
int playerCategoryRank = player.getCategory().getCategoryRank()
int opponentCategoryRank = opponent.getCategory().getCategoryRank()
int handResult
if (playerCategoryRank != opponentCategoryRank) {
handResult = playerCategoryRank.compareTo(opponentCategoryRank)
} else {
// they're in the same category, e.g. both players have 2 pairs
handResult = player.compareTo(oppenent)
}