When you have two poker hands, both are a Jacks or Better pair, this article will show you how to compare those hands and determine which hand wins.
We previously went over how to determine if a hand is a jacks or better pair.
A jacks or higher pair is a poker hand that where exactly two of its cards have the same value, which is a jack or higher.
When determining the winner between two hands that are jacks-or-better pairs, follow this process.
- Compare the values of the pairs.
- If those values are equal, compare the values of other three 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.
Let’s look at some examples.
Say we have these two hands:
It’s best to sort the cards in descending value order (from highest to lowest), first by the pairs, then by the kickers. So we rearrange the cards in both hands to look like:
Note: The suits don’t matter, only the order of the card values.
You can see that hand 1 has a pair of kings, while hand 2 has a pair of jacks. Kings easily beats jacks, so hand 1 wins.
But what both hands hand pairs of the same value? Let’s try another.
After sorting, we get:
Both hands have a pair of queens, so we’ll need to look at the three kicker cards of each hand.
The first one is a 9 in both hands, so you move onto the next card. The second is a 7 in both hands, still no tie breaker. So we move on to the final card. Hand 1 has a 2, while hand 2 has a 3. So hand 2 has the higher-ranking pair and wins this battle.
Setup
Note: The first stages of the setup can be found on the introduction page to comparing poker hands, here ( https://gameplaycoder.com/how-to-code-poker-hands-comparing-hands/#setup ).
There aren’t any other specific preparations we need before we begin.
Writing The Code For Comparing Pairs of Jacks Or Better
When two hands are both a pair of jacks or better, the GetWinningHand
function will eventually call a function that compares two jacks or better pairs.
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 -1
(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.
FindWinnerJacksOrBetter
FindWinnerJacksOrBetter = function(hand1, hand2) {
sortedHand1 = CardMatchUtils.SortCardsByDescendingValue(hand1);
SET hand1Info to an empty object { }
CardMatchUtils.DoCardsHaveSameValue(hand1, 2, hand1Info);
sortedHand2 = CardMatchUtils.SortCardsByDescendingValue(hand2);
SET hand2Info to an empty object { }
CardMatchUtils.DoCardsHaveSameValue(hand2, 2, hand2Info);
SET winningIndex = ComparePairs(hand1, hand1Info, hand2, hand2Info);
IF (winningIndex NOT EQUAL TO -1)
RETURN winningIndex (one hand's pair outranks the other hand's, and no further checking is necessary)
END
(both hands have the same ranking pair, now compare the kickers of both hands)
SET winningIndex = CompareKickers(hand1, hand1Info, hand2, hand2Info);
RETURN winningIndex;
}
Comparing the Pairs
The first half of this function sets up the hands for comparing their pairs. It sorts the cards in descending card value. Next, it uses the DoCardsHaveSameValue
function to get the two cards in the hand that make up the pair.
But there is a problem here. We’d like to compare the values of the pairs here, and you may recall that DoCardsHaveSameValue
only tells us if there are a certain number of cards in the hand that have the same value (in this case 2). It doesn’t tell us what that value is.
So, you’ll need to make some adjustments to your DoCardsHaveSameValue
function. We can add this data to our custom wildsInfo
parameter.
Open your CardMatchUtils
source file, and find the DoCardsHaveSameValue
function. Inside that function, at the beginning of it, add a new variable named cardValues
and assign it an empty array []
.
Next, if an info
object was sent as a parameter to the DoCardsHaveSameValue
function, assign its cardValues
property to your cardValues
variable:
if ("cardValues" in info) {
cardValues = info.cardValues;
}
Next, at every point within DoCardsHaveSameValue
, when the function is about to return true
(this is also when it updates its info parameter if one was specified just before returning), add the following code:
- Add the current base card value to your
cardValues
array:
cardValues.push(u_baseCardValue);
- Add the
cardValues
array as a property to yourinfo
object:
info.cardValues = cardValues;
What this code does is tell us what the value of the card was that was found the requested number of times.
Let’s have a look at a quick example: say we have this hand:
If we called DoCardsHaveSameValue(hand, 2, info)
, the function would return true
, because it found two queens. Also, the info
object would have a new cardValues
property that would be set to [12]
, because CardValues.QUEEN
has a value of 12
, and that was the value of the card that was found the two times we requested.
We need the value of the first element in the info.cardValues
array from each hand to compare their pair values.
So, from CardMatchUtils.DoCardsHaveSameValue(hand1, 2, hand1Info)
in our FindWinnerJacksOrBetter
function, there will be a hand1Info.cardValues
property you can now use. We’ll make use of these in the ComparePairs(hand1, hand1Info, hand2, hand2Info)
function. See below:
ComparePairs
ComparePairs = function(hand1, hand1Info, hand2, hand2Info) {
SET hand1WorkingPairValue = hand1Info.cardValues[0]
IF (CardMatchUtils.CountCardsByValue(hand1, WILD_VALUE) GREATER OR EQUALS 2)
hand1WorkingPairValue = ACE_VALUE
SET hand2WorkingPairValue = hand2Info.cardValues[0]
IF (CardMatchUtils.CountCardsByValue(hand2, WILD_VALUE) GREATER OR EQUALS 2)
hand2WorkingPairValue = ACE_VALUE
IF (hand1WorkingPairValue > hand2WorkingPairValue)
RETURN 0 (hand 1 has the higher ranking pair)
ELSE IF (hand1WorkingPairValue < hand2WorkingPairValue)
RETURN 1 (hand 2 has the higher ranking pair)
END
RETURN -1 (both hands' pairs have the same rank)
}
Since we now have the values of the pairs in both hands, we could’ve just compared hand1Info.cardValues[0]
to hand2Info.cardValues[0]
. But instead, we performed an additional check if the hand contained at least two wild cards (see below), then assigned the working pair value to the ace value. That’s because if we did only a cardValues[0]
comparison, that presents a problem when wild cards are involved.
Remember, to satisfy the requirements of CardMatchUtils.DoCardsHaveSameValue
, a wild card assumes the value of the highest non-wild card. So if you had a hand like this:
The wild card would assume a value of a king, and you’d have a pair of kings.
But what if you had a hand with, not one, but TWO wilds in it!? (gasp o: )
Normally, one of the wilds would still try to assume the value of the highest non-wild card. in this case, it would be a 9, but this does not for a jacks-or-higher pair. Instead, we could simply have the two wilds themselves form the pair, and assume the highest non-wild value, which would be ace. So the pair of wilds acts like a pair of aces.
So, if the CountCardsByValue
call finds two wild cards in the hand, the working pair value for that hand will be CardValues.WILD
, instead of the value found in cardValues[0]
.
Note: You want to check if there are at least two wild cards, because, say hand 1 contained two wilds, and hand 2 contained three. The wilds in both hands would form a pair, and hand 2 would have an extra wild card left over. This third wild, however, is not involved in the pair, but would be a kicker, substituting as an ace.
Comparing the Kickers
If the pairs of both hands have the same rank, then we’ll need to compare the other three cards, the kickers, and see which hand, if either, is finally a winner.
When comparing the kickers, it would be great if we could first remove the pairs from both hands so we’re only left with the remaining three cards of each. This would also remove situations where the value of a pair might not be the highest value in the hand. The two cards that make up the pair aren’t necessarily at the beginning of the hand, (when ordered by descending card value). For example, the hand could contain a pair of queens, but the highest card is a king.
So, you can remove the cards that make up the pair (including wilds) by writing a new function to go into CardMatchUtils
file. Let’s call this function BuildHandExcludingValues
. This function will create a copy of a hand, with specific cards excluded from the copy. It takes three parameters:
cards
– The hand (an array ofCard
objects)valuesToExclude
– An array of card values that are to be excluded from the new copy, if they are found incards
maxCountToExclude
– The maximum count of cards that can be excluded. This is useful to prevent the function from excluding too many cards. For example, a hand may have three queens in it; we only want to remove two, and the third one is a kicker.
Without further ado, tis BuildHandExcludingValues
function:
BuildHandExcludingValues
BuildHandExcludingValues = function(cards, valuesToExclude, maxCountToExclude) {
SET copyHand = [] (this is our new hand; set it up as an empty array)
SET currentCountExcluded = 0 (keep track of the number of cards excluded)
FOR EACH card IN cards
IF (card.value does not match any of the values in valuesToExclude)
add the card to the copyHand array
ELSE
IF currentCountExcluded LESS THAN maxCountToExclude
increment currentCountExcluded by 1 (this card is effectively "excluded" from the copy)
ELSE
add the card to the copyHand array (the max number of excluded cards has been reach; include card in the copy, even if it's supposed to be excluded)
END
END
END
RETURN copyHand
}
Let’s have a look at two quick examples.
Say you have this hand:
Your pair would be the king and the wild (acting as the other king). Your kickers are the three remaining cards.
If you called BuildHandExcludingValues
with valuesToExclude
set to [ CardValues.KING, CardValues.WILD ]
, and maxCountToExclude
set to 2
, the copy returned would look like:
Now, consider this hand:
After calling BuildHandExcludingValues
with valuesToExclude
set to [ CardValues.QUEEN ]
, and maxCountToExclude
set to 2
, the copy returned would look like:
In this case, the queens form a pair without using a wild, so the wild becomes a kicker that assumes the highest value (ace).
Before you compare the kickers of both hands, you’ll need to sort them in descending order, but this time, wilds will be placed first (as the highest value) instead of last like usual. You’ll use the new function CardMatchUtils.SortCardsByDescendingValueHighWilds
that you wrote in the last article.
The comparison of the kickers can be made with another new function that you can place in CardMatchUtils
: CardMatchUtils.CompareHands
. You’ll see how this function works below.
CompareKickers
CompareKickers = function(hand1, hand1Info, hand2, hand2Info) {
(build a temporary hand that contains only the kickers from hand 1)
SET valuesToExclude = [ CardValues.WILD ]
IF (CardMatchUtils.CountCardsByValue(hand1, WILD_VALUE) NOT EQUAL 2)
add hand1Info.cardValues[0] to the valuesToExclude array
SET hand1Kickers = CardMatchUtils.BuildHandExcludingValues(hand1, valuesToExclude, 2)
hand1Kickers = CardMatchUtils.SortCardsByDescendingValueHighWilds(hand1Kickers)
(build a temporary hand that contains only the kickers from hand 2)
SET valuesToExclude = [ CardValues.WILD ]
IF (CardMatchUtils.CountCardsByValue(hand1, WILD_VALUE) NOT EQUAL 2)
add hand2Info.cardValues[0] to the valuesToExclude array
SET hand2Kickers = CardMatchUtils.BuildHandExcludingValues(hand2, valuesToExclude, 2)
hand2Kickers = CardMatchUtils.SortCardsByDescendingValueHighWilds(hand2Kickers);
(compare the two temporary hands)
SET winningPlayerIndex = CardMatchUtils.CompareHands(hand1Kickers, hand2Kickers)
RETURN winningPlayerIndex
}
CompareHands
CardMatchUtils.CompareHands = function(hand1, hand2) {
(both hand1 and hand2 should contain the same number of cards in them, but if they don't, use the hand with fewer cards as the number of cards to
compare)
SET numberOfCardsToCompare = MIN(hand1.length, hand2.length)
FOR cardIndex = 0 TO numberOfCardsToCompare
(get the nth card from each hand)
SET card1 = hand1[cardIndex]
SET card2 = hand2[cardIndex]
(get the card value of both cards to compare; treat wilds as aces)
SET card1Value = MIN(card1.value, CardValues.ACE)
SET card2Value = MIN(card1.value, CardValues.ACE)
IF (card1Value GREATER THAN card2Value)
RETURN 0 (hand 1 has a higher ranking hand)
ELSE IF (card1Value LESS THAN card2Value)
RETURN 1 (hand 2 has a higher ranking hand)
END IF
END
(all cards in both hands are equal)
RETURN -1
}
The CardMatchUtils.CompareHands
function accepts two parameters: both players’ hands. The hands are the temporary ones that include only the kickers, and should already be sorted in descending order with wilds at the beginning of the order. The function compares cards in both hands, starting with each hand’s first card, then second if necessary, and so on. It returns 0
if hand1
has a higher hand, 1
if hand2
has a higher hand, or -1
if both hands are equal. The value returned gets passed back up to the function that called it, CompareKickers
, which passes the returned value back up to the original calling function, FindWinnerJacksOrBetter
.
That pretty much wraps it up for this article! When you have a physical deck of cards, and you compare two poker hands, it’s easy to determine which one wins. But when you have to write out the process for doing so, step by step, it’s a bit more challenging that you might realize. 😉
Compare Your Own Hands
You can use the controls below to build your own hands and compare pairs of jacks or better. Now that you have two poker hands, high card and jacks or better pairs, you can also compare those two ranks, and you’ll see that the pair will always beat the high card. Have some fun playing around with it, and if you find an issue, please let me know!
Player 1
Player 2
Player 3
If you have any questions about recognizing a royal flush, or the above interaction, please let me know at cartrell@gameplaycoder.com.
Thanks, and stay tuned, because we have more poker hands to cover in this series!
– C. out.
Never really thought about it, but it makes sense that the lowest hand would be determined through the value of the cards. I’ve mostly just tried solo poker games though I’m guessing in groups this is how it would work.
Yep, when more than one player has a high hand, you sort the cards in descending value, then compare them. It’s interesting how the steps can be broken down into intricate details. Thanks!
– C. out.