This project was built as part of The Odin Project: JavaScript course in order to practice what I've learned about test-driven development in JavaScript.
Implement the classic game 'Battleship' in the browser using test-driven development.
I will only perform unit testing on application functionality; no integration testing or testing the DOM.
For an explanation of the rules of the game: https://en.wikipedia.org/wiki/Battleship_(game)
-
Create the
Ship
class/factory- A
Ship
instance will have the following properties:- length
- number of times it's been hit
- Ships will have a
hit()
method that increases the number of 'hits' in that instance - Ships will have an
isSunk()
method that calculates whether it is considered sunk based on its length and the number of hits it has received - Consider: I only need to test an object's public interface. Only methods or properties that are used outside of a
Ship
instance need unit tests. (This follows the rule: do not test private methods.)
- A
-
Create a
Gameboard
class/factory- A
Gameboard
instance will have the following properties:- grid size: num of cells in x and y axis
- board data: array of 100 Cell instances
- ships: array of all ships placed in gameboard
- Gameboards will be able to place ships at specific coordinates by calling the
Ship
class/factory - Gameboards will have a
receiveAttack
function that takes in a pair of coordinates, determines whether or not the attack hit a ship, and then either sends thehit()
function to the appropriate ship or records the coordinates of the missed shot - Gameboards will keep track of missed attacks so they can display them properly
- Gameboards will be able to report whether or not all of their ships have been sunk
- Consider: I have not yet created any user interface. I should know my code is coming together by running the tests. I should not be relying on
console.log
or DOM methods to make sure my code is doing what I expect it to.
- A
-
Create a
Player
class/factory- Players take turns playing the game by attacking the enemy Gameboard
- The game is played against the computer, so make the 'computer' player capable of making random plays. The AI doesn't have to be smart, but it should know whether a given move is legal (i.e. it shouldn't shoot the same coordinate twice)
-
Create the main game loop and a module for DOM interaction
- Begin crafting user interface
- The game loop should set up a new game by creating Players and Gameboards. For starters, just populate each Gameboard with predetermined coordinates. I will later implement a system for allowing players to place their ships.
- Create functions to render both players' boards using information from the appropriate Gameboard
- Create functions to allow the user to click on a coordinate in the enemy Gameboard to attack
- Consider: The game loop should step through the game turn by turn using only methods from other objects. If any any point I am tempted to write a new function inside the game loop, step back and figure out which class or module that function should belong to.
- Create conditions so that the game ends once one player's ships have all been sunk. This function is appropriate for the Game module
-
Finish it up!
- Implement system that allows players to place their ships.
- Polish the AI of the computer player by having it try adjacent slots after getting a 'hit'
- Optionally, create a 2-player option that lets users take turns by passing the device back and forth.
- Make sure the game is playable on mobile
- Implement a 'pass device' screen so that players don't see each others boards