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.
Comparing a full house looks like this:
- Compare the triplets of both hands. Highest triplet wins.
- If they are both the same, compare the pairs of both hands. Highest pair wins.
- 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:
Second order: You could have a “2-3” full house, where the pair is the higher value and the triplet is lower.
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:
- Start with the highest value card, ace, and replace one wild in the
cardValues
with that. - If the other value in the array is also a wild, replace that one with a king.
- 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 hadcardValues
: [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
Player 2
Player 3
If you have any questions about anything in this article, please let me know at cartrell@gameplaycoder.com.
Thanks and take care,
– C. out.