Memory game
I have just completed another project: a memory game inspired by the 1983 DOS Memory game published by International PC Owners (IPCO).
The project consists of a backend written in Go (main.go) and a frontend in HTML, CSS, and JavaScript (index.html, style.css, and script.js).
The idea behind it was to create a simple project with a Go backend running inside my current Docker container that communicates with a frontend. All this with no frameworks, to keep it simple, lightweight, and portable.
As the backend will be running in a container — and I don’t plan to monitor it — I decided not to use any logs or print any messages. In fact, I don’t even use the fmt package. I use two flags: one for the port (8080 when testing locally, and another one inside the container), and one for the path to the static files.
When launching the container, I move the binary to /usr/local/bin/ and the static files to another location. Then I run the binary with the proper flags in the background.
Inside the Go app, I have a large slice of emojis from different topics, referred to as collection in the code. A specific topic is selected randomly (using the rand/v2 package), duplicated into another slice, and shuffled with the Fisher-Yates algorithm.
Communication is done via a JSON object sent through a POST request. What is sent is the status of the game: the board (cards and their order), the revealed cards, the matched ones, the score, the number of moves, whether the game is won, the first card flipped, the second card flipped, and whether it is currently possible to flip a card. One important thing to keep in mind is that there is only one copy of the game state in the backend. This means that if a second user wants to play, they will find an already started game, and both will see strange behavior. As I don’t want to manage multiple games at the same time yet, I’m leaving it as is. I also don’t check the origin of requests, so there is no Cross-Origin Resource Sharing (CORS) because all is done on my server.
The JavaScript file is the other main part of the app. This file communicates with the backend and renders the cards. This is done with async functions and await to call the API and parse the JSON response. I control the animations with setTimeout, using the same durations as defined in the CSS. If I ever change the CSS animation timings, I’ll have to remember to update them in the JavaScript as well — or add an event listener to the card animations. To avoid unexpected behavior from the user, I have a boolean called isProcessing that prevents any actions while an animation is playing (i.e., showing or flipping cards).
I think we can’t really consider this interface a REST API — just REST-like — because it uses HTTP as the protocol, URLs to identify resources, the POST method, and it returns JSON. But it doesn’t implement caching (I don’t need it), and it isn’t stateless — the backend app keeps the game state in memory. So, it’s not fully RESTful, but almost.
I must say I didn’t do it entirely on my own — I used Claude and ChatGPT for the base design. But far from just vibe-coding, I tried to understand every line, question every decision, and change many things to match my preferences. I was also able to find and fix several bugs left by the AI. And I created a favicon for the occasion. Right now, AI is very advanced and can help speed things up — but it’s important to understand what the code does to ensure it’s actually what you want.