(The complete source code for this poker game can be found here)

In our last installment, we created the cards module in Node.js which had the following responsibilities:

  • Define the structure of a card
  • Create a deck of 52 cards
  • Clone the deck and shuffle
  • Translate a string like “six of diamonds” into a card object

Now we’re going to visit the next part of this game, the hands module.  A hand in poker is what decides if you have won the game.  In Hold ‘Em, your hand is comprised of the best five cards between your pocket cards and the five shared cards.

Let’s go ahead and add the following code which provides a numeric score (0-8) of the possible hands a player can receive.

// hands.js
const HIGH_CARD = 0;
const PAIR = 1;
const TWO_PAIR = 2;
const THREE_OF_A_KIND = 3;
const STRAIGHT = 4;
const FLUSH = 5;
const FULL_HOUSE = 6;
const FOUR_OF_A_KIND = 7;
const STRAIGHT_FLUSH = 8;
const ROYAL_FLUSH = 9;

Now we’re going to create a function that takes an array of cards (could be between 2 and 7 total) and picks the strongest hand using only 5 of those cards.

The flow will look like this:

// hands.js
function getBestHand(cards) {
 var hand = getRoyalFlush(cards);

 if (!hand) {
   hand = getStraightFlush(cards);
 }

 if (!hand) {
   hand = getFourOfAKind(cards);
 }
 if (!hand) {
   hand = getFullHouse(cards);
 }

 if (!hand) {
   hand = getFlush(cards);
 }

 if (!hand) {
   hand = getStraight(cards);
 }

 if (!hand) {
   hand = getThreeOfAKind(cards);
 }

 if (!hand) {
   hand = getTwoPair(cards);
 }

 if (!hand) {
   hand = getPair(cards);
 }

 if (!hand) {
   hand = getHighCard(cards);
 }

 return hand;
}

It’s a fairly straight-forward example.  Starting with the biggest hand, we will work our way down until we find a hand.  If we make it all the way through without finding a straight, flush, or pair then we will get our high card and that will be our hand.

Speaking of hands, the hand itself is an object as well.  Let’s look at the implementation of getHighCard() to see how we create a hand object.

function getHighCard(cards) {
   var idx = -1;
   for (var i = 0; i < cards.length; i++) {      if (cards[i].value > idx) {
       idx = i;
     }
 }
 return {value: HIGH_CARD, cards: [cards[idx]]};
}

This function loops through the cards in the hand (it doesn’t matter how many) and checks for the index in the array of the highest value.  After it has checked all the cards, it returns a hand object which contains the array of cards relevant to this hand (in this case, just one card), and a hand value (HIGH_CARD=0).

If you’d like to see how I’ve implemented each of these functions, check out the source here.  The functions themselves are fairly easy and have their own little specifications.

// Let’s play poker!

Now that we’ve implemented code that can take an array of cards and translate it into a poker hand, let’s go ahead and create our game.

I’ll create a simple file called game.js which will be our executable.

// game.js
var players = [{name: "John"}, {name: "Paul"}, {name: "George"}, {name: "Ringo"}];
var deck = cards.shuffle();

// who's winning at any given moment
var bestPlayer = null;
var bestHand = null;

In the example above I’ve gone ahead and created my players and I’ve shuffled a fresh deck of cards from the cards module.

Now let’s deal our pocket hands to our players.

// game.js
for (var i = 0; i < players.length; i++) {
 players[i].pocketCards = deck.splice(0, 2);
}

Splice in JavaScript is a handy function for removing elements from an array.  Since the deck is shuffled, I can just pull cards off the top in the same manner a dealer in Las Vegas might grab the next card off a stack.

(Note: technically in poker you’re supposed to hand out one card per person and burn a card in between each phase of the game.  This would be a simple, but unnecessary feature in this demonstration.  Feel free to fork and extend this functionality to deal more like how a human would deal.)

Since this is Hold ‘Em, we need an array of community, or shared cards.

var commonCards = [];

Common cards will act like a player’s pocket cards.  We can just splice() cards out of our deck and make them available to everyone.  Now, let’s create a simple function to determine who has the best hand at any point during the game.

function getPlayerWithBestHand(){
  // reset
  bestPlayer = null;
  bestHand = null;

 for(var i = 0; i < players.length;i++){    var playerCards = players[i].pocketCards.slice(0);    playerCards.push.apply(playerCards, commonCards);    var hand = hands.getBestHand(playerCards);    if(!bestPlayer || !bestHand){      bestPlayer = players[i];      bestHand = hand;      continue;    }    if(hand.value > bestHand.value){
     bestPlayer = players[i];
     bestHand = hand;
     continue;
   }

 }

 return bestPlayer;
}

This function creates a new array of cards containing the players’ pocket cards as well as the community cards and passes them to our getBestHand() function from the hands module.

Then each hand is checked by it’s value (ranking of 0 – 8) against other player’s hands. The player with the best hand is returned.

(Note: again, this can be extended to check the high card (the last card in the hand’s card array, but it’s not necessary for our demo here)

And we’ll create one more function that can quietly announce who’s winning at any given moment.

function echoBestPlayer(round){
 getPlayerWithBestHand();
 console.log(`After the ${round}, ${bestPlayer.name} is winning with a ${hands.getName(bestHand.value)}`);
}

To wrap up, we’ll deal the flop, turn, and river, and we’ll call echoBestPlayer() after each deal to keep us updated how the game is going.

echoBestPlayer('deal');  // who's winning after the initial deal?

// now the flop
commonCards = deck.splice(0, 3);
echoBestPlayer('flop');

commonCards.push.apply(commonCards, deck.splice(0, 1));
echoBestPlayer('turn');

commonCards.push.apply(commonCards, deck.splice(0, 1));
echoBestPlayer('river');d

Now we’ll run our game.

node game.js

And we should see something like this:

After the deal, John is winning with a high card
After the flop, Ringo is winning with a two pair
After the turn, Ringo is winning with a two pair
After the river, George is winning with a two pair

Let’s run it again!

After the deal, John is winning with a high card
After the flop, George is winning with a two pair
After the turn, George is winning with a two pair
After the river, George is winning with a full house

// Summary

In this course, we successfully constructed a working Texas Hold ‘Em poker game with very little code (around 500 lines).  I’m sure it could be done with less, but I made a few choices along the way to make the examples more verbose.

Anyway, I sincerely thank you for following along with us and I hope you’ll return for future courses.   I’d love to hear from you.  Send me your thoughts above on my contact page (Yes I read all of them!).  Till next time!