In this series I'll share my progress with my self-imposed programming challenge: build a Battlesnake in as many different programming languages as possible.
Check the first post for a short intro to this series.
You can also follow my progress on GitHub.
JavaScript
For this second post of the series, I've picked the language you can't really avoid if you're a developer: JavaScript.
JavaScript is everywhere. Not only is JavaScript on every layer of the tech stack (frontend/middleware/backend), but you can also find JavaScript in every software domain. No matter if you want to do command-line tools, creative coding, or machine learning, you can do it in JavaScript. Because JavaScript is so ubiquitous, as a developer it’s the best career choice you can make.
In the past JavaScript has been ridiculed as a language for doing mundane things in web pages. Haters would even say that JavaScript is “not a real programming language”. Fortunately, those days are long gone, and with the rise of TypeScript and mature testing frameworks, JavaScript is ready to be used by larger teams and for larger codebases.
Let's see how these language features help in building Battlesnakes...
Hello, world!
Not a single line of overhead code is needed to put "Hello, world!" on the screen in JavaScript:
console.log('Hello, world!');
This is the Dockerfile for the runtime environment:
FROM node:20-alpine
RUN mkdir /app
WORKDIR /app
COPY snake.js .
CMD ["node", "snake.js"]
And here's the development setup in action:
A basic web server
NodeJS comes with an HTTP server as part of the HTTP interfaces. Implementing a "Request Handler" makes it very straightforward to handle specific HTTP requests.
This is the full code for the web server that implements the GET /
endpoint:
const http = require('http');
const requestHandler = (req, res) => {
if (req.url === '/') {
handleGetMetaData(req, res);
}
}
const handleGetMetaData = (req, res) => {
const response = {
'apiversion': '1',
'author': 'robvanderleek',
'color': '#C00000',
'head': 'caffeine',
'tail': 'curled',
'version': '1.0'
}
res.end(JSON.stringify(response));
}
const PORT = process.env.PORT || 3000;
const server = http.createServer(requestHandler);
server.listen(PORT, '0.0.0.0', () => console.log(`Battlesnake server running on port: ${PORT}`));
Game logic
The game logic is spread out over a number of short functions, nothing fancy.
Below are the two core game logic functions that check if a given position is within the bounds of the board, and if it is empty (so not occupied by any of the snakes on the board):
const freeCell = (board, c) => {
if (c.x < 0 || c.y < 0 || c.x >= board.width || c.y >= board.height) {
return false;
}
const occupied = board.snakes.flatMap(s => s.body).some(p => equal(c, p)));
return !occupied;
}
const equal = (p1, p2) => p1.x === p2.x && p1.y === p2.y;
And this is the complete code in action:
The full code for the JavaScript Battlesnake can be found here on GitHub.
Feedback appreciated!
I hope you like reading along with my coding adventures.
Let me know in the comments below what you think about the code above, or what programming languages you are looking forward to in this series.
Until the next language!