How to Code Poker Hands – Two Pair

Hey! What’s up.

Today, we’ll be resuming in the mini-series of writing code that can tell what kind of poker hand a player has. And the poker hand we’re covering is a two pair.

  • Pair (jacks or higher only)
  • Two pair
  • Three of a kind
  • Straight
  • Flush
  • Full house
  • Four of a kind
  • Straight flush (a non-ace-high straight flush)
  • Royal flush (an ace-high straight flush)

A two pair is a hand that has two cards of one value, two more cards of another value, and a third card whose value is different than the first four. Here is an example the a two pair hand:


We have a pair of kings and sixes.
Setup

If you’d like to see the first article, coding a pair of Jacks or higher, you can check that out here. There, you’ll also a detailed description of the data structures used. But here is a quick rundown of those data structures:

Card values
CardValues = {
  two: 2,
  three: 3,
  four: 4,
  five: 5,
  six: 6,
  seven: 7,
  eight: 8,
  nine: 9,
  ten: 10,
  jack: 11,
  queen: 12,
  king: 13,
  ace: 14,
  wild: 100
};
Card suits
CardSuits = {
  hearts: 1,
  diamonds: 2,
  clubs: 3,
  spades: 4
};
Card
Card = function(value, suit) {
  this.value = value;
  this.suit = suit;
};
Hand

And a hand is an array of Card objects:

var hand = [
  new Card([card value 1], [card suit 1]),
  new Card([card value 2], [card suit 2]),
  ...
  new Card([card value 5], [card suit 5])
];
Writing The Code To Identify A Two Pair

When looking for a two pair, it’s also very helpful if we first sort the cards by their value (rank), in descending order. We previously defined a “utilities” file, CardMatchUtils.js, and added a function to it called, CardMatchUtils.SortCardsByDescendingValue, to help with that.

We’re also using the “wild card”, which is a card that can assume the value of any card. So, the following hand would also qualify as a two pair:

In this image, we have a pair of sixes, and because we have a wild card, we take the highest non-paired card, in this case a king, and pair the wild with that. So, we have a pair of kings.

The main function of our pseudocode looks like this:

TwoPair
TwoPair = FUNCTION(hand) {
  SORT the hand by descending card value and store in a variable called sortedHand
  SET wildsInfo to an empty object
  ADD a PROPERTY numWilds to wildsInfo and set it to 0
  ADD a PROPERTY startIndex to wildsInfo and set it to 0
  
  IF CardsHaveSameValue(sortedHand, 2, wildsInfo) AND
  CardsHaveSameValue(sortedHand, 2, wildsInfo)
    //we have two pairs!
    RETURN TRUE 
    
  //no two pair in this hand
  RETURN FALSE
}

That’s it… not so fast! What’s this CardsHaveSameValue function we’ve never seen before? 🤔

This is a new utility to our CardMatchUtils.js file. Let’s officially call this CardMatchUtils.DoCardsHaveSameValue. This function will determine if a hand has at a certain number of cards that have the same arbitrary value.

This function accepts three parameters:

  • sortedHand – Array of Card objects that are already sorted in descending value.
  • numToMatch – An integer that indicates how many cards whose value we are looking to match. In our case, it’s two.
  • wildsInfo – An object that will allow us to save data for subsequent calls to this DoCardsHaveSameValue function. From our code above, we called CardsHaveSameValue twice, passing in wildsInfo each time. The first call needs to save certain intermittent data so the next call can resume where the first one left off. The wildsInfo parameter has two properties:
    • numWilds – The number of wild cards available for use as substitutes.
    • startIndex – The index of the sortedHand array on which DoCardsHaveSameValue starts when it checks each card in the hand.

The wildsInfo paramater is only needed if your game supports wild cards. Otherwise, you can set it to null (or don’t specify it, if the programming language you’re using supports some form of optional arguments like JavaScript or C#).

CardMatchUtils.DoCardsHaveSameValue will return true if the specified number of cards have the same value, or false otherwise.

DoCardsHaveSameValue
CardMatchUtils.DoCardsHaveSameValue = function(sortedHand, numToMatch, wildsInfo) {
  SET numWilds to 0
  SET startIndex to 0
  
  IF wildsInfo is specified
    SET numWilds to wildsInfo.numWilds
    IF numWilds is 0
      count the number of wild cards in the hand, and set this value to numWilds
    END IF
    SET startIndex to wildsInfo.startIndex
  ELSE
    count the number of wild cards in the hand, and set this value to numWilds
  END IF
  
  SET maxIndex to sortedHand.length - numWilds - 1
  SET baseCardValue to 0
  SET numMatched to 0
  
  LOOP through each card in the sortedHand array, starting at index startIndex
    IF it's the first card in the loop
      //first card starts off the number of matches with a base card value
      SET baseCardValue to the card's value
      SET numMatched to 1
      CONTINUE with next card in the loop
    END IF
    
    IF the baseCardValue EQUALS the card's value
      //this card's value matches the base card value
      ADD 1 to the current value of numMatched
      
      IF numMatched EQUALS numToMatch
        //total number of matched cards found - success
        IF wildsInfo is specified
          SET PROPERTY wildsInfo.numWilds to numWilds
          SET PROPERTY wildsInfo.startIndex to the current loop index + 1
        END IF
        RETURN TRUE
      END IF
      
      //still need to match more cards for the base card value
      CONTINUE with next card in the loop
    END IF
    
    //This card's value does not match the base card value. Check if there are enough wilds that can satisfy the match.
    
    IF numMatched + numWilds is GREATER THAN OR EQUALS numToMatch
      //there are enough wilds that can satisfy the base card value - success
    
      //deduct the number of wilds used to satisfy the base card value from the current number of wild cards
      SET numberOfWildsToDeduct to numToMatch - numMatched
      DEDUCT numberOfWildsToDeduct from numWilds
      
      //update the wilds info
      IF wildsInfo is specified
        SET PROPERTY wildsInfo.numWilds to numWilds
        SET PROPERTY wildsInfo.startIndex to the current loop index
      END IF
      
      RETURN TRUE
    END IF
    
    //If we arrive here, there are not enough wild cards to satisfy the base card value.
    
    //start a new base card value with the current card that did not match
    SET baseCardValue to the value of the card
    
    IF the card is a wild card
      //the base card value can't be a wild card - abort the for loop
      END LOOP
    END IF
    
    SET numMatched to 1
  END LOOP
  
  //unable to satisfy a match - however, one last attempt, if there are remaining wilds, check if number of matched cards on the last loop + num wilds satify
  IF numMatched + numWilds GREATER THAN OR EQUALS numToMatch
    //there are enough wilds that can satisfy the base card value - success!
    
    //deduct the number of wilds used to satisfy the base card value from the current number of wild cards
    SET numberOfWildsToDeduct to numToMatch - numMatched
    DEDUCT numberOfWildsToDeduct from numWilds
    
    //update the wilds info
    IF wildsInfo is specified
      SET PROPERTY wildsInfo.numWilds to numWilds
      SET PROPERTY wildsInfo.startIndex to the current loop index
    END IF
    
    RETURN TRUE
  END IF
    
  //if we arrive here, we were unable to satisfy a match
  RETURN FALSE
}

You can see that if wildsInfo is specified, its properties are updated for subsequent calls to CardMatchUtils.DoCardsHaveSameValue.

Now, let’s have another look at our previous hand with a wild card in it:

We first sort the cards by descending value, so the sorted hand looks like:

The wild cards are always sorted last.

Note: The order of cards by is are arbitrary in this case. The 6c and 6h cards could have been swapped.

Recall that of TwoPair function calls CardMatchUtils.DoCardsHaveSameValue twice, specifying the samewildsInfo parameter each time.

The first time it’s called, the pair of sixes was found. When CardMatchUtils.DoCardsHaveSameValue completes, it will return true, because it found a pair of kings. When the code doesn’t find a match, it will first try to use as many wilds available to satisy the match. In this hand, there is one wild, so it was used. The wildsInfo object was modified as such:

{
  numWilds => 0
  startIndex => 1
}

The next time CardMatchUtils.DoCardsHaveSameValue is called, instead of starting at the first index (index 0, the KH) in the array, it will start at index 1, the six of clubs. It will find two cards of the same value, the 6C, and 6H, and return true. Since both calls to CardMatchUtils.DoCardsHaveSameValue returned true, this hand does indeed contain two pairs.

If you have any questions, contact me by using the contact form here, or you can e-mail me directly at cartrell@gameplaycoder.com.

And of course, if you have a card game you need help coding, get in touch with me, and let’s talk!

That’s all for now. In the next article, we’ll go over the poker hand, three of a kind.

Thanks, and I’ll talk to you next time. Take care,

– C. out.