Snake, a game that is pre-loaded on almost all mobile phones between the late 90s and early 2000s. The game concept was originated back in 1976. Since then many different variations of the game have been made due to its simple yet addictive gameplay.
This online multiplayer Snake game uses the same WebSocket game engine I wrote previously for my Tank Battle. The simplicity of the game made it a very good candidate for me to learn and try out different AI algorithms.
I also had a lot of fun playing Snake on my old Nokia phone and I think it should be a lot more fun if you can play with friends over the internet.
The goal of the game is to grow your snake as long as possible without hitting your own body, another player or the wall. The white square on the screen is food and each time your snake eat a food it will grow one square longer. Up to eight players can compete at the same time. I could allow more players but it may get a bit crowded.
I have implemented two different AI for the computer controlled players. The first one uses a simple Greedy Algorithm to work out its next move. It can only think one grid ahead but is very cheap to calculate. The second AI extends the first one with DFS (Depth-First-Search) to work out the best path to the food. It is a bit more expensive to calculate but it makes the Snake "smarter" and survive longer in the game (more details in the Technical Details section below).
You can adjust the game speed if you find it is too hard or too easy for you.
At the moment only one game session is allowed on the server. Starting a new game will end the only active game on the server before a new one is started. You cannot start a new game if there are active players in the game.
This game uses .NET Core 3.1 and SignalR on the server side. JavaScript and HTML Canvas on the client side.
Touch screen control is supported. I'm using HammerJS which is the best JavaScript library I came across so far for handling touch gestures.
The Greedy Algorithm I wrote for the AI player uses what I call a path map which is a grid map of the game world the AI uses to navigate. Each grid in the map has a value associated with it. The value of the grid is calculated using an inverse function of its distance to the food. Negative values are assigned to danger zones such as the body of the snake. The AI snake then simply choose one of the three grids next to it with the highest value and move there. The same process is repeated until the snake reaches the food. The average cost of this algorithm is N where N is the number of grid in the path map. In this case 27x18 which is 486.
The problem with this simply algorithm is that it has no concept of path and our greedy snake often trap itself and die. To improve this without significantly increase the cost. I have implemented a DFS function which uses the same path map to "greedily" calculate multiple paths to the food. Being greedy means the neighbour nodes (grids) with the highest value is chosen first when traversing the tree. Because any node in the tree can only be visited once, this greedy DFS algorithm does not guarantee global optimal, but it definitely made the snake a lot less suicidal and the cost of this algorithm is only approximately 2N.
Fun fact: the highest score I have ever seen from the AI snake is 121.
There are still a few things on my TODO list for this project. The main one is snake AI improvement. I always want to try some unsupervised learning and this game seems to be a good candidate for it.
As always, I'd love your feedback. Send me an email or leave me a message on LinkedIn or Blogger.