How to Code Poker Hands – Comparing Hands For A Full House

Continuing the series of comparing poker hands of the same rank, this article will show you how to write code to compare two hands that are both a full house.

In a previous article for poker hands, you learned how to write code that checks if a hand is a full house. That is, the hand contains three cards of one value, and two of another, and the suits are not all the same.

Three cards are nines, two cards are fours, and their suits are not uniform.

Comparing a full house looks like this:

  1. Compare the triplets of both hands. Highest triplet wins.
  2. If they are both the same, compare the pairs of both hands. Highest pair wins.
  3. Both hands have equal triplets and pairs. They’re tied.

Getting Triplet And Pair Values

Before we can compare triplets and pairs, we need to get the values of the cards that make up the triplets and pairs.

Let’s first have a look at the cards in hand, because after being sorted in descending value, they’ll have one of two orders.

Note: Make sure that the cards are sorted by card rank in descending order (highest to lowest) first.

First order: You could have – what we’ll call a “3-2” full house – where the higher value is the triplet and the lower value is the pair, as in:

The value of the triplet is 10, and the value of the pair is 3.

Second order: You could have a “2-3” full house, where the pair is the higher value and the triplet is lower.

This time they’re switched. The value of the pair is 10, and the value of the triplet is 3.

To determine the triplet and pair values, compare the values of second and third card of the hand. 💡

In the 3-2 full house, 10♦ 10♣ 10♠ 3♥ 3♦, the values of the second and third card will be the same. In this case, they’re both 10. That means the value pf the triplet is 3. From this, the pair starts on the fourth card, so the value of the pair is the value of that fourth card (in this case, 2).

In the 2-3 full house, 10♦ 10♣ 3♥ 3♦ 3♠, the values of the second and third card will be different. Here, the value of the triplet is 2, and the value of the pair is 10.

Now that you know the values of the triplets, you can compare them. In the example we’ve been using 10 > 3, so the 3-2 hand wins over the 2-3 hand.

And if the values of the triplets were the same, then you’d compare the values of the pairs to determine the higher hand. And if the pairs were the same, both hands are of equal rank.

Setup

Note: The first stages of the setup can be found on the introduction page to comparing poker hands, here.

There aren’t any other specific preparations we need before we begin.

Writing The Code For Comparing Two Full Houses

When both hands are full houses, the GetWinningPlayerId function will eventually call a the FindWinnerFullHouse function that compares them to determine which one wins.

FindWinnerFullHouse
FindWinnerFullHouse = FUNCTION(hand1, hand2)
  SET workingHand1 = CardMatchUtils.SortCardsByDescendingValue(hand1)
  SET workingHand2 = CardMatchUtils.SortCardsByDescendingValue(hand2)

  SET trioPairValues1 = GetTrioPairValues(workingHand1)
  SET trioPairValues2 = GetTrioPairValues(workingHand2)

  SET trioValue1 = trioPairValues1[0]
  SET trioValue2 = trioPairValues2[0]
  IF (trioValue1 > trioValue2)
    RETURN 0
  ELSE IF (trioValue1 < trioValue2)
    RETURN 1
  END

  SET pairValue1 = trioPairValues1[1]
  SET pairValue2 = trioPairValues2[1]
  IF (pairValue1 > pairValue2)
    RETURN 0
  ELSE IF (pairValue1 < pairValue2)
    RETURN 1
  END

  RETURN -1
END
GetTrioPairValues
GetTrioPairValues = FUNCTION(hand)
  SET secondCardValue = hand[1].value;
  SET thirdCardValue = hand[2].value;

  IF secondCardValue EQUALS thirdCardValue
    SET fourthCardValue = hand[3].value;
    RETURN [ secondCardValue, fourthCardValue ]
  END

  RETURN [ thirdCardValue, secondCardValue ]
END

In the code above, first we sort both hands by card rank in descending order. Next, we call a new function, GetTrioPairValues, which will tell us the values of the pairs and triplets of both hands. The value that GetTrioPairValues returns is an array that contains two elements: first is the value of the triplet, second is the value of the pair.

Next, the code compares the values of the triplets. If a winner is found, it returns the winning player index (0 for the hand 1, or 1 for hand 2). Otherwise, it compare pairs, and again returning the winning player index if a winner is found. And finally, if the pairs are equal, it returns -1, meaning both hands are evenly matched.

That’s it! This one was easy! 😁

.. Whooaaa, hold on a minute chief. What about the wild cards? 😒

Ugh! Them damn wild cards again! Shit! 😅 Well, we’ll handle those next.

Comparing Two Full House Hands With Wild Cards

If a hand has wild cards, the would assume values that would create the best full house possible. If one or more wild cards are in the hand, the above logic, about comparing the second and third cards in the hand, will not work, because the hand won’t have both a triplet and a pair.

We can restore that logic by first replacing the wilds with actual card values. The first step to this is using our handy CardMatchUtils.DoCardsHaveSameValue function.

We’ve used this function many times before. It will tell us if a card with a certain value appears in the hand a specified number of times. Also, if wild cards are in the hand, they can assume said card’s value in order to help satisfy the count. The function returns true if the card was found in the hand the specified number of times. Lastly, the function tracks the values of those cards that match the specified count.

We’ve made some updates to the function since it was first introduced. And we’ll make some new changes here to accommodate wild cards.

DoCardsHaveSameValue
CardMatchUtils.DoCardsHaveSameValue = FUNCTION(sortedHand, numToMatch, wildsInfo)
  SET numWilds to 0
  SET startIndex to 0
  SET cardValues to empty array []

  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
    SET startIndex to wildsInfo.startIndex
    SET cardValues to wildsInfo.cardValues
  ELSE
    count the number of wild cards in the hand, and set this value to numWilds
  END

  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
      IF the card is a wild card
        //first card is a wild card - the only way the first card would be a wild is if all cards
        // starting at the start index are wilds (assuming cards are already sorted in descending 
        // value order, with wilds at the end)

        //the hand must contain at least as many wilds as the requested number of cards to match
        IF (u_numWilds LESS THAN u_numToMatch)
          RETURN FALSE
        END

        IF wildsInfo is specified
          SET PROPERTY wildsInfo.numWilds to numWilds - numToMatch
          SET PROPERTY wildsInfo.startIndex to [index of card within loop] + numToMatch;

          ADD card's value into cardValues array
          SET PROPERTY wildsInfo.cardValues to cardValues
        END
        RETURN TRUE
      ELSE
        //first card starts off the number of matches with a base card value
        SET baseCardValue to the card's value
      END

      SET numMatched to 1
      CONTINUE with next card in the loop
    END

    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

          ADD card's value into cardValues array
          SET PROPERTY wildsInfo.cardValues to cardValues
        END
        RETURN TRUE
      END

      //still need to match more cards for the base card value
      CONTINUE with next card in the loop
    END

    //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

        ADD baseCardValue into cardValues array
        SET PROPERTY wildsInfo.cardValues to cardValues
      END

      RETURN TRUE
    END

    //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

    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

      IF baseCardValue NOT EQUAL 0
        ADD baseCardValue value into cardValues array
      ELSE
        ADD wild card value (CardValues.wild) into cardValues array
      END

      SET PROPERTY wildsInfo.cardValues to cardValues
    END

    RETURN TRUE
  END

  //if we arrive here, we were unable to satisfy a match
  RETURN FALSE
END

In a nutshell, this function now handles what happens if it encounters a wild card as the first card it checks, and that if only wild cards were processed, the cardValues array will specify the wild card value to let us know.

Note: Just like when you determined if a card was a full house, you’ll need to call the CardMatchUtils.DoCardsHaveSameValue function twice, once to look for the triplet, and again for the pair, as in a 3-2 full house. If you don’t get successful calls both times, you’ll then need to check for a 2-3 full house. You can find details of this on the original full house-matching article here.

If you’re checking for a 3-2 full house, you’d write something like this:

SET info to an empty object { };
IF CardMatchUtils.DoCardsHaveSameValue(hand, 3, info) AND CardMatchUtils.DoCardsHaveSameValue(hand, 2, info))
  (we have a 3-2 full house)
END

And for a 2-3 full house:

SET info to an empty object { };
IF CardMatchUtils.DoCardsHaveSameValue(hand, 2, info) AND CardMatchUtils.DoCardsHaveSameValue(hand, 3, info))
  (we have a 2-3 full house)
END

Here are five examples of some hands encountered what the cardValues array will include, and the intended resulting hands are.

Example 1
Hand: 8-8-7-7-w (“w” is a wild card, and suits don’t matter in a full house)
Becomes: 8-8-(8)-7-7
The cardValues array would be [8, 7]
This would end up being a 3-2 full house, as the wild assumes the third eight.

Example 2
Hand: 8-8-7-w-w
Becomes: 8-8-(8)-7-(7)
cardValues: [8, 7]
he first DoCardsHaveSameValue call will substitute one of the wilds as the eight, satisfying the triplet. On the second call, the other wild is used to satisfy a pair of sevens, qualifying as a 3-2 full house.

Example 3
Hand: 8-7-w-w-w
Becomes: 8-(8)-(8)-7-(7)
cardValues: [8, 7]
imilar to the last example, but the first DoCardsHaveSameValue substituted two eights to satisfy the triplet.

Example 4
Hand: 8-w-w-w-w
Becomes: (A)-(A)-(A)-8-(8)
cardValues: [8, w]
A little tricky one here (:
Normally, this hand would become 8-(8)-(8)-(A)-(A), because the eight was encountered first, so and there are enough wilds to satisfy the triplet for a 3-2. However, 8-8-8-A-A is not the best hand that can be formed, because we also have enough wilds to form triple aces (which is the highest triplet possible).

That’s where having the DoCardsHaveSameValue function put a “wild card value” in the cardValues array, as you can see in the second call. Later on in this article, we’ll deal with this when we start replacing wilds with actual card values. Hang tight for now 😉

Example 5
Hand: w-w-w-w-w
Becomes: (A)-(A)-(A)-(K)-(K)
cardValues: [w, w]
Wow! 😮 The DoCardsHaveSameValue function gives us two wild card values in its cardValues array for a 3-2. With all wilds, we substitute the highest cards possible: a trio of aces and a pair of kings. Like the last example, there’s a bit of substitution going on here, in both the hand, and the card values, which I’ll show you how to handle in this article.

Setting Up The cardValues For Substitutions Of Wilds

Now that we have a triplet and pair value in the cardValues array, we can begin handling the situations where wilds are in the hand.

But first, if the cardValues array itself contains wild cards, as in examples 4 and 5, we must first replace those with non-wild card values before we can replace those in the hand.

There are two steps to do this:

  1. Start with the highest value card, ace, and replace one wild in the cardValues with that.
  2. If the other value in the array is also a wild, replace that one with a king.
  3. Sort the contents of the new cardValues in descending order of value.

So, let’s have a look at example 4.
cardValues: [8, w]
We’d replace the wild with an ace, and the array looks like:
[8, A]
Then after sorting in descending order of value it now looks like:
[A, 8]

In example 5, we had
cardValues: [w, w]
We’d replace the wild with an ace, and the array looks like:
[A, w]
Then, replace the second wild with a king to get
[A, K]
They are already properly sorted.

Some code for this function, looks like:

WildsAssumeInfoCardValues
WildsAssumeInfoCardValues = FUNCTION(cardValues)
  SET replaceValue to CardValues.ace

  IF cardValues[0] EQUALS CardValues.wild
    SET cardValues[0] to replaceValue
    SET replaceValue to CardValues.king (or subtract 1)
  END

  IF cardValues[1] EQUALS CardValues.wild
    SET cardValues[1] to replaceValue
  END

  sort cardValues in descending order
END

What this WildsAssumeInfoCardValues does is start with a “replacing value” of ace. Then, every time it encounters a wild value in the cardValues array, it replaces that value with the value of replaceValue. If it’s the first card in the array, it also sets the replacing value to king, so that if the second card is also a wild, it would be replaced with a king instead of an ace.

Replacing Wilds In The Hand

Nooooww!

We’re finally ready to replace the wilds in the hand with values from the cardValues array!

What we’re doing here is first starting with the first value in the cardValues array (triplet), and replace, up to the number of replacements necessary, wilds with that card value.

Then, we do the same for the second value in the cardValues array for the pair.

Let’s dive in. 😏

WildsAssumeCardValues
WildsAssumeCardValues = FUNCTION(hand, cardValues)
  SET numWilds TO CardMatchUtils.CountCardsByValue(hand, CardValues.wild)

  (handle triplet)
  SET cardValue TO cardValues[0]
  SET numCardsWithValue TO CardMatchUtils.CountCardsByValue(hand, cardValue)
  SET numCardsToMatch TO 3
  SET numWildsToReplace TO numCardsToMatch - numCardsWithValue
  IF numWildsToReplace LESS THAN OR EQUAL TO 0
    (skip the rest of handling triplet and move on to "handle pair"
  END

  SET cards TO (make a copy of the cards in the hand)
  FOR EACH card IN cards
    IF the card is a wild card
      replace that value of the card with cardValue
      decrease numWilds by 1
      IF numWilds EQUALS 0
        RETURN (we're done; no more wilds to replace)
      END
    END
  END

  (handle pair)
  SET cardValue TO cardValues[1]
  SET numCardsWithValue TO CardMatchUtils.CountCardsByValue(hand, cardValue)
  SET numCardsToMatch TO 2
  SET numWildsToReplace TO numCardsToMatch - numCardsWithValue
  IF numWildsToReplace LESS THAN OR EQUAL TO 0
    RETURN (we're done; no wilds to replace)
  END

  SET cards TO (make a copy of the cards in the hand)
  FOR EACH card IN cards
    IF the card is a wild card
      replace that value of the card with cardValue
      decrease numWilds by 1
      IF numWilds EQUALS 0
        RETURN (we're done; no mre wilds to replace)
      END
    END
  END

  sort cards by in order of descending card value
  RETURN cards
END

This function replaces wilds in the hand with values specified in the cardValues array, until it runs out of wilds in the hand. Triplets are handled first, getting the higher value of the cardValues array. Then if there are any wilds left, the pair is handled.

Coming Full Circle

If you’re still with me, than great job getting this far! (muscle arm emote)

Now that we’ve removed all wilds in the hand, you can go back and use the GetTrioPairValues to get the values of the triplets and pairs, and finally compare triplets and pairs to determine which full house pair wins.

You’ve reached the end for comparing full houses! No, for real this time, that’s it. 😐

Compare Your Own Hands

You can use the controls below to build your own hands and compare full houses. Have fun playing around with it!


Player 1

Result:

Player 2

Result:

Player 3

Result:

Who Won:

If you have any questions about anything in this article, please let me know at cartrell@gameplaycoder.com.

Thanks and take care,

– C. out.