# Online card game with node.js and socket.io - Episode 1

Source: https://tpiros.dev/blog/online-card-game-with-node-js-and-socket-io-episode-1

I love challenges and learning new technologies. My JavaScript knowledge pretty much stopped at jQuery. I thought that was it, there's nothing more to know beyond `.append()`, `.click(function ())` and so on. I was wrong. I've set myself a challenge: learn the latest and greatest of JavaScript by writing an online, multiplayer game using Node.js and [Socket.io](http://socket.io). I'm going to document the steps as I go through the learning process.

The code for part 1 won't be on GitHub. It's in a sketchy format that'd probably confuse people, and it'll likely change as I keep developing. I'm not revealing the actual card game yet. That'll go public once the game is live.

Let's start with the basics: setting up and running Node.js, then installing [Socket.io](http://socket.io). I followed the official [instructions](http://nodejs.org/download/) for both ([Socket.io setup](http://socket.io/#how-to-use)). Done. Now let's write some JavaScript.

The approach I'm following is elementary. Since this is a card game, we need to produce a deck, shuffle it, draw cards, and play cards. That's it for now. Logic (when to play a card, which player can play what) comes later. Much later. To make this a bit "Node-ish", I'll create two JavaScript files: `game.js` (containing the game's logic) and `index.js` (running a few tests).

The card game will use 52 cards from a [French pack or Anglo-American pack](http://en.wikipedia.org/wiki/Standard_52-card_deck). For those unfamiliar: there are 4 suits (Hearts, Diamonds, Spades, Clubs), numbers from 2 to 10, and figures (Jack, Queen, King, Ace). (I can't resist mentioning the [Ace of Spades](https://www.youtube.com/watch?v=1iwC2QljLn4).)

The simplest way to represent these cards is numbering from 1 to 13 for each card (1 is an Ace, 11-12-13 are Jack-Queen-King) and appending a letter: H for Hearts, D for Diamonds, and so on. The Ace of Spades becomes 1S. The Jack of Hearts becomes 11H.

Without further ado, here's the code. First, we create a pack of 52 cards and add a method to shuffle it. Shuffling is a bit tricky because JavaScript doesn't ship with a good array shuffle method, so we need the [Fisher-Yates algorithm](http://en.wikipedia.org/wiki/Fisher-Yates_shuffle).

```javascript
function createPack() {
  var suits = new Array("H", "C", "S", "D");
  var pack = new Array();
  var n = 52;
  var index = n / suits.length;

  var count = 0;

  for (i = 0; i <= 3; i++) {
    for (j = 1; j <= index; j++) {
      pack[packCount++] = j + suits[i];
    }
  }
  finalPack = pack.concat(pack);
  return finalPack;
```

Two more functions needed: drawing a card and playing a card. These are simple array operations.

**Update** After testing, I noticed that `concat()` doesn't work on arrays sent as references (in this case the "hand" array), so I switched to `push.apply()`. See [the MDN reference](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/concat) for details.

```javascript
function draw(pack, amount, hand, initial) {
  var cards = new Array();
  cards = pack.slice(0, amount);

  pack.splice(0, amount);

  if (!initial) {
    hand.push.apply(hand, cards);
    //hand.concat(hand);
  }

  return cards;
}

function playCard(amount, hand, index) {
  hand.splice(index, amount);
  return hand;
}
```

Finally, we need to export all these functions (making them available to other JavaScript files). The last lines of `game.js` should be:

```javascript
exports.createPack = createPack;
exports.shufflePack = shufflePack;
exports.draw = draw;
exports.playCard = playCard;
```

Time to test. Create `index.js` and add the following content. Note the highlighted row where we pull in `game.js`:

```javascript
var game = require('./game');

var pack = game.createPack();
var myPack = game.shufflePack(pack);
console.log('Size of pack before draw: ' + myPack.length);
console.log('Drawing 5 cards.');
var hand = game.draw(myPack, 5, '', true);
console.log('Size of pack after draw: ' + myPack.length);
console.log('Cards in hand:');
console.log(hand);
console.log();
console.log("Now I'll draw a card");
var draw = game.draw(myPack, 1, hand, false);
console.log(draw);
console.log('Size of pack after drawing one card: ' + myPack.length);
console.log('So all cards in my hand are: ');
console.log(hand);
//////
console.log();
console.log("Now I'll draw 3 cards");
var draw = game.draw(myPack, 3, hand, false);
console.log(draw);
console.log('Size of pack after drawing 3 cards: ' + myPack.length);
console.log('So all cards in my hand are: ');
console.log(hand);
console.log();
console.log("I'll play one card now, dropping the last card.");
console.log();
var lastCard = hand.length - 1;
console.log("Last card's index: " + lastCard);
var newHand = game.playCard(1, hand, lastCard);
console.log('Cards in my new hand are:');
console.log(newHand);
console.log();
console.log("I'll play the third card:");
var thirdCard = 2; //index of 3rd card is 2
console.log('Index of the third card: ' + thirdCard);
var evenNewerHand = game.playCard(1, newHand, thirdCard);
console.log('Cards now in my hand hand are:');
console.log(evenNewerHand);
console.log();
console.log('Size of pack should not change: ' + myPack.length);
```

Run `node index.js` from the command line. The result should look something like:

```
# node index.js
Size of pack before draw: 52
Drawing 5 cards.
Size of pack after draw: 47
Cards in hand:
[ '6H', '3H', '5S', '13H', '8D' ]

Now I'll draw a card
[ '8H' ]
Size of pack after drawing one card: 46
So all cards in my hand are:
[ '6H', '3H', '5S', '13H', '8D', '8H' ]

Now I'll draw 3 cards
[ '2H', '7C', '7S' ]
Size of pack after drawing 3 cards: 43
So all cards in my hand are:
[ '6H', '3H', '5S', '13H', '8D', '8H', '2H', '7C', '7S' ]

I'll play one card now, dropping the last card.

Last card's index: 8
Cards in my new hand are:
[ '6H', '3H', '5S', '13H', '8D', '8H', '2H', '7C' ]

I'll play the third card:
Index of the third card: 2
Cards now in my hand hand are:
[ '6H', '3H', '13H', '8D', '8H', '2H', '7C' ]

Size of pack should not change: 43
```

That's it for now. Simple so far. Next time, we'll add a websocket using [Socket.io](http://socket.io) and keep building. Until then.
