When you have two poker hands, and both are straight flushes, this article will show you the code that compares them to find which one wins.
A previous article for poker hands demonstrated how to compare a hand to determine if it was straight flush (the article also covered a royal flush as well). A straight flush is a hand where all the cards are in sequential order, and they all have the same suit. This hand is a straight flush:
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 Fours Of Kinds
When two hands that are both a straight flush, the GetWinningHand function will call the FindWinnerStraightFlush function that compares the two hands.
Note: As it turns out, comparing two straight flush hands is the same as comparing two straight hands! The only addition is that you have to make sure all the cards are the same suit.
The only code featured in this article are the functions specific to comparing straight flushes. To see the concepts and code for comparing two straights, see this article.
FindWinnerStraightFlush
FindWinnerStraightFlush = function(hand1, hand2) {
SET workingHand1 = CardMatchUtils.SortCardsByDescendingValue(hand1);
SET hand1Info to an empty object { }
CardMatchUtils.AreCardsStraight(workingHand1, hand1Info)
SET workingHand1 = WildsAssumeValues(workingHand1, hand1Info)
SET sortedHand2 = CardMatchUtils.SortCardsByDescendingValue(hand2);
SET hand2Info to an empty object { }
CardMatchUtils.AreCardsStraight(workingHand2, hand2Info)
SET workingHand2 = WildsAssumeValues(workingHand2, hand2Info)
SET winningPlayerIndex = CardMatchUtils.CompareHands(workingHand1, workingHand2)
RETURN winningPlayerIndex
}
WildsAssumeValues
WildsAssumeValues = function(hand, info) {
SET index to 0
WHILE index IS LESS THAN number of cards in the hand (for example, "hand.length")
SET card = hand[index] (get the nth card in hand)
IF the card is a wild (card.value EQUALS CardValues.wild)
SET the card value to the last value in the info.cardValues array
REMOVE the last card value from the info.cardValues array (info.cardValues.pop())
END
SET index = index + 1
END
SET sortedHand to CardMatchUtils.SortCardsByDescendingValue(hand)
RETURN sortedHand
}
Compare Your Own Hands
You can use the controls below to build your own hands and compare fours of kinds. Have fun playing around with it!
Player 1
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Player 2
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Player 3
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Who Won:
If you have any questions about anything in this article, please let me know at cartrell@gameplaycoder.com.
When you have two poker hands, and both are a four of a kind, how can you determine which one ranks higher? In this article, you’ll learn how to code a solution.
A previous article for poker hands demonstrated how to compare a hand to determine if it was four of a kind. A four of a kind is hand where four of the cards are the same value, and the remaining card is a different value. It’s like a three of a kind, but instead of matching three cards, it matches four. Here’s an example of a four of a kind:
Also, the comparison process is very similar to a comparing threes of kinds:
Compare the values of the quadruplet (the four cards that have the same value).
If those values are equal, compare the values of other the kickers, which is the card that has the other value.
If no kicker breaks the tie, and all cards have been compared, then both hands are equal.
Let’s look at some examples:
Hand 1
Hand 2
Hand 1 has a quad value of 5, while hand 2 has a quad value of 3. Since 5 is greater than 3, hand 1 is the higher four of a kind.
If the quad values of both hands are the same, then you compare the kicker card. Check this out:
Hand 1
Hand 2
Both hands had a quad value of queen. Hand 1 has a kicker value of king, while hand 2’s kicker value is ace. Ace beats king, so hand 2 is the winner here.
And one more thing before we get into the code – the wild cards (:
But handling wild cards in comparing a four of a kind is similar to that of a three of a kind. Take these hands:
Hand 1
Hand 2
In hand 1, the wild card is swapped for a 2 to form a four of a kind. The kicker value is a queen. For hand 2, it already has a four of a kind from the twos, so you can use the wild card to substitute the highest possible value, an ace.
When comparing both hands, hand 2 wins, because it has the higher kicker value (ace winning over queen).
Note: In hand 1, you could’ve substituted also the wild with the highest possible value, ace. But then, it would no not form a four of a kind, but a three of a kind. You also could’ve substituted it with another queen to form a full house, twos over queens, but a full house ranks lower than a four of a kind. So, substituting the wild for as a two produces the highest possible hand.
On a side note, in hand 2, you could’ve substituted the wild as a two, forming a five of a kind, which ranks higher than a four of a kind. However, we won’t be covering fives of kinds in this series. I’ll leave it as a challenge to you, should you accept it (: If you’re interested, you can learn a little more about a five of a kind here.
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 Fours Of Kinds
When two hands are both a three of a kind, the GetWinningHand function will call a function that compares two hands of said poker hand.
In this case, GetWinningHand function will eventually call FindWinnerFourOfAKind (shown below) to compare the hands. This function accepts two parameters, the hand for both players, and it’ll return the ID of the player who has the winning hand. If both hands are equal, it’ll return 0 (which we’ll use to indicate a draw). The pseudocode below starts by comparing the values of the pairs first, then comparing the kickers if necessary.
FindWinnerFourOfAKind
FindWinnerFourOfAKind = function(hand1, hand2) {
sortedHand1 = CardMatchUtils.SortCardsByDescendingValue(hand1);
SET hand1Info to an empty object { }
CardMatchUtils.DoCardsHaveSameValue(hand1, 4, hand1Info);
sortedHand2 = CardMatchUtils.SortCardsByDescendingValue(hand2);
SET hand2Info to an empty object { }
CardMatchUtils.DoCardsHaveSameValue(hand2, 4, hand2Info);
SET winningIndex = CompareQuads(hand1, hand1Info, hand2, hand2Info);
IF (winningIndex NOT EQUAL TO -1)
RETURN winningIndex (one hand's quad outranks the other hand's, and no further checking is necessary)
END
(both hands have the same ranking quad, now compare the kickers of both hands)
SET winningIndex = CompareKickers(hand1, hand1Info, hand2, hand2Info);
RETURN winningIndex;
}
Like most poker hand matching and comparing functions, you’ll need to first sort the cards in descending order of value (highest to lowest) before processing. This helps tremendously in the code. Yeah, you and I could just “look” at a couple hands and see the winner, but code? Not so much. 🙃
If you already read the article for comparing threes of kinds, this function looks very similar to FindWinnerThreeKind!
(Psst, here’s the big secret! 🐱👤 You catch a break with comparing fours of kinds. It’s mostly a copy-paste job, changing threes to fours, and replacing “trios” with “quads”)
Comparing The Quadruplets
In the FindWinnerFourOfAKind function, the code above sets the hands up for comparing their quadruplets. It then sorts the cards or descending order by card value. Next, it uses the DoCardsHaveSameValue function to get the four cards in the hand that make the quad, as well as determine the quad’s value.
CompareQuads
CompareQuads = function(hand1, hand1Info, hand2, hand2Info) {
SET hand1WorkingQuadValue = hand1Info.cardValues[0]
IF (CardMatchUtils.CountCardsByValue(hand1, WILD_VALUE) GREATER OR EQUALS 4)
hand1WorkingPairValue = ACE_VALUE
END
SET hand2WorkingQuadValue = hand2Info.cardValues[0]
IF (CardMatchUtils.CountCardsByValue(hand2, WILD_VALUE) GREATER OR EQUALS 4)
hand2WorkingQuadValue = ACE_VALUE
END
IF (hand1WorkingQuadValue > hand2WorkingQuadValue)
RETURN 0 (hand 1 has the higher ranking quad)
ELSE IF (hand1WorkingQuadValue < hand2WorkingQuadValue)
RETURN 1 (hand 2 has the higher ranking quad)
END
RETURN -1 (both hands' quads have the same value)
}
This function is very similar to the CompareTrios function in our recent article for comparing threes of kinds, except instead of dealing with three cards, we’re dealing with four. If you’d like details on the workings of that function, please check here.
Comparing The Kickers
If the quads of both hands have the same value, then you’ll need to compare the final card in each hand, its kicker.
Like you did when comparing the kickers with previous poker hands, when comparing the kickers, you first remove the quads from both hands so you’re left with the remaining kicker. You can use the CardMatchUtils.BuildHandExcludingValues function to remove the quad.
GetKickers
GetKickers = function(hand, info) {
(get the value of the cards that form the quad)
SET quadCardValue = info.cardValues[0]
(count the number of cards in the hand that match the quad card value)
SET numQuadValueCards = CardMatchUtils.CountCardsByValue(hand, quadCardValue)
(if there are at least as many quad value cards as there are non-kicker cards, specify the quad card value to the values of cards to exclude)
SET numNonKickerCards = 4
IF numQuadValueCards >= numNonKickerCards
SET valuesToExclude = quadCardValue
ELSE {
(otherwise, if there are at least as many wild cards as there are non-kicker cards, add the wild card value to the values of cards to exclude)
SET numWildCards = CardMatchUtils.CountCardsByValue(hand, CardValues.WILD)
IF numWildCards >= numNonKickerCards
SET valuesToExclude = CardValues.WILD
ELSE
(finally, specify BOTH, the quad card value and the wild card value as the values of cards to exclude)
SET valuesToExclude = [ CardValues.WILD, quadCardValue ]
END
}
(create the temporary kickers hand by excluding the specified values and returning the rest)
SET handOfKickers = CardMatchUtils.BuildHandExcludingValues(hand, valuesToExclude, numNonKickerCards)
(finally, sort the kickers hand in descending order, with wilds as the highest value)
handOfKickers = CardMatchUtils.SortCardsByDescendingValueHighWilds(handOfKickers)
RETURN handOfKickers
}
In the GetKickers above, the info object is the same one used in FindWinnerFourKind. It’s either the hand1Info or hand2Info object, depending on which hand you’re getting the kickers from.
There are three situations in GetKickers that determine which values of cards to exclude as kickers.
The first is the simplest. It’s the quad card value used to form the four of a kind. Cards of this value obviously can’t be the kickers. This means they’ll be excluded, leaving the remaining card as the kicker.
The second situation is a hand that contains at least four wilds cards. These cards can assume the highest non-wild value, which is an ace. So the four wilds would form the four of a kind, using an ace as the quad card value. So the wild card value itself would be excluded from the hand of kickers.
Finally, the hand doesn’t have four cards with the same value, but it does contain one of the following combinations:
One wild and a triplet
Two wilds and a pair
Three wilds and the higher non-kicker of the remaining two cards
Note: When excluding cards, you’re always excluding exactly four cards (the number of non-kicker cards).
Those wilds will assume the value of the whatever the quad value is, forming the four of a kind. In this situation, you want to exclude both values of both, the wild card, and the quad card value.
The GetKickers function from above helps with this.
CompareKickers
CompareKickers = function(hand1, hand1Info, hand2, hand2Info) {
SET hand1Kickers = GetKickers(hand1, hand1Info)
SET hand2Kickers = GetKickers(hand2, hand2Info)
SET winningPlayerIndex = CardMatchUtils.CompareHands(hand1Kickers, hand2Kickers)
RETURN winningPlayerIndex
}
The CardMatchUtils.CompareHands function is the same one we used here.
The CompareKickers will return 0 if hand1 has the better kickers, 1 if hand2 has the better kickers, or -1 if both hands are the same rank.
That’s pretty much it! 😎
Compare Your Own Hands
You can use the controls below to build your own hands and compare fours of kinds. Have fun playing around with it!
Player 1
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Player 2
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Player 3
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Who Won:
If you have any questions about anything in this article, please let me know at cartrell@gameplaycoder.com.
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:
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:
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:
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 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
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Player 2
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Player 3
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Who Won:
If you have any questions about anything in this article, please let me know at cartrell@gameplaycoder.com.
Continuing the series of comparing poker hands of the same rank, this article will show you how to write code to compare two flushes to see which ranks higher.
In a previous article for poker hands, you saw how to check a hand to determine if a it’s a flush. That is, all five of its cards are the same suit, and their values are not in sequential order.
Each card is diamonds, and they are not all in sequential order.
Comparing two flush hands is a bit easier than the others we’ve covered so far. You need to perform these three steps:
Temporarily replace all wilds with aces.
Sort cards in hand by descending value.
Compare cards in both hands.
And we’ve performed these tasks before, so let’s get started!
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 Flushes
When both hands are flushes, the GetWinningPlayerId function will eventually call a the FindWinnerFlush function that compares them to determine which one wins.
Let’s have a look at that function.
FindWinnerFlush
FindWinnerFlush = function(hand1, hand2) {
SET workingHand1 = CopyHand(hand1)
ReplaceWildsWithAces(workingHand1)
SET workingHand1 = CardMatchUtils.SortCardsByDescendingValue(workingHand1)
SET workingHand2 = CopyHand(hand2)
ReplaceWildsWithAces(workingHand2)
SET workingHand2 = CardMatchUtils.SortCardsByDescendingValue(workingHand2)
SET winningPlayerIndex = CardMatchUtils.CompareHands(workingHand1, workingHand2)
RETURN winningPlayerIndex
}
Let’s go over the three steps in more detail.
STEP 1: Temporarily Replace All Wilds With Aces
First, you want to replace any wild cards in the hand with aces. Although a Flush is a hand where all cards are the same suit, if we’re comparing two flushes, the cards’ values now play a factor. So wilds can be replaced with aces to give the highest possible hand value. Also remember, wilds can assume any suit as well as any value, so the condition of the flush is still met.
Say, you had this hand:
That one wild card would be replaced with an ace:
Note: Wilds, as covered in this series, and for the sake of keeping the pseudo code relatively simple when wilds are involved, have no restrictions on the actual card suits and values they can replace. As you can see in the substitution in the above image, it contains two ad cards. If you’d like more official rulings on wilds, please have a look at this Wiki.
Since the card values are being altered, we don’t want to modify the original hands (hand1 and hand2 from above). So, first, you need to make a copy of the hand. You’ll then do all your work and comparing on this “working hand”.
CopyHand
CopyHand = function(hand) {
SET copyHand = new Array()
FOR EACH card in hand
(create a copy of the card)
SET copyCard = new Card(card.value, card.suit)
(add the copied card to the copy hand)
copyHand.push(copyCard)
END
RETURN copyHand
}
Now that you have a copy of all cards in the hand, let’s have a look at the psuedo code that replaces wilds with aces.
ReplaceWildsWithAces
ReplaceWildsWithAces = function(hand) {
FOR EACH card in hand
IF (card.value EQUALS CardValues.wild)
card.value = CardValues.ace
END
END
}
STEP 2: Sort Cards In Hand By Descending Value
Next, after all the wilds have been replaced with aces, sort the cards in the working hand in order of descending value (highest to lowest). We turn to our hero, CardMatchUtils.SortCardsByDescendingValue! We’ve used this guy many times now… where would we be without him? I don’t know about you, but I don’t wanna find out! 😆
Step 3: Compare Cards In Both Hands
The final step is comparing the cards in both hands.
Once again, we turn to a highly used function, CardMatchUtils.CompareHands. This function will compare two hands, both are assumed to already be sorted by descending card value. It accepts two parameters, hand1 and hand2. If hand1 has the higher hand, the function returns 0. If hand2 is higher, 1 is returned. Otherwise, -1 is return if both hands are equal.
So compared to other hand-comparing topics, comparing two flush hands is relatively easy. We’ve already written most of the functions used comparing flushes.
Example
Let’s have one example, using the two hands featured at the top of this article. Which one wins? Let’s find out! ⚔
Hand 2
Hand 2
First, let replace all wilds with aces. Hand 1 has one wild in it, so it now looks like:
The wild assumes both value and suit, and becomes an ace of diamonds.
Hand 2 has no wilds, so we’re done with step 1.
Next, we sort the cards in each hand by value in descending order. The hands now look like:
Hand 1
Hand 2
Finally, compare the cards, starting with the first card in each hand. Both hands have an ace, so move on to the second card.
Hand 1 has a jack, while hand 2 hand a queen. The queen outranks the jack, so hand 2 is the winning flush hand. 🙂
That’s it for comparing flushes! Below is a set of controls you can play with to creating and compare your own flush hands.
Compare Your Own Hands
Player 1
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Player 2
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Player 3
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Who Won:
If you have any questions about anything in this article, please let me know at cartrell@gameplaycoder.com.
Continuing the series of comparing poker hands of the same rank, this article will show you how to write code to compare two straights to see which one wins.
In a previous article for poker hands, you saw how to check a hand to determine if a hand was a straight. A straight is a hand where the values of all five cards are in sequential order. Here’s an example of a straight:
From left to right, each card is one less than the last one.
Comparing Straight Hands
When both hands are a straight, it’s very easy to compare the hands. First, sort the cards in order of descending value, meaning from highest to lowest. Next, compare the first card (highest) card from each hand. The hand with the higher card is the hand with the higher-ranking flush. If both cards are equal, then both hands are of equal rank.
Have a look at this example, hand 2 has the higher-ranking flush, since a jack outranks an eight.
Hand 1
Hand 2
This works very well for card values two through ace. But what about dem pesky wild cards? 😼
Comparing Straight Hands With Wild Cards
Wildcards do complicate things a little, but it’s nothing we can’t handle. 😏
Note: You can’t compare straights with wild cards in them, so you have to substitute them for the correct values. Before, when all you were doing was determining if a hand is a straight or not, this was not necessary. However, before you can do a comparison, you need to have all the wilds gone.
When you have wildcards in a straight hand, you can do these three steps:
Substitute card values for any values in between the highest and lowest card to fill out the straight. Use as many wilds as needed to fill out the gap between the highest and lowest card.
If there are any wilds left over, and the highest card is not an ace, substitute one wild with a card value higher than the highest card.
Repeat step 2 until you have replaced a wild card with an ace, or you run out of wilds.
If there are any wilds left over, and the lowest card is not a two, substitute one wild with a card value lower than the lowest card.
Repeat step 3 until you have replaced a wild card with a two, or you run out of wilds.
Some visual examples are always in order. 🙂
Example 1
Have a look at this hand:
Following step 1, you can substitute the two wilds with an eight and six, and you end up with:
Note: Remember, in a straight, as long as the hand contains at least two different suits, the suits don’t matter.
Example 2
Let’s try this hand:
Again, following step 1, we substitute wilds in between the highest and lowest values. Here, we’d use one wild and replace it with a nine, and we have:
We’ve one wild remaining, so we move on to step 2, and replace it with one higher than the highest card. So, you’d replace that wild with a queen, finally ending up with:
Example 3
Hey, lemme get another. Thanks, man. Good lookin’ out. 🤜🏾🤛🏾
Yep. (: If you’re holding these cards:
Step 1: There is no gap in between the queen and jack, so there’s nothing to do here.
Step 2: You can replace two cards higher then the queen, the king and ace. So you’d end up with this:
Step 3: With one wild left over, you replace it with one card lower than the lowest card, which currently is a jack. So, your final hand looks like:
Example 4
One final example. This one’s a bit of a smart-ass hand 😒
You can imagine some dude trying to put in all wilds to break the program. Yeah, well, you got his number, too.
Here, you have no existing card values from which to establish a highest or lowest card. So to make the best possible straight, you can simply replace it with a hand that looks like the previous example’s solution:
However, there is a more programmatic way of doing this other than simply a brute force hard-code, which I’ll show you how.
Because there are no card values, you can establish a “fake” highest and lowest value of “ace + 1”. Since the highest and lowest values are the same, step 1 is skipped. Since your highest value is higher than an ace (somehow, lol), step 2 is skipped.
That leaves step 3, so you start replacing wilds with values lower than the lowest value, which is also “ace + 1”. So the first wild would substitute “ace + 1 – 1” = ace. Then the next substitution is one lower than the lowest value, ace, which is ace – 1 = king.
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 Straights
When both hands are straights, the GetWinningPlayerId function will eventually call the FindWinnerStraight function that compares them to determine which one wins.
First, if either hand contains any wild cards, you’ll need to substitute them using the three steps mentioned above. Once all wilds have been substituted in both hands, you can compare them.
Let’s start with the FindWinnerStraight function.
FindWinnerStraight
FindWinnerStraight = function(hand1, hand2) {
SET workingHand1 = CardMatchUtils.SortCardsByDescendingValue(hand1);
SET hand1Info to an empty object { }
CardMatchUtils.AreCardsStraight(workingHand1, hand1Info)
SET workingHand1 = WildsAssumeValues(workingHand1, hand1Info)
SET sortedHand2 = CardMatchUtils.SortCardsByDescendingValue(hand2);
SET hand2Info to an empty object { }
CardMatchUtils.AreCardsStraight(workingHand2, hand2Info)
SET workingHand2 = WildsAssumeValues(workingHand2, hand2Info)
SET winningPlayerIndex = CardMatchUtils.CompareHands(workingHand1, workingHand2)
RETURN winningPlayerIndex
}
In the psuedocode above, you may have noticed the AreCardsStraight function from before, but it now has a new parameter that wasn’t there before: “info”.
We’ll need to make some adjustments to the AreCardsStraight, because if wilds are in the hand, we want to know what values will be replacing these wilds (using the three steps above). We can store the values in the info.cardValues array, same one we’ve used in previous hand comparing functions.
So, our new ‘AreCardsStraight’ function looks like this:
AreCardsStraight
AreCardsStraight = FUNCTION(sortedHand, info) {
SET numWilds to CardMatchUtils.CountCardsByValue(sortedHand, CardValues.wild)
SET cardValues to an empty array []
SET currentCardValue to 0
(these will be used later, but we want to set them up here)
SET highestCardValue to null
SET lowestCardValue to null
FOR EACH card in the sortedHand {
IF this card (the current loop card) is a wild card
IF (highestCardValue EQUALS null)
(this is the first card being checked)
SET highestCardValue to CardValues.ace + 1
END
EXIT FOR EACH LOOP
END
IF (this card is the first card being checked)
SET currentCardValue to the value of this card (card.value)
SET highestCardValue to currentCardValue
CONTINUE FOR LOOP again with next card (in other words, "continue" if you're familiar with for-loops)
END
SET valueDifference to currentCardValue - card.value
SET currentCardValue to card.value
IF valueDifference EQUALS 1
CONTINUE FOR LOOP again with next card (the condition for the straight is met so far)
END
IF valueDifference EQUALS 0
RETURN FALSE (this card has the same value as the previous card's stored in currentCardValue, the card from the previous loop iteration - this hand is not a straight)
END
SET lowestCardValue to currentCardValue
(check if there are enough wilds remaining to cover the difference in card values)
SET numWildsToUse to valueDifference - 1
IF numWilds GREATER THAN 0 AND numWilds IS GREATER THAN OR EQUALS numWildsToUse
(there are enough wilds, deduct that from the number of wilds available, and straight is still satisfied
SET numWilds to numWilds - numWildsToUse
(fill in the actial card values that will be replacing the wilds)
SET wildIndex to 0
WHILE wildIndex IS LESS THAN numWildsToUse
(repeat these steps as long as the WHILE condition is true)
SET substitutedCardValue to cardValue + wildIndex + 1
ADD substitutedCardValue into array cardValues
SET wildIndex to wildIndex + 1
END
ELSE
RETURN FALSE (there are not enough wilds to cover the range in value between the two cards - this hand is not a straight)
END
END
(straight is satisfied through all cards - success!)
(if there are any wilds remaining, try to assume values higher than the highest non-wild)
IF highestCardValue EQUALS null
SET highestCardValue to CardValues.ace
END
SET numWildsToUse to numWilds
WHILE (numWildsToUse IS GREATER THAN 0) {
SET cardValue to highestCardValue + (numWilds - numWildsToUse) + 1
IF (cardValue IS LESS THAN OR EQUALS CardValues.ace)
ADD cardValue into array cardValues
SET numWildsToUse to numWildsToUse - 1
ELSE
EXIT WHILE LOOP
END
END
(if there are any wilds remaining after assuming the higher values, try to assume values lower than the lowest non-wild)
IF (lowestCardValue EQUALS null
SET lowestCardValue to highestCardValue
END
SET offset to 0
WHILE offset IS LESS THAN numWildsToUse
SET cardValue to lowestCardValue - offset - 1
ADD cardValue into array cardValues
SET offset to offset + 1
END
IF info IS SPECIFIED
SET info.numWilds to numWilds
SET into.cardValues to array cardValues
END
RETURN TRUE
}
Wow! 😮 This is a little more than our original AreCardsStraight function! But it now handles all three steps of replacing wilds with the correct card values. If you got nothing else from this, know that the AreCardsStraight can now return to you those cardValues. 😉
Note that this function does not replace the cards in the hand itself. We’ll be doing that next; the main function of AreCardsStraight is still to determine if a hand is straight, and you can specify an optional info only if you need to know how many wilds are in the hand, and which card values would replace them to make a wild-less hand.
Replacing The Wild Cards With Card Values
Going back to the FindWinnerStraight, you maye have noticed a new function you’ve never seen before, called WildsAssumeValues. It accepts two parameters, a hand (an array or Card objects), and an info object. What this function will do is return a new hand, with all the wilds replaced with the values specified in the info.cardValues array.
Let’s have a look.
WildsAssumeValues
WildsAssumeValues = function(hand, info) {
SET index to 0
WHILE index IS LESS THAN number of cards in the hand (for example, "hand.length")
SET card = hand[index] (get the nth card in hand)
IF the card is a wild (card.value EQUALS CardValues.wild)
SET the card value to the last value in the info.cardValues array
REMOVE the last card value from the info.cardValues array (info.cardValues.pop())
END
SET index = index + 1
END
SET sortedHand to CardMatchUtils.SortCardsByDescendingValue(hand)
RETURN sortedHand
}
All the WildsAssumeValues does is go through the hand, replacing any wilds it finds with a value from the info.cardValues array. Then, it removes that value from the array to make sure it’s not used again. Finally, it creates a new hand and sorts the cards by card value in descending order, and returns that new hand. This new hand is what we’ll use to compare straights with.
Back in the FindWinnerStraight function, at this point, you’ll now have two hands with any wilds replaced with actual card values, and you can finally compare both hands using the CardMatchUtils.CompareHands function.
Remember, CardMatchUtils.CompareHands will return 1 if the first hand wins, -1 if the second hand winds, or 0 if both hands are tied.
That’s it for comparing two straight hands! Now, if you like, you can play with creating your own hands using the controls below. Enjoy! 😎
Compare Your Own Hands
Player 1
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Player 2
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Player 3
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Who Won:
If you have any questions about anything in this article, please let me know at cartrell@gameplaycoder.com.
When you have two poker hands and both are a three of a kind, this article will show you how to compare those hands and determine which one wins.
In a previous article for poker hands, you saw how to compare a hand to determine if a hand was three of a kind. A three of a kind is a hand three of the cards are the same value, and the remaining two cards are of different, non-pair values. Here’s an example of a three of a kind:
There are three 7s, and the remaining two cards, the eight and ten, are different values from the sevens and each other, so they don’t form a pair.
When determining the winner between two hands that are both three of a kind, the process is very similar to the pair’s, except we’re dealing with a trio instead fo a pair:
Compare the values of the trios.
If those values are equal, compare the values of other two cards (the “kickers“), starting with the highest one.
Continue comparing kickers until a kicker from one hand is higher than the other’s.
If no kicker breaks the tie, and all cards have been compared, then both hands are equal.
Some examples should help with explaining the concepts.
Consider these two hands:
Hand 1
Hand 2
Note: Just like with pairs being first sorted by the pairs,, the cards are sorted first the trio, then by the kickers in descending order of value. The hands above are already sorted this way.
First, compare the value of the trios. Hand 1 has trio of 8s, and hand 2 has a trio of 9s. So hand 2 wins this contest.
Let’s try another. Let’s say the values of the trios of both hands are the same as shown here:
Hand 1
Hand 2
Both hands have the same trio value of three. So you compare the kickers.
The values of first the kicker of each hand is a seven, so we’re tied. Let’s compare the second and final kicker. You can see that 6 > 4, so the first hand has the higher three of a kind.
And we can’t forget about our crazy wild cat wild cards! 😼 They always seem to throw a 🐵 🔧 into our plans. But we’re going to consider them as well.
Have a look:
Hand 1
Hand 2
In hand 1, we have a trio value of kings, and the a wild card is one of the kickers. Hand 2 also has a trio value of kings (the wild card substituting as a king). Since both hands have the same trio value (king), let’s compare the kickers.
Remember that a wild card can assume any value, and in our case, we want the wild card to assume the highest possible value (while still satisfying the hand and form the highest possible hand: see the note below). In the case of hand 1, the wild card assumes the value of a ace. If you compare that to hand 2’s first kicker, an ace beats a 10. So hand 1 is the winner here.
Note: In hand 1 above, you could’ve also formed the three of a kind by substituting the wild for a king like this:
However, if you use as many non-wild cards as possible to form your three of a kind, when using wild cards won’t increase the trio value, you can save any remaining wilds for as kickers. It will always be substituted as an ace, thus giving you the highest possible hand. When comparing hands, the code introduced in this article will help with that.
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 Threes Of Kinds
When two hands are both a pair of jacks or better, the GetWinningHand function will eventually call a function that compares two hands of said poker hand.
In this case, GetWinningHand function will eventually call FindWinnerJacksOrBetter to compare the hands. Just like FindWinnerHighCard from the last article, FindWinnerJacksOrBetter accepts two parameters, the hand for both players, and it’ll return the ID of the player who has the winning hand. If both hands are equal, it’ll return 0 (which we’ll use to mean a draw). The pseudocode below starts by comparing the values of the pairs first, then comparing the kickers if necessary.
FindWinnerThreeKind
FindWinnerThreeKind = function(hand1, hand2) {
sortedHand1 = CardMatchUtils.SortCardsByDescendingValue(hand1);
SET hand1Info to an empty object { }
CardMatchUtils.DoCardsHaveSameValue(hand1, 3, hand1Info);
sortedHand2 = CardMatchUtils.SortCardsByDescendingValue(hand2);
SET hand2Info to an empty object { }
CardMatchUtils.DoCardsHaveSameValue(hand2, 3, hand2Info);
SET winningIndex = CompareTrios(hand1, hand1Info, hand2, hand2Info);
IF (winningIndex NOT EQUAL TO -1)
RETURN winningIndex (one hand's trio outranks the other hand's, and no further checking is necessary)
END
(both hands have the same ranking trio, now compare the kickers of both hands)
SET winningIndex = CompareKickers(hand1, hand1Info, hand2, hand2Info);
RETURN winningIndex;
}
Comparing the Trios
First the code above sets the hands up for comparing their trios. It then sort the cards in descending card value. Next, it uses the DoCardsHaveSameValue function to get the three cards in the hand that make the trio, as well as determine the card value of the trio.
CompareTrios
CompareTrios = function(hand1, hand1Info, hand2, hand2Info) {
SET hand1WorkingTrioValue = hand1Info.cardValues[0]
IF (CardMatchUtils.CountCardsByValue(hand1, WILD_VALUE) GREATER OR EQUALS 3)
hand1WorkingPairValue = ACE_VALUE
SET hand2WorkingTrioValue = hand2Info.cardValues[0]
IF (CardMatchUtils.CountCardsByValue(hand2, WILD_VALUE) GREATER OR EQUALS 3)
hand2WorkingTrioValue = ACE_VALUE
IF (hand1WorkingTrioValue > hand2WorkingTrioValue)
RETURN 0 (hand 1 has the higher ranking trio)
ELSE IF (hand1WorkingTrioValue < hand2WorkingTrioValue)
RETURN 1 (hand 2 has the higher ranking trio)
END
RETURN -1 (both hands' trios have the same value)
}
This function is very similar to the ComparePairs function in our recent article for comparing pairs of jacks or better, except instead of dealing with two cards, we’re dealing with three. If you’d like details on the workings of that function, please check here.
Comparing the Kickers
If the trios of both hands have the same rank, then you’ll need to compare the other two cards, the kickers.
Like you did when comparing the kickers with previous poker hands, when comparing the kickers, you first remove the trios from both hands so you’re left with the remaining kickers. You can use the CardMatchUtils.BuildHandExcludingValues function to remove the trio.
You can use this psuedocode to get the kickers in the hand:
GetKickers
GetKickers = function(hand, info) {
(get the value of the cards that form the trio)
SET trioCardValue = info.cardValues[0]
(count the number of cards in the hand that match the trio card value)
SET numTrioValueCards = CardMatchUtils.CountCardsByValue(hand, trioCardValue)
(if there are at least as many trio value cards as there are non-kicker cards, specify the trio card value to the values of cards to exclude)
SET numNonKickerCards = 3
IF numTrioValueCards >= numNonKickerCards
SET valuesToExclude = trioCardValue
ELSE {
(otherwise, if there are at least as many wild cards as there are non-kicker cards, add the wild card value to the values of cards to exclude)
SET numWildCards = CardMatchUtils.CountCardsByValue(hand, CardValues.WILD)
IF numWildCards >= numNonKickerCards
SET valuesToExclude = CardValues.WILD
ELSE
(finally, specify BOTH, the trio card value and the wild card value as the values of cards to exclude)
SET valuesToExclude = [ CardValues.WILD, trioCardValue ]
END
}
(create the temporary kickers hand by excluding the specified values and returning the rest)
SET handOfKickers = CardMatchUtils.BuildHandExcludingValues(hand, valuesToExclude, numNonKickerCards)
(finally, sort the kickers hand in descending order, with wilds as the highest value)
handOfKickers = CardMatchUtils.SortCardsByDescendingValueHighWilds(handOfKickers)
RETURN handOfKickers
}
In the GetKickers above, the info object is the same one used in FindWinnerThreeKind. It was the hand1Info or hand2Info object, depending on which hand you’re getting the kickers from.
There are three situations in GetKickers that determine which values of cards to exclude as kickers.
The first is the simplest. It’s the trio card value used to form the three of a kind; they obviously can’t be the kickers. That means they will be excluded, leaving the remaining two cards as the kickers.
The second situation is that if the hand contains at least three wilds cards. These cards can assume the highest non-wild value, which is an ace. So three wilds would form a three of a kind, using an ace as the trio card value. So the wild card value would be excluded from the hand of kickers.
Finally, the hand doesn’t have three cards with the same value, but it does contain two wild cards. Those wilds will still assume the value of the highest non-wild card, forming the three of a kind. The trio card value is whatever value those wilds card assumed. In this situation, you want to exclude both values of both, the wild card, and the trio card value.
Note: When excluding cards, you’re always excluding exactly three cards (the number of non-kicker cards).
Comparing The Kickers
I hope you are still with me at this point. If you’re reading this far, I suppose it goes without asking 😉
When comparing which three-of-a-kind hand winds, if the trio values of both hands are the same, then you need to compare one or both of the kicker cards from both hands to determine the winner.
CompareKickers
CompareKickers = function(hand1, hand1Info, hand2, hand2Info) {
SET hand1Kickers = GetKickers(hand1, hand1Info)
SET hand2Kickers = GetKickers(hand2, hand2Info)
SET winningPlayerIndex = CardMatchUtils.CompareHands(hand1Kickers, hand2Kickers)
RETURN winningPlayerIndex
}
The CardMatchUtils.CompareHands function is the same one we used here.
The CompareKickers will return 0 if hand1 has the better kickers (and thus the better three-of-a-kind-hand), 1 if hand2 has the better kickers, or -1 if both hands are the same rank.
That’s it for this article. As we write more solutions, we can often re-use code from previous ones to help simply and speed up the process.
Compare Your Own Hands
You can use the controls below to build your own hands and compare threes of kinds. Have some fun playing around with it, and if you find an issue, please let me know!
Player 1
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Player 2
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Player 3
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Who Won:
If you have any questions about the content in this article, go ahead and let me know at cartrell@gameplaycoder.com.
When you have two poker hands and both are a two pair, this article will show you how to compare them and determine which one ranks higher.
In a previous article for poker hands, you saw how to compare a hand to determine if a hand was a two pair. The pairs in the hand are made of two different values, and a fifth card with a different value from either of the pairs. Here’s an example of a two pair:
The is a “two pair, queens and fives”, and the kicker card is a jack.
When determining the winner between two hands that are both a two pair, the process is very similar to the pair’s, except we’re dealing with two pairs in each hand instead of one:
Compare the values of each hand’s higher pair.
If those values are equal, compare the values of each hand’s lower pair.
If those are equal, compare the values of the final card (the “kickers” ) in each hand.
Finally, if the kicker does not breaks the tie, then both hands are equal.
Let’s have a look at an example.
Hand 1
Hand 2
In hand 1, the value of its higher pair is five, and hand 2’s is six. So, hand 2 is the winner.
Now, consider these hands:
Hand 1
Hand 2
The higher pair in hand 1 has a value of five, and so does hand 2. So move onto the lower pair.
The value of hand 1’s lower pair is four, while hand 2’s is three. This time, hand 1 is the winner.
And if the values of the pairs in both hands are equal, then you’d go on to compare the final kicker card of each hand.
Wild Cards
But what about wild cards!? 😮
Yeah, guess we shoulda seen that one comin’. 😉
Remember that a wild card can assume the value of any card. If your hand has a pair of wilds in it, then both wilds can assume the highest value, ace. Have a look at this:
The suits of the aces don’t matter; wilds only care about card values in the case of a two pair.
If the hand only contained a pair one wild, and two other cards of different values, then the wild would assume other card with the higher value. So, if the hand was this:
The wild would assume the value of jack, because that’s the highest non-paired card. So the hand acts like:
This creates a challenge for us in a few ways, and we’ll need to make some changes to how two pairs are even matched in the first place.
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 Pairs
When two hands are both a two pair, the GetWinningHandfunction will eventually call a function that compares both of these types of hands.
But before we do that, we’ll need a way to get the values of both pairs in a hand when we compare the hand to another two-pair hand.
Have a look at this hand:
If you go back to examine the psuedocode of the TwoPair function, you’ll see that it calls CardsHaveSameValue(sortedHand, 2, wildsInfo) twice. That’s because it’s checking to see if 2 cards have the same value twice.
There are two caveats to this function.
One is that it could find two pairs, where both pairs have the same value, something like:
While technically, this hand contains two pairs of cards, it’s not a two pair, because the pairs are the same value. Also, if you’ve implemented a system, where you’re matching hands, starting with the highest ranking hand and working down, this hand would always be matched as a four of a kind before ever being evaluated as a two pair.
The second caveat is that the info.cardValues array inside the parameter of CardsHaveSameValue does not report the correct value if our hand has only one pair and a wild. After calling CardsHaveSameValue twice, it would report the cardValues of the two cards found would be CardValues.JACK and CardValues.TWO! It should’ve reported CardValues.NINE instead! When you’re simply matching for a two pair hand, it doesn’t matter which card values get reported, since they aren’t used anyway. But if you’re comparing two hands of a two pair, that’s a whole ‘nother story. The correct values of the pairs are important.
We won’t make any adjustments to CardsHaveSameValue since it works well for out matching situations. We don’t want to break anything. So, getting the correct pairs will require some custom code for comparing two pairs.
Let’s begin, shall we? 😏
Our main function, GetWinningHand will eventually call FindWinnerTwoPair to compare the hands. Just like the previous FindWinnerHighCard and FindWinnerJacksOrBetter functions from previous articles, FindWinnerTwoPair accepts two parameters, the hand for both players, and it’ll return the ID of the player who has the winning hand. If both hands are equal, it’ll return 0 (which we’ll use to mean a draw). The pseudocode below starts by comparing the values of the pairs first, then comparing the kickers if necessary.
FindWinnerTwoPair
FindWinnerTwoPair = function(hand1, hand2) {
sortedHand1 = CardMatchUtils.SortCardsByDescendingValue(hand1);
SET hand1Info to an empty object { }
SetInfoAndCheckForTwoPair(hand1, hand1Info);
sortedHand2 = CardMatchUtils.SortCardsByDescendingValue(hand2);
SET hand2Info to an empty object { }
SetInfoAndCheckForTwoPair(hand2, hand2Info);
SET winningIndex = ComparePairs(hand1, hand1Info, hand2, hand2Info);
IF (winningIndex NOT EQUAL TO -1)
RETURN winningIndex (one hand's pairs outranks the other hand's, and no further checking is necessary)
END
(both hands have the same ranking pairs, now compare the kickers of both hands)
SET winningIndex = CompareKickers(hand1, hand1Info, hand2, hand2Info);
RETURN winningIndex;
}
The FindWinnerTwoPair function uses a few new functions, SetInfoAndCheckForTwoPair and ComparePairs, and we’ll get into those below.
Checking For A Two Pair And Getting The Pair Values
This function will check for a two pair with two unique values of pairs, and it will update the info parameter sent to it.
SetInfoAndCheckForTwoPair
SetInfoAndCheckForTwoPair = function(hand, info) {
IF info not is specified
SET info to an empty object { }
END
IF info does not contain the property cardValues
SET info.cardValues to an empty array [ ]
END
SET valueCounts to CountCardValues(hand) (count the number of times each card value appears in the hand)
FOR EACH valueCount found in valueCounts
IF the number of times that value was found EQUALS two (valueCount.count == 2)
add that card value to the end of the info.cardValues array
END
END
IF the number of values in the info.cardValues array EQUALS two (info.cardValues.length == 2)
(we have two pairs with unique values, so the two pair is satisfied, we can exit here with success)
sort the values in info.cardValues in descending order (highest to lowest)
RETURN TRUE
END
IF the number of values in the info.cardValues array EQUALS one (info.cardValues.length == 1)
(only found one pair, check if the other pair could be formed using wilds, if any exist)
(exclude the two cards that form the pair from the hand using the frst [and only] card value in the info.cardValues array)
SET handMinusPair = CardMatchUtils.BuildHandExcludingValues(hand, 2, info.cardValues[0])
IF CardMatchUtils.DoCardsHaveSameValue(handMinusPair, 2, info) == TRUE
(There was a wild in the remaining three cards that formed a pair with the highest value. The DoCardsHaveSameValue will add that card's value
onto the end of the info.cardValues array.)
sort the values in info.cardValues in descending order (highest to lowest))
RETURN TRUE
END
END
(this hand is not a two pair, exit with failure)
RETURN FALSE
}
Counting Card Values
This function counts how many times the values of each card in the hand appears. This is useful for counting pairs, and generic enough to put into CardMatchUtils.
CountCardValues
CardMatchUtils.CountCardValues = function(hand) {
SET countValues to an empty array [ ]
FOR EACH card in the hand
FOR EACH countValueUnit in countValues
IF countValueUnit.value EQUALS card.value
ADD 1 onto countValueUnit.count
END
END
IF none of the current count value units in countValues have a value that equals the card's value
(add a new count value unit onto the countValues array with these values)
countValues.push({
value: card.value
count: 1
})
END
END
RETURN countValues
}
Quite a lot here, right. Let’s have a closer look, shall we? 🙃
First, have a look at SetInfoAndCheckForTwoPair. This function accepts two parameters:
The hand of cards, already sorted in descending order, wilds last.
An optional info parameter.
When the function first runs, if no info parameter is specified (which would be the case if you’re only matching for a two pair and not comparing it), then one is created for use of this function. Otherwise, the info object specified is used, and modified by this function (for later use). We also want to create a new cardValues array property inside the info object and set it to an empty array [ ].
After that, the function counts the number of times each card value appears in the hand. This introduces a new function that you can place in your CardMatchUtils called CountCardValues.
So if you looked at our previous hand:
When we count the values in it, the CountCardValues would return this array:
Back to the SetInfoAndCheckForTwoPair function: for those elements in this array that have a count property of 2, add them those values to the info.cardValues array. In this case, only the pair of jacks was found, so your info.cardValues looks like [ 11 ].
Next, if after counting card values, our info.cardValues has exactly two elements in it, this means it found two pairs of unique values. So, we’ve satisfied the condition of a two pair, and we can exit with success.
However, as in our example, we only found one pair. So we need to check the remaining three cards.
At this point, CardMatchUtils.DoCardsHaveSameValue would not have any adverse side effects if we used it on the remaining three cards, because if a wild was one of them, it would assume the highest value between the other two cards.
It would be nice if we could temporarily remove the first pair so we could easily compare the remaining three. Fortunately, we already have a CardMatchUtils.BuildHandExcludingValues function that can do just that! 😎
So there is this line in the SetInfoAndCheckForTwoPair function: SET handMinusPair = CardMatchUtils.BuildHandExcludingValues(hand, 2, info.cardValues[0]) It builds us a new temporary hand without the jacks in it (or whatever the value of the first pair was).
In SetInfoAndCheckForTwoPair, we can then go on to call: CardMatchUtils.DoCardsHaveSameValue(handMinusPair, 2, info) And if it returns TRUE, then:
A pair formed using a wild was possible
The info.cardValue array will be updated (by DoCardsHaveSameValue) which will contain the value that the wild assumed. In this case, a nine.
Finally, in SetInfoAndCheckForTwoPair just before, and if, it finds success, it sorts the values in the info.cardValues array in descending order (highest to lowest). It does this because when comparing the pairs of both hands, this makes comparisons easier, because we’ll be comparing the higher-ranking pair of one hand to the other hand’s higher-ranking pair. Then, if necessary, the lower-ranking pairs.
So when SetInfoAndCheckForTwoPair completes and it returns TRUE, not only will yo have a valid two-pair hand, but then you’ll also know the values of both pairs.
Comparing The Pairs
The next major function in FindWinnerTwoPair is ComparePairs. This will compare the values of the pairs of both hands and return 0 if the first hand wins, 1 if the second hand wins, or -1 if both hands are equal.
ComparePairs
ComparePairs = function(hand1, hand1Info, hand2, hand2Info) {
(compare the higher-ranking pairs of each hand first)
SET hand1WorkingPairValue = hand1Info.cardValues[0]
IF hand1WorkingPairValue EQUALS WILD_VALUE
hand1WorkingPairValue = ACE_VALUE
SET hand2WorkingPairValue = hand2Info.cardValues[0]
IF hand2WorkingPairValue EQUALS WILD_VALUE
hand2WorkingPairValue = ACE_VALUE
IF (hand1WorkingPairValue > hand2WorkingPairValue)
RETURN 0 (hand 1's higher-ranking pair wins)
ELSE IF (hand1WorkingPairValue < hand2WorkingPairValue)
RETURN 1 (hand 2's higher-ranking pair wins)
END
(compare the lower-ranking pairs of each hand first)
SET hand1WorkingPairValue = hand1Info.cardValues[1]
IF hand1WorkingPairValue EQUALS WILD_VALUE
hand1WorkingPairValue = ACE_VALUE
SET hand2WorkingPairValue = hand2Info.cardValues[1]
IF hand2WorkingPairValue EQUALS WILD_VALUE
hand2WorkingPairValue = ACE_VALUE
IF (hand1WorkingPairValue > hand2WorkingPairValue)
RETURN 0 (hand 1's lower-ranking pair wins)
ELSE IF (hand1WorkingPairValue < hand2WorkingPairValue)
RETURN 1 (hand 2's lower-ranking pair wins)
END
RETURN -1 (both pairs in both hands are equally ranked)
}
The ComparePairs is similar to past ones we’ve written, except the main difference her is, we’re comparing two pairs instead of one. Also, this is why sorting the values in the info.cardValues array in descending order (highest to lowest) is so important.
As you can see, when comparing the higher-ranking pairs of both hands we use cardValues[0] from both hands’ info object. Then if they are equal, we compare the lower-ranking pairs using cardValues[1].
We also do the usual replacing of wild values with aces if the value of a pair is a wild.
Comparing The Kickers
It’s down to the final stretch. Both hands are neck and neck so far, and it’s come down to that final x-factor card for a possible tie-breaker.
CompareKickers
CompareKickers = function(hand1, hand1Info, hand2, hand2Info) {
SET hand1Kickers = GetKickers(hand1, hand1Info)
SET hand2Kickers = GetKickers(hand2, hand2Info)
SET winningPlayerIndex = CardMatchUtils.CompareHands(hand1Kickers, hand2Kickers)
RETURN winningPlayerIndex
}
This function gets the kicker card. To do this, you exclude from the hand, all other cards that make up both pairs. This happens inside the GetKickers function.
GetKickers
GetKickers = function(hand, info) {
SET valuesToExclude to an empty array [ ]
(set the higher-ranking pair of cards to be excluded)
SET pairValue to info.cardValues[0]
IF the number of cards in the hand with the value of pairValue EQUALS 2
add pairValue to the valuesToExclude array
ELSE IF the number of wild cards in the hand EQUALS 2
add CardValues.wild to the valuesToExclude array
ELSE
add both, pairValue and CardValues.wild to the valuesToExclude array
END
(set the lower-ranking pair of cards to be excluded)
SET pairValue to info.cardValues[1]
IF the number of cards in the hand with the value of pairValue EQUALS 2
add pairValue to the valuesToExclude array
ELSE IF the number of wild cards in the hand EQUALS 2
add CardValues.wild to the valuesToExclude array
ELSE
add both, pairValue and CardValues.wild to the valuesToExclude array
END
SET kickers to CardMatchUtils.BuildHandExcludingValues(hand, valuesToExclude, 4)
RETURN kickers
}
This function will exclude all cards found in pairs, leaving only one card remaining. Even though CardMatchUtils.BuildHandExcludingValues returns a hand (an array of Card objects), the array will always contain just one Card in it.
Now that you have the kickers in both hands, you can compare those cards. Since it’s only one card for each, you could just write a straight up comparison, and return the appropriate index depending on the result.
However, I think it’s still better to write: SET winningPlayerIndex = CardMatchUtils.CompareHands(hand1Kickers, hand2Kickers) because we already have that comparison code written, and it’ll already return the appropriate index for us, leaving the code here cleaner. 😉
Conclusion
Whew! This one was pretty meticulous just to compare two hands of two-pairs to see which one won! But I think you’ll be pleased with the result once it’s all working.
Compare Your Own Hands
You can use the controls below to build your own hands and compare hands of two pairs. Have some fun playing around with it, and if you find an issue, please let me know!
Player 1
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Player 2
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Player 3
Card 1
Card 2
Card 3
Card 4
Card 5
Result:
Who Won:
If you have any questions about anything in this article, please let me know at cartrell@gameplaycoder.com.