Clone this repo, install the packages, fire up the server and you should be good to go!
Open http://localhost:3000 to view it in the browser.
There are 3 components:
<Game>
, a headless component which contains core logic of the game. It accepts a UI component as function as child pattern. Users can provide any implementation of Minesweeper UI to it without worrying about the game logic, and it will just work. Benefit: Same game logic can be used with different game UI.<Board>
, a default UI implementation of game board which is passed to<Game>
.<Menu>
allows us to change difficulty level and start a new game. We've 3 predefined levels to choose from: Beginner, Intermediate, and Expert, each having a different board configuration(rows
,cols
, andmines
).
The game has 2 components: Board and Cell
Board class contains:
- properties:
rows
,cols
,cells
, andplantedMinesLocation
- methods to manipulate cells inside board.
It is responsible for:
- Creating a board of size
rows
*cols
. Each cell of the board is an instance of classCell
. - Planting X mines randomly on the board.
- Calculatinng
nearbyMinesCount
for each cell. - Opening all the nearby empty cells recursively when you click on a cell. It stops opening cells once it reaches the boundary of numbers(nearbyMinesCount).
- Showing all the mines once the game is over.
Cell class contains
- properties:
row
,col
,opened
,mine
, andnearbyMinesCount
- methods to manipulate cell properties
- Immutability
Right now, a single instance of the board object is mutated. Another approach could be to create an entirely new instance of the board object every time it changes, i.e. using an immutable object. I thought about this a bit and went with my current approach because if the size of the board grows, immutability will incur a larger cost. There are advantages to immutability in general, but in this specific case, I think a mutable approach is more efficient.
- Test cases
I haven't added tests yet, but I've structured this such that it would be straightforward to add unit tests for the individual classes (Board, Cell), and integration tests for React components.
-
Flagging feature is not implemented yet.
-
Win game feature is not implemented, which is very straightfoward to implement. Just count the number of cells you have opened, then it becomes:
hasWon = ((rows * cols) - #mines) === #openedCells