Fuelled by passion for the idea, I eagerly set about the basics.
If you're not familiar with Battleship the board game, it's a two-player guessing game.
Each player is presented with two ten-by-ten grids, one in which they can place their fleet of five ships [in secrecy], and another for keeping track of shots taken against the opponent and the result (red for hit, white for miss).
The number of grid cells that each ship occupies is determined by the type of ship; aircraft carrier (5), battleship (4), submarine (3), destroyer (3), patrol boat (2). Ships can be placed on the grid either horizontally or vertically.
Players take it in turns to 'shoot', reading aloud a single coordinate to the opponent for them to feedback if it was a hit or miss. Once all cells of a ship have been hit, the ship is sunk. If all the player's ships are sunk, the game is over and their opponent wins.
I could have blown away weeks if not months on this project. Understandingly this wasn't an option so to assist in the development I utilised the following third-party libraries:
- Mustache: Nice, easy-to-use templating system for the front-end.
- PeerJS: A helping hand when it came to the peer-to-peer connectivity, wrapping up the complex WebRTC functionality in a nice easy-to-use manner.
While most of the game came together pretty easily, there were some complexities and challenges along the way. I may have lost some sleep to the following:
Not the biggest of pains with this project, but an unsuspecting one when you really start to break down the criteria and work through the logic.
As part of the game interface, a ten-by-ten grid is present allowing the user to plot five different ships on their local board. Hovering over the grid will give a representation of where the ship is going to be placed, and on click the ship will be plotted in the respective position (providing constraints are met). The orientation of the selected ship can be toggled using the space bar, and any previously plotted ship can be removed by double clicking it.
It is to be ensured that ships can not be plotted [partially] outside of the grid, and that they must not overlap each other (with any conflicting squares showing in red).
Those avid Battleship board gamers would be familiar with the traditional set-up, and how easy it was to sneak at the opponents ship positions, gaining a quick advantage and easily wiping out their fleet. I wanted to avoid that from happening; assuming you're not playing right next to the opponent who can easily resort to the same tactics, this shouldn't be too difficult.
The solution was really quite simple, validate the shot on the opponents machine and that way we won't need to store their coordinates locally. This did have a negative affect by causing some lag in the solution, with every shot having to be sent across the internet and pending a response; a small inconvenience but unavoidable.
Subsequently, we had to prevent this functionality from being abused. What if I was to open up the console and send a bunch of coordinates to the remote computer for validation when it wasn't my turn, would it still process those coordinates and let me know if they were hits or misses? Thankfully no, the remote computer has context of who's turn it is, and will just ignore any requests of this nature.
Perhaps the biggest woe of the solution, but fundamental to the whole concept. A complexity of both client and server side development.
PeerJS provided a lot of ground work here, even a handy Node JS library to be run on the server with easy to install instructions. The complications came because at the time I was relatively new to the server configuration side of things which meant a steep learning curve.
With the package installed and running, it needed exposing to the internet for use with the client application; requiring some proxing and SSL configuration to be in place. Once tamed, the library worked pretty well with only the odd temperamental issues associated to local network constraints.
This meant I could progress with the client side, slowly grasping the library until it was fluid in my mind and way of working. For testing I needed another peer (another tab in Chrome); constantly switching between the two to mitigate any mishaps and get a feel for the game play.
When it became second nature, it was simple enough to pass through things like media streams and instructions, making for really painless development then onwards.
The Finished Project
After a manic week, the solution was in a state ready to be submitted. While there are areas of improvement (like the interface), I can't fault the project for what was achieved in the time and the amount I learned from doing it. I was further impressed when the result came back from the lecture, which gave me the confidence to host the solution for others to use.
I would provide a run through, but to avoid a lengthy eye-watering post I encourage you to explore the live demo for yourselves.
I thoroughly enjoyed developing this project, with the added bonus of playing against my brother at home for some last minute testing and [well-earned] procrastination. I hope you enjoy it too.