Skip to content

Instantly share code, notes, and snippets.

@donalmurtagh
Last active January 19, 2021 14:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save donalmurtagh/0ef9af5457030ee4acdff1157143e001 to your computer and use it in GitHub Desktop.
Save donalmurtagh/0ef9af5457030ee4acdff1157143e001 to your computer and use it in GitHub Desktop.

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

  1. Figure out which category (pair, 2 pairs, flush, straight, etc.) each hand belongs to
  2. If they're in different categories, the hand in the higher category wins
  3. 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)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment