Continuing the series of writing code that recognizing poker hands, you’ll learn how to code a solution for determining if a hand is a straight.
A straight is a hand where all five cards are in order of sequential rank, meaning each card is the next highest (or lowest) than the one before it.
If you’d like to see poker hands that have already been covered, please check the links below.
- Pair (jacks or higher only)
- Two pair
- Three of a kind
- Straight (You are here)
- Flush
- Full house
- Four of a kind
- Straight flush (a non-ace-high straight flush)
- Royal flush (an ace-high straight flush)
Setup
The setup is the same as in the previous articles of this mini-series. A quick rundown of the setup is below, but if you’d like to skip ahead, click here. If you’d like to see the full details of the setup, check out this link.
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
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 Straight
As stated earlier, a straight is a hand where each card is one value (rank) above the next card, or below the next card. An easy way to accomplish this is to first sort the cards by descending value, then check that each card is one less than the one before it.
However, the deck being used includes a “wild card”, which can assume any value. So, this makes the challenge a bit more interesting. 😏
Also, in anticipation of recognizing another poker hand that also uses a straight (the straight flush), you can place the function that you’ll be writing (called CardMatchUtils.AreCardsStraight
) in the in the “utilities” file, CardMatchUtils.js
. This is a file that we’ve been using to assist with matching poker hands in past articles. It contains common functions that can be used across several poker hands, so we don’t have to keep rewriting them for every poker hand.
There are two functions that CardMatchUtils
will use:
CardMatchUtils.SortCardsByDescendingValue
– This function sorts the cards in the hand by descending value. This orders the cards from highest value to lowest.CardMatchUtils.AreCardsStraight
– This function has not yet been written (but that’s what you’ll write in this article!) This function will be used in recognizing both, the straight, and the straight flush hands.
Let’s start with the pseudo code for the straight. It looks like this:
Straight = FUNCTION(hand) {
SORT the hand by descending card value and store in a variable called sortedHand
IF AreCardsStraight(sortedHand)
//we have a straight!
RETURN TRUE
//this hand is not a straight
RETURN FALSE
}
It’s short and fairly straightforward. However, the AreCardsStraight
function mentioned above is where all the action is. It will determine if the cards are straight, and return TRUE
if they are. It takes one parameter, which is a hand (array) of cards, already sorted in descending order, by their values. The pseudo code for the AreCardsStraight
function looks like:
AreCardsStraight
AreCardsStraight = FUNCTION(sortedHand) {
count the number of wild cards in the hand and store in a variable called numWilds (to do this, you can use the `CardMatchUtils.CountCardsByValue` function that was introduced here ( https://gameplaycoder.com/how-to-code-poker-hands-pair-of-jacks-or-higher/#countCardsByValue ) )
set a variable called currentCardValue to 0
FOR EACH card in the sortedHand {
IF this card (the current loop card) is the first card being checked {
set currentCardValue to the value of this card
re-start FOR loop again with next card (in other words, "continue" if you're familiar with for-loops)
}
subtract the value of currentCardValue from the value of this card and store in a variable called valueDifference
set currentCardValue to the value of this card
IF valueDifference EQUALS 1 {
re-start FOR loop again with next card (the condition for the straight is met so far)
}
IF the card is a wild card {
EXIT FOR LOOP (a wild card can assume any card value, including the next value to satisfy a straight, since)
}
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)
}
(check if there are enough wilds remaining to cover the difference in card values)
IF numWilds GREATER THAN 0 AND numWilds GREAT THAN OR EQUALS valueDifference - 1 {
(there are enough wilds, deduct that from the number of wilds available, and straight is still satisfied
numWilds = numWilds - (valueDifference - 1)
} ELSE {
RETURN FALSE (there are not enough wilds to cover the range in value between the two cards - this hand is not a straight)
}
}
(straight is satisfied through all cards - success!)
RETURN TRUE
}
What the AreCardsStraight
function does is take the value of the first card, and compare it to the next card’s value. If the value of the next card is one less, then the straight so far is OK, it continues checking cards. The first two card comparisons look like:
If the next card is a wild card it instead of a card whose value is one less, then the wild card will assume the value of the card with the lesser value, and it continues checking cards. Let’s say your hand is a different one, like this:
After sorting the above hand in descending value order, you’d have:
Once we arrive at the wild card, we can exit the loop. There is no point in further checking cards, because they will all be wild cards, assuming the next value lowest value. And AreCardsStraight
returns TRUE
if the end of the loop is reached. This means the hand is identified as a straight, because each card is one less value than the one preceding it.
Ok, let’s try another example.
Say you had a hand, and after sorting, looked like this:
Once we get to the queen, the next card is a 10, which is more than one value less than the queen (the jack was expected). Since you have one wild card, you can “use” it as the jack, and the straight would still be satisfied.
But wait…
What if THIS was your hand?
To cover the gap in between the 8 and 6, you’d use the wild as a 7. However, there is another gap in between the 6 and 4. Since you used the wild already – and this hand only has one wild – you can no longer substitute another wild for a 3. So hmm, I’ma ‘fraid this hand would not be a straight. 🤔
Have a look at this hand:
This hand would be a straight, because it contains two wilds to cover both gaps, between the 9 and 7, and another one between the 7 and 5. Yes!
The gaps we’ve looked at only cover a value range of one. Let’s say you had this hand (after sorting):
There are two gaps between the 7 and 4 (6 and 5), we’d need at least two wilds to cover them both. Since this hand only has one, it’s not a straight.
One more:
This hand would be a straight because it has enough wilds (at least three) to cover for the 9, 8, and 7. I know I’m getting pretty wild with wilds here, but it illustrates the point of using wild cards to support any hand to find a straight.
Build your own Hand
Like in the last article, you can use the controls below to create your own hand to see if it is a straight or not. It will also recognize previous hands we’ve covered up to this point, which are pairs (jacks or higher), two pair, and three of a kind.
If you have any questions about recognizing a straight hand, or the above interaction, please let me know at cartrell@gameplaycoder.com.
Finally, if you’d like to hire me to program an actual card game for you, please e-mail me, or you may use the contact form here.
That’s it for now. Thanks, and stay tuned as we add more poker hands. The next one will be the flush!
– C. out.
Hands like this would be where the deception part of Poker comes into play. Getting two pairs or three of certain numbers is a bit more straight forward than building up a straight hand of cards, and obviously you don’t want your opponents to know that you’re looking to build this.
That’s why you have to Set your cards face down! 😆
Thank you very much for writing these; they helped me think through algorythms for the hold’m tool I’m developing.
You problably already know this, and maybe you didn’t deal with this in your code, in some Poker varants, there are ‘wheel straights’ where the Ace completes some kind of wheel (circle). In Texas Hold’um, the 5-4-3-2-Ace is a wheel straight.
Since the cards are sorted DESC, I simply checked if A is first card and 5 is second card and then acted like it was 6-5-4-3-2.
Thank you again
Hey visualjc,
Glad you found the information useful.
Actually, I have done that kind of straight, where the ace is the lowest card. When I was first coding the poker-hand matchings, I found the Wiki page to be instrumental.
What kind of hold’m tool are you working on?