Minesweeper Battle: Inspiration
Minesweeper is a classic, nostalgic, game that has stood the test of time. But while it may be fun, it can boring alone. As a single player game, the grid is fixed at the very beginning, and involves a slow, systematic deduction process to find all the mines in the grid. What if we could modify this time-honored game to be not only multiplayer, but also dynamic and competitive; combining logical deduction, with speed, accuracy, and a bit of luck? Let us introduce Minesweeper-Battle, a online version of minesweeper where players are competing against each other in real time. While we preserve all features of the original game, we also added new features to make our online version more competitive.
Minesweeper Battle: How to Play
Our game preserves all the features of the classic minesweeper; first click will open a large revealed patch, correctly flag all landmines for the win, and revealing a mine ends the game with a loss.
However, what’s special about our game is of course its online competitive multiplayer features: every user is playing against at least one other player in real time. Additionally, when a player correctly flags a mine, the player will send a “disruption” to a random opponent. That is, a random-sized patch on the opponent’s grid will be reset; opened blocks will be masked again, flags will be taken down, and placements of landmines and the adjacency numbers will be updated too.
On the main game page, the user will see their game grid as well as their opponents’ grids. When an opponent finishes their game, their grid will change color depending on whether if it was a win or lose. When a player finishes their game, a leaderboard will be shown with the rankings of all the users in the game.
To identify the users in a game, each player is prompted to enter a username on first entry into the application page; they’ll have the option to either create a game or join an existing game, and they can immediately start playing. If a player loses connection to the game, their game state is always persisted on the server, so they can join back into the game at any time.
How we built it
The application was built using React (in Typescript) and Convex, with Convex doing a lot of the heavy lifting with synchronization and real-time updates. We created all of the UI and game design from scratch, first building a playable single-player Minesweeper game, before adding a database and real-time synchronization utilizing Convex.
Throughout the gameplay, occasional mutation requests are sent to the server to ensure that the server game state is kept up to date, making sure that every player is able to see their opponents’ game states in real-time. This synchronized game state is used to display other information like rankings, whether opponents have won or lost, etc.
Challenges
One of the first challenges we faced in this project was with the game design; we wanted a game that was interesting to implement, but also interesting to play. The interactions between players needed to be well thought out, and we decided upon sending “disruptions” to opponent grids when a user correctly flags a mine, inspired by Tetris multiplayer, where users can send “garbage lines” to their opponents upon a line clear.
Further, as a part of the design of the game, we had lengthy discussions about what aspects of the game logic should be implemented in the frontend, and which aspects should be implemented in the backend. Implementing the game logic in the backend would provide more fine-grained and guaranteed synchronization, but implementing the game logic in the frontend would reduce latency and allow for more responsive gameplay. In the end, due to the WiFi connectivity issues in the venue, the latency benefits outweighed any synchronization benefits, and we opted to implement the bulk of the game logic in the frontend, with the backend simply managing the persistence of game and grid states.
The process of learning Convex and the workflows involved was also challenging, but paid off quite well in the end—it’s a new way of approaching full stack development, and we found Convex to be extremely useful in simplifying and speeding up the development process after we learned about all of its features, especially with the real-time synchronization of game states.
Another challenge we faced was the presence of race conditions in the queries and mutations; combined with the React lifecycle, we had several race condition bugs where the order of query resolution caused certain parts of the game to be out of date, causing weird behavior. After painful debugging and careful thought, we eventually managed to resolve all of the race conditions we faced during testing.
What we learned
Everyone on the team was new to Convex, so we learned how to use queries, mutations, tables, and many other Convex functionalities to create a robust backend for our game. In order to maximize the learning experience of the hackathon, we assigned members of the team to parts of the project that they were NOT familiar with. For example, a member of the team has also had no experience with React or Typescript, so naturally we decided to assign him to work on the frontend, and he was able to learn a lot about web development.
Aside from tools, we generally learned a lot about what it is like to create real-time applications and synchronize the experience between multiple players. In an effort to reduce latency, we moved most of the game logic to the frontend, and so we needed to make sure that despite potential differences in the game state between players, they can still have a smooth experience and stay updated on the status of other players. Many bugs that we encountered involved race conditions and we had to write the code to be resilient to such potential problems.
Finally, we learned a lot about game design, and a lot of the code we wrote in later stages of the project involved adding components to make the game experience more fun to play, and the competitive experience between players more balanced. For example, we realized that one way that players can abuse the disruption system is by spamming the flag on a known mine to send multiple disruptions for a single mine. We therefore had to add an edge case, and other cases like this, for situations where players could try to outsmart the game.
Accomplishments that we're proud of
We are proud of pushing out a fully functioning product (from design to implementation to hosting) with limited time. We are also proud of how despite assigning each team member the part of the project we are not familiar with, all four of us were able to learn efficiently, and contribute a notable amount to the project.
Futures for Minesweeper Battle
There are a lot of ways to extend this project; at the moment, we have a working prototype of the main gameplay loop and the new features required for multiplayer Minesweeper to function. In the future, the game could be enhanced with more thought into game balancing, improving the game design to increase the amount of fun and engagement in the user experience.
Additional features like lobbies and settings for Minesweeper difficulties would be interesting to add, and even incorporating AI to make bot opponents (even adaptive bots corresponding to the player’s current experience level).
The UI could also use some improvements, with more specialized graphic design and styling to make the site look sleeker; more GUI elements could be added to provide more pertinent information to users during the game play as well (ex. number of mines remaining, who you’re sending disruptions to, etc.)
The application could also be improved with the addition of security, authentication, and authorization; currently, we identify users only through a single username string, with no extra checks. This means that any user can impersonate any other user, and users cannot have the same usernames. Adding additional authentication mechanisms and actual user accounts could make the game feel a lot more official and polished.
Built With
- convex
- css
- html
- react
- typescript
- vercel
Log in or sign up for Devpost to join the conversation.