Build a Snake Game in functional JavaScript - Part 0
Tags: functional, beginners, codenewbie, javascript
Published: 2020-03-25 21:41:01

If you are interested in reading this article in Spanish, check out my blog [The Developer's Dungeon](https://www.patferraggi.dev/blog/2020/mar/functional-snake-0/)

If you have been following my latest articles you probably know I have been trying to learn functional programming. 
At first, I was trying to learn `Haskell` by reading this [book](https://haskellbook.com/), learning Category Theory from this [book](https://github.com/hmemcpy/milewski-ctfp-pdf/) and even trying to build a [Snake Game](https://en.wikipedia.org/wiki/Snake_(video_game_genre)) in `Haskell`

![Snake Game in Haskell](https://dev-to-uploads.s3.amazonaws.com/i/c8s3lcbr42qgiqd1wmor.jpeg)

It is fair to say that I was miserable, I was making very small progress and dealing with incredible amounts of frustration, I realize then that the problem was I was trying to tackle too many things at once.

I was:

1. Trying to learn Haskell's Syntax
2. Trying to learn Functional Programming
3. Trying to build a Snake Game.
4. Trying to learn a new IDE and Dev Tools.

Mainly what was happening was that I was getting stuck constantly due to not understanding how to do basic things (like writing to the console) or not knowing the correct names for the common patterns in functional programming. So, I decided to change my approach. I went to something I knew, `JavaScript`. I am not an expert but I use it every day, I also had 2 books and a course prepared.

* [Mostly adequate guide to Functional Programming](https://mostly-adequate.gitbooks.io/mostly-adequate-guide/)

* [Functional-Light JavaScript](https://github.com/getify/Functional-Light-JS)

* [Functional-Light JavaScript V3 course on Frontend Masters](https://frontendmasters.com/courses/functional-javascript-v3/)

After going over them and doing some small practices I decided to take on again the challenge of building the game, now in a language I knew, so if at one point I got stuck with the `functional way` I could always default to doing classic `JavaScript`. In this tutorial, I am gonna guide you while building the game, take this not as a perfect example but as a journal of my steps into the `functional way`.

----

I took the idea of building this game from [Christopher Okhravi 's explanation](https://www.youtube.com/watch?v=poVMBGe1THE) and decided I am gonna create this small game in multiple functional programming languages so I could check which one I liked the most and then dive deep into it. First, let me make clear that I find Christopher's content and way of explaining things amazing, but I encountered two problems with this video:

1. Since I lacked the functional background I couldn't follow the code he wrote or understand why he had built stuff in a certain way so I just decided to take the matter into my own hands, build it on my own so I could do a comparison later.
2. Since I don't know the common patterns for functional programming, I couldn't deal with having to build the base functions and at the same time building the game.

To solve both problems I decided to go with [Ramda.js](https://ramdajs.com/docs/), this library implements a lot of the functions you would find in a fully functional language, they are all `pure` and they all come `curried` by default.

--- 

Sorry for the long introduction, I wanted to explain what guided my decisions and how did I got to this point. Let's start.

In this first part of the series, we are gonna try to build the 3 basic elements of the game: Map, Snake(represented by `X` 's), and Apple(represented by `O`) and display them in the console. So we get something like this: 

![Final result](https://dev-to-uploads.s3.amazonaws.com/i/luqvnm14kryoxlgedlvl.png)

## The foundations, a point.

The map is a two-dimensional array with an `X` and `Y` coordinate, we are gonna call this type a `point` and we are gonna define it as follows:

```javascript
const point = (x, y) => {
  return {
    x: x,
    y: y
  };
};
```

From this, we can create the `snake` which is nothing more than a collection of `points`, the `apple` which is just a single `point` in the `map`. These 2 things will be part of the `state` of our game.

```javascript
/// I chose an arbitrary position for our apple and snake
const initialState = {
  snake: [point(2, 2)],
  apple: point(5, 5)
};
```

## Displaying the world

In our case, the UI is gonna be the `terminal`, we want that to be decoupled from the logic of our game, so we leave the previous code in a module called `snake.js` and we create a new module called `ui.js` where we can start creating the code that will display a `map`, the initial `snake` and the initial `apple`.

### The Map

As we said before the `map` is just a two-dimensional array filled with `.`, how can we do that?

We import `ramda`

```javascript
const r = require("ramda");
```

We create a function that receives, the number of rows, the number of columns and the initial `state` of our game(we are gonna use that `state` later to draw the `apple` and the `snake` on top of the `map`).

```javascript
const createWorld = (rows, columns, state) => {
  // We create a function that will create an array of a certain length 
  // with the '.' on every element by partially applying ramda.repeat
  const repeatDot = r.repeat(".");

  // we create an array with the length of `columns` with all dots in it, 
  // then we map over it and for every element we insert a new array 
  // with the length of rows with all dots in it.
  return r.map(r.thunkify(repeatDot)(rows), repeatDot(columns));
};
```

### The apple

Let's continue with the `apple` since it is just a single `point`. We could start by doing this:

```javascript
const addApple = (state, map) => {
  map[state.apple.x][state.apple.y] = "0";

  return map;
};
```

The function would receive the `map` and the `state` and it would add a `O` in the position the `apple` should be. This works, but I know is not "very functional" since I am mutating an array in place. Instead, we could use a function called `adjust` that will receive an _index_, a _string_, and an _array_ and it will copy that _array_ but replace the element in the _index_ by the _string_ it received as a parameter. So let's create a helper function for updating our `map`.

```javascript
// This function will take a string and a point, it will first replace `X` 
// coordinate of the array and then replace the `Y`.
const update = r.curry((str, point) =>
  r.adjust(
    point.y,
    r.adjust(point.x, () => str)
  )
);
```

You probably noticed something strange in this function, we are not passing the `map` anywhere, this is because we are delaying evaluation, instead of passing the `map` we are returning a function that will receive the `map` and produce a result, I know this looks weird, but it will become evident in a moment, trust me.
Now that we have the `update` helper function we can refactor our `addApple` function like this:

```javascript
const addApple = state => update("O")(state.apple);
```

Our `addApple` function will take the `state`, call the `update` function and return the function that will do the work when passed the `map`. 
So, let's try to draw the `apple`, for that, I imagined that it would be like an assembly line. First, we create the `map`, then we draw the `apple` on top, so we are gonna make use of a function very common in Functional Programming called `pipe`.

```javascript
const createWorld = (rows, columns, state) => {
  const repeatDot = r.repeat(".");
  const map = r.map(r.thunkify(repeatDot)(rows), repeatDot(columns));

  return r.pipe(addApple(state))(map);
};
```

With pipe what we do is set up a number of functions that will be run one after the other passing the return value of each to the next function. This seems pretty much what we want to do right? first, draw the `map`, then draw the `apple` on top and lastly draw the `snake`.

### The snake

So now that we have a way to draw on top of the `map` let's extend that to draw the `snake`

```javascript
const addSnake = state => r.pipe(...r.map(update("X"), state.snake));
```

So what are we doing here? well, we are creating a function that will put an `X` on every single position of the `snake` and then returning all those changes in the form of a single function by partially applying `pipe`. When that function gets executed and receives the `map` is gonna do all the changes in a chain. Now our `createWorld` will look like this:

```javascript
const createWorld = (rows, columns, state) => {
  const repeatDot = r.repeat(".");
  const map = r.map(r.thunkify(repeatDot)(rows), repeatDot(columns));

  return r.pipe(addSnake(state), addApple(state))(map);
};
```

Now how can we display that? let's create a `displayWorld` function

```javascript
const intercalate = r.curry((str, xs) => xs.join(str));

const displayWorld = matrix => {
  console.clear();
  console.log(intercalate("\r\n", r.map(intercalate(" "), matrix)));
};
```

This function is nothing magical, it just takes the `map`, logs every line by putting a space in between each element, and when it gets to the end it breaks the line, I did extract the logic of joining to a helper function to make it more readable.

Finally, we can put our initial `state` together and show it in the console

```javascript
const display = (rows, columns, state) => {
  return r.pipe(createWorld, displayWorld)(rows, columns, state);
};

display(15, 15, Snake.initialState);
```

![Final result](https://dev-to-uploads.s3.amazonaws.com/i/luqvnm14kryoxlgedlvl.png)

I know, we really need to get someone to work on the graphics if we are gonna try to sell this game right?

----

I hope this example wasn't too hard for you guys, I tried my best to explain my thought process when creating the `UI`.

In the following post, we will try to cover all the logic for moving the `snake`, eating the `apple`, restarting the game and losing. 

If you liked this article please don't forget to share or comment, if you have any doubts about the code don't doubt to ask me in the comments. You can also check the source code [here](https://github.com/Raagh/functional-snake-game) :smile:.