Hey! What’s up.
Today, we’ll be resuming in the mini-series of writing code that can tell what kind of poker hand a player has. And the poker hand we’re covering is a two pair.
- Pair (jacks or higher only)
- Two pair
- Three of a kind
- Straight
- Flush
- Full house
- Four of a kind
- Straight flush (a non-ace-high straight flush)
- Royal flush (an ace-high straight flush)
A two pair is a hand that has two cards of one value, two more cards of another value, and a third card whose value is different than the first four. Here is an example the a two pair hand:
Setup
If you’d like to see the first article, coding a pair of Jacks or higher, you can check that out here. There, you’ll also a detailed description of the data structures used. But here is a quick rundown of those data structures:
Card values
CardValues = {
two: 2,
three: 3,
four: 4,
five: 5,
six: 6,
seven: 7,
eight: 8,
nine: 9,
ten: 10,
jack: 11,
queen: 12,
king: 13,
ace: 14,
wild: 100
};
Card suits
CardSuits = {
hearts: 1,
diamonds: 2,
clubs: 3,
spades: 4
};
Card
Card = function(value, suit) {
this.value = value;
this.suit = suit;
};
Hand
And a hand is an array of Card
objects:
var hand = [
new Card([card value 1], [card suit 1]),
new Card([card value 2], [card suit 2]),
...
new Card([card value 5], [card suit 5])
];
Writing The Code To Identify A Two Pair
When looking for a two pair, it’s also very helpful if we first sort the cards by their value (rank), in descending order. We previously defined a “utilities” file, CardMatchUtils.js
, and added a function to it called, CardMatchUtils.SortCardsByDescendingValue
, to help with that.
We’re also using the “wild card”, which is a card that can assume the value of any card. So, the following hand would also qualify as a two pair:
In this image, we have a pair of sixes, and because we have a wild card, we take the highest non-paired card, in this case a king, and pair the wild with that. So, we have a pair of kings.
The main function of our pseudocode looks like this:
TwoPair
TwoPair = FUNCTION(hand) {
SORT the hand by descending card value and store in a variable called sortedHand
SET wildsInfo to an empty object
ADD a PROPERTY numWilds to wildsInfo and set it to 0
ADD a PROPERTY startIndex to wildsInfo and set it to 0
IF CardsHaveSameValue(sortedHand, 2, wildsInfo) AND
CardsHaveSameValue(sortedHand, 2, wildsInfo)
//we have two pairs!
RETURN TRUE
//no two pair in this hand
RETURN FALSE
}
That’s it… not so fast! What’s this CardsHaveSameValue
function we’ve never seen before? 🤔
This is a new utility to our CardMatchUtils.js
file. Let’s officially call this CardMatchUtils.DoCardsHaveSameValue
. This function will determine if a hand has at a certain number of cards that have the same arbitrary value.
This function accepts three parameters:
sortedHand
– Array ofCard
objects that are already sorted in descending value.numToMatch
– An integer that indicates how many cards whose value we are looking to match. In our case, it’s two.wildsInfo
– An object that will allow us to save data for subsequent calls to thisDoCardsHaveSameValue
function. From our code above, we calledCardsHaveSameValue
twice, passing inwildsInfo
each time. The first call needs to save certain intermittent data so the next call can resume where the first one left off. ThewildsInfo
parameter has two properties:numWilds
– The number of wild cards available for use as substitutes.startIndex
– The index of thesortedHand
array on whichDoCardsHaveSameValue
starts when it checks each card in the hand.
The wildsInfo
paramater is only needed if your game supports wild cards. Otherwise, you can set it to null
(or don’t specify it, if the programming language you’re using supports some form of optional arguments like JavaScript or C#).
CardMatchUtils.DoCardsHaveSameValue
will return true
if the specified number of cards have the same value, or false
otherwise.
DoCardsHaveSameValue
CardMatchUtils.DoCardsHaveSameValue = function(sortedHand, numToMatch, wildsInfo) {
SET numWilds to 0
SET startIndex to 0
IF wildsInfo is specified
SET numWilds to wildsInfo.numWilds
IF numWilds is 0
count the number of wild cards in the hand, and set this value to numWilds
END IF
SET startIndex to wildsInfo.startIndex
ELSE
count the number of wild cards in the hand, and set this value to numWilds
END IF
SET maxIndex to sortedHand.length - numWilds - 1
SET baseCardValue to 0
SET numMatched to 0
LOOP through each card in the sortedHand array, starting at index startIndex
IF it's the first card in the loop
//first card starts off the number of matches with a base card value
SET baseCardValue to the card's value
SET numMatched to 1
CONTINUE with next card in the loop
END IF
IF the baseCardValue EQUALS the card's value
//this card's value matches the base card value
ADD 1 to the current value of numMatched
IF numMatched EQUALS numToMatch
//total number of matched cards found - success
IF wildsInfo is specified
SET PROPERTY wildsInfo.numWilds to numWilds
SET PROPERTY wildsInfo.startIndex to the current loop index + 1
END IF
RETURN TRUE
END IF
//still need to match more cards for the base card value
CONTINUE with next card in the loop
END IF
//This card's value does not match the base card value. Check if there are enough wilds that can satisfy the match.
IF numMatched + numWilds is GREATER THAN OR EQUALS numToMatch
//there are enough wilds that can satisfy the base card value - success
//deduct the number of wilds used to satisfy the base card value from the current number of wild cards
SET numberOfWildsToDeduct to numToMatch - numMatched
DEDUCT numberOfWildsToDeduct from numWilds
//update the wilds info
IF wildsInfo is specified
SET PROPERTY wildsInfo.numWilds to numWilds
SET PROPERTY wildsInfo.startIndex to the current loop index
END IF
RETURN TRUE
END IF
//If we arrive here, there are not enough wild cards to satisfy the base card value.
//start a new base card value with the current card that did not match
SET baseCardValue to the value of the card
IF the card is a wild card
//the base card value can't be a wild card - abort the for loop
END LOOP
END IF
SET numMatched to 1
END LOOP
//unable to satisfy a match - however, one last attempt, if there are remaining wilds, check if number of matched cards on the last loop + num wilds satify
IF numMatched + numWilds GREATER THAN OR EQUALS numToMatch
//there are enough wilds that can satisfy the base card value - success!
//deduct the number of wilds used to satisfy the base card value from the current number of wild cards
SET numberOfWildsToDeduct to numToMatch - numMatched
DEDUCT numberOfWildsToDeduct from numWilds
//update the wilds info
IF wildsInfo is specified
SET PROPERTY wildsInfo.numWilds to numWilds
SET PROPERTY wildsInfo.startIndex to the current loop index
END IF
RETURN TRUE
END IF
//if we arrive here, we were unable to satisfy a match
RETURN FALSE
}
You can see that if wildsInfo
is specified, its properties are updated for subsequent calls to CardMatchUtils.DoCardsHaveSameValue
.
Now, let’s have another look at our previous hand with a wild card in it:
We first sort the cards by descending value, so the sorted hand looks like:
Note: The order of cards by is are arbitrary in this case. The 6c and 6h cards could have been swapped.
Recall that of TwoPair
function calls CardMatchUtils.DoCardsHaveSameValue
twice, specifying the samewildsInfo
parameter each time.
The first time it’s called, the pair of sixes was found. When CardMatchUtils.DoCardsHaveSameValue
completes, it will return true
, because it found a pair of kings. When the code doesn’t find a match, it will first try to use as many wilds available to satisy the match. In this hand, there is one wild, so it was used. The wildsInfo
object was modified as such:
{
numWilds => 0
startIndex => 1
}
The next time CardMatchUtils.DoCardsHaveSameValue
is called, instead of starting at the first index (index 0, the KH) in the array, it will start at index 1, the six of clubs. It will find two cards of the same value, the 6C, and 6H, and return true
. Since both calls to CardMatchUtils.DoCardsHaveSameValue
returned true
, this hand does indeed contain two pairs.
If you have any questions, contact me by using the contact form here, or you can e-mail me directly at cartrell@gameplaycoder.com.
And of course, if you have a card game you need help coding, get in touch with me, and let’s talk!
That’s all for now. In the next article, we’ll go over the poker hand, three of a kind.
Thanks, and I’ll talk to you next time. Take care,
– C. out.