(The complete source to our Node.js Texas Hold ‘Em game can be found here)

// Introduction

In this course we are going to build a Texas Hold ‘Em simulator.  If you are one of the few people on earth not familiar with Hold ‘Em, the rules can be found here.

The game should take a number of players and deal each player two cards (“pocket cards”).  Then the dealer should deal 3 community cards that are shared amongst the players (“the flop”).  Then another shared card is dealt (“the turn”) and finally one last card (“the river”).  In a real game players would make their bets in between each of these rounds of dealing.  Maybe later we’ll simulate some betting based on the perceived strength of the player’s hand, but for now we’re just going to work on dealing and deciding who has the best hand.

// Our project

We are going to use Node.js to build our Texas Hold ‘Em simulator.  And you’ll be surprised to see how little code it takes to make a fairly complex card game.  Tests for our project will be written in jasmine.

We will only need three files to build this game.

  • cards.js –  A module that knows the value/suit of cards, how to shuffle, and how to translate a string like “four of clubs” to a numeric value.
  • hands.js – A module that knows how to look at an array of cards and give the hand a numeric ranking.  For example, a straight flush has a higher ranking than a pair of clubs.
  • game.js – This will be our main entry point, where the game can be launched.

// Defining cards

In cards.js we will start describing the 52 cards in our deck.  Cards have important attributes such as the suit and their numerical value.

Note: Aces in Texas Hold ‘Em are a special card that can be a low value on a straight (A2345) or the high value of a straight (10JQKA).  In this tutorial we will be using aces as the second example, a high value of a straight.  You are welcome to extend this engine further if you would like to support both usages of the ace cards.

// cards.js
const CLUBS = 'clubs';
const HEARTS = 'hearts';
const DIAMONDS = 'diamonds';
const SPADES = 'spades';

const SUITS = [CLUBS, HEARTS, DIAMONDS, SPADES];

const CARD_NAMES = [null, null, "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "jack", "queen", "king", "ace"];

I’ve defined the suits available and put them in an array.  I’ve also created an array of card names.  The purpose of this is so I can easily translate phrases like “six of diamonds” to a numerical value of 6 and the suit “diamonds.  Notice I have no card names for position 0 and 1.  I could use ace as position 1, but I’m not going to in this tutorial.

// Creating a prototype deck

Next I’m going to create an array told hold our 52 cards.

var cards = [];

Then I’m going to loop through our card names and suits and create the 52 cards for our game.

SUITS.forEach((suit) => {
    for (var i = 2; i <= 14; i++) {
        cards.push({value: i, name: CARD_NAMES[i], suit: suit})
    }
});

Using this enhanced forEach() I’ve successfully created my deck.  Now I’m going to need a handy shuffle function.  For our game, when we shuffle, what we actually want to do is shuffle a clone of our prototype deck.

Cloning in an array in Node.js is simple.  The code below will create a new array just for our game.  The original cards array will go untouched.

var dealCards = cards.slice(0);

Now we can create our handy shuffle function.  I’m going to use the Math.random() to help me shuffle my deck.  We will swap the position of two cards in the deck as we loop through each card, ending up with a randomly shuffled deck of cards.

function shuffle() {
    var dealCards = cards.slice(0);

    for (let i = dealCards.length; i; i--) {
        let j = Math.floor(Math.random() * i);
        [dealCards[i - 1], dealCards[j]] = [dealCards[j], dealCards[i - 1]];
    }
    return dealCards;
}

// Tests!

Let’s write some tests.  As I said before we’re using jasmine for our testing suite.  And if you’ve never used jasmine before, getting started is as easy as running the following commands:

npm install -g jasmine
jasmine init

Jasmine will create a spec/ folder in our project and we can create a test by simply calling a file .spec.js.  So to test our cards.js file, let’s create spec/cards.spec.js.

Behavior-driven design tests (or BDD) are created using some functions provided by jasmine.  Yes I know I should have written these tests first, but for the purposes of this tutorial, I thought it would be easier to show how I’ll test the cards.js file later.

Let’s write a test to ensure our deck has 52 cards.

var cards = require('../cards');
describe('cards', () => {
 it('has 52 cards', () => {
   expect(cards.cards.length).toEqual(52);
 });
}

Now to run our tests we simply executed the “jasmine” command with no parameters.

Let’s add another test to ensure that our cards.js file has a shuffle function defined.

it('contains a shuffle function ', () => {
    expect(cards['shuffle']).toBeDefined();
    expect(typeof cards['shuffle']).toEqual('function');
});

If you got an error that said that cards or shuffle were undefined, check to make sure you exported our prototype cards array from cards.js.  Your export function at the end of cards.js should look something like this.

// cards.js
module.exports = { cards:cards, shuffle:shuffle }

// Summary

In this installment we learned that we can create a Texas Hold ‘Em game with only three files (cards.js, hands.js, and game.js).  We created the blueprints for our game by adding card definitions to cards.js.  Then we created some tests to ensure our deck had 52 cards and that we had a shuffle function defined.

In our next course we’ll talk about how to rank poker hands.