C++ library containing the core logic of Minesweeper game.
- C++ version required
- Installation
- How to use
- External libraries
- Version history
- Pre console separation version history
- Fixes and features left to consider/implement
Minimum C++ version required: C++14.
C++14 required for:
std::make_unique
.
C++11 required for numerous modern features.
If you want to clone this git repository, use
git clone --recurse-submodules https://github.com/TimiMakkonen/minesweeper.git
or something similar to ensure that astoeckel/json submodule gets cloned properly.
Then you can use this library as part of your own CMake project as you desire.
You can follow these simple instructions to build this library:
-
Make sure you have CMake installed. (version 3.8 or later)
-
Create and change to a
build
-directory by running these commands:cd <path to this directory> mkdir build cd build
-
Configure CMake and build this library by running these commands:
cmake .. cmake --build .
After this you can run ctest
-command or the resulting MinesweeperTests.exe
(which can be found somewhere in build/tests/
) to run tests.
Alternatively you can run MinesweeperExamples.exe
(which can be found somewhere in build/examples/
) to run minesweeper_examples.cpp
, so that you can follow the examples or play with this library as you please.
Naturally, if you make any changes in the code, you have to build the project again by deleting the contents of build
-directory and running commands in step 3 again.
To use this Minesweeper game library, pass your implementation of provided IRandom
pure virtual class to Game
class or alternatively pass it as an default option to the Game
class statically, so that it can be used by all the instances of Game
class.
If you are truly lazy, and/or you do not need to have/control randomness elsewhere, you can simply initialise and pass Random
(provided implementation of IRandom
that uses std::mt19937
) as instructed above.
You can check examples
function in minesweeper_examples.cpp
for more detailed usage explanation and game.h
for the main interface.
- astoeckel/json (v3.9.1) for JSON (de)serialisation
- This repository is a lightweight copy of the nlohmann/json header-only library.
- google/googletest for unit tests
- Fixed some standard
#include
directives and checked which classes and functions use them. - Fixed
HeaderFilterRegex
forclang-tidy
. - Excluded some unhelpful
clang-tidy
checks and also gave explanations to all of the excludes. - Added
cmake.yml
,clang-format.yml
andclang-tidy.yml
GitHub action workflows.cmake.yml
builds tests on different platforms.clang-format.yml
automatically formats the code usingclang-format
.clang-tidy.yml
checks the code for typical programming errors.
- Fixed potential stack overflow in large grids caused by recursion when checking around input coordinates.
- Updated external astoeckel/json submodule from v3.8.0 to v3.9.1.
- Changed behaviour of solution visualisation methods.
visualiseSolution
andvisualiseCellSolution
originally returned visualisation showing every cell either as:- a mine (if they contained a mine),
- a cell with neighbouring mines i.e. a number (if they did not have a mine but had neighbouring mines), or
- an empty cell (if all other options did not apply).
- Now these old methods have been renamed into
visualiseSolutionData
andvisualiseCellSolutionData
, respectively. - The new
visualiseSolution
andvisualiseCellSolution
methods now return a visualisation which is identical to the previous one, but now show mines as marked instead of bare mines. - These changes should represent and emphasise their actual meaning much better.
- In summary:
- old
visualiseSolution
is nowvisualiseSolutionData
, - old
visualiseCellSolution
is nowvisualiseCellSolutionData
, - new
visualiseSolution
is identical to old one, but shows mines as marked, - new
visualiseCellSolution
is identical to old one, but shows mines as marked.
- old
- Added solution visualisation methods.
- Work the same way as normal visualisation methods, except that they return the solution information instead of the current visualisation information.
- Added
completeAroundInputCoordinates
method to automatically check/show trivial unchecked cells around chosen coordinates.- For example, if we use this on a visible cell that has 2 mines around, and we have already marked two mines around this visible cell, then we will check/show the rest of cells around this visible cell.
- If the player has wrongly marked one of the mines around the visible cell this method is used on, this method will end up checking a mine and the player will lose the game.
- If this method is used on a cell that is not visible yet, this method throws.
- Removed repetition related to checking valid neighbours around a cell.
- Fixed some minor typos.
- Added CodeCounter.
- Urgently corrected C++ version required to C++14.
- Failed to realise
std::make_unique
was included in C++14.- Could also be replaced by some C++11 alternative later on, if needed.
- Failed to realise
- Removed
std::
-prefix accidentally left in front ofvoid_t<>
intype_traits.h
. - Added CMake option to build shared libraries within the project
- Fixed a typo in
examples/CMakeLists.txt
.
- Urgent fix for the broken ArthurSonzogni/nlohmann_json_cmake_fetchcontent submodule in v8.4.1.
- Switched from ArthurSonzogni/nlohmann_json_cmake_fetchcontent
submodule to astoeckel/json submodule (v3.8.0).
- Both of these repositories are lightweight copies of the nlohmann/json header-only library.
- ArthurSonzogni/nlohmann_json_cmake_fetchcontent
is mainly meant/supported to be used with CMake's
FetchContent
(andExternalProject
). - astoeckel/json on the other hand is meant/supported to be used with git submodules.
- Change necessary to ensure sustainability of previous versions in this library for the releases to come.
- Since CMake's
FetchContent
(andExternalProject
) use tags instead of specific hashes, the owner of ArthurSonzogni/nlohmann_json_cmake_fetchcontent repository does not mind reassigning tags. (After some updates to their own code.) Hence the previous version/commit, 'v8.4.1', was too easy for me to break.
- Since CMake's
- Updated external ArthurSonzogni/nlohmann_json_cmake_fetchcontent submodule from v3.7.3 to v3.8.0.
- This repository is a lightweight copy of the nlohmann/json header-only library.
- Added
External libraries
andTable of contents
sections toREADME.MD
.
- Added
VisualMinesweeperCell
enum class to represent the visual state of a cell. - Added
visualise
template method to help with getting information needed to visually express theGame
.- Uses
VisualMinesweeperCell
as the underlying information type. - Works with any 1D or 2D container which:
- has
size
andpush_back
methods, and - uses
value_type
that supports conversion fromVisualMinesweeperCell
enum class. (eg.int
)
- has
- Works for example with:
std::vector\<VisualMinesweeperCell\>
,std::vector\<int\>
,std::vector\<std::vector\<VisualMinesweeperCell\>\>
andstd::vector\<std::vector\<int\>\>
.
- Uses
- Added
visualiseCell
template method to help with getting information needed to visually express a cell.- Uses
VisualMinesweeperCell
as the underlying information type. - Works with any type that supports conversion from
VisualMinesweeperCell
enum class. (eg.int
)
- Uses
- Added option to add mines by proportion instead of number.
- Added new constructors and
newGame
overloads to support this.
- Added new constructors and
- Added
Game
copy/move constructors, friend swap and copy/move assignment operator. - Added
IRandom
default constructors, destructor and assignment operators. - Added
type_traits
to help with template type checking at compile-time. - Prettified headers.
- Updated
minesweeper_examples.cpp
. - Fixed some throw messages.
- Made
clang-tidy
to actually work on headers.- Fixed bunch of new warnings/errors identified by this.
- Removed internal calls to public methods within the same class.
- Should make possible thread-safe implementation trivial to achieve. (simply add mutex field and lock all public methods)
- Added some tests.
- Added reset and newGame methods.
reset(bool keepCreatedMines = false)
method keeps current grid size and number of mines parameters and allows to keep currently set mines as well if argumentkeepCreatedMines
is set to true.newGame
methods start completely new game with different grid sizes and number of mines.
- Disabled cell marking for already visible cells. (no throw, just nothing happens)
- Added argument verifications to various methods and made them throw.
- Added virtual destructor to
IRandom
. - Formatted code using
clang-format
. - Tidied code using
clang-tidy
. - Added some tests and test data.
- Added serialisation and deserialisation methods.
- Using nlohmann/json header-only library to do this in
json
-form. - Added ArthurSonzogni/nlohmann_json_cmake_fetchcontent as submodule to this project to implement this neatly in lightweight form.
- Already considering about using different (faster) JSON library or different serialisation data format since this current method is relatively slow for larger grids.
- Using nlohmann/json header-only library to do this in
- Added some tests.
- Slightly edited
README.MD
.
- Made public
createMinesAndNums(const int initChosenX, const int initChosenY)
redundant.- Can still be called as before, but completely unnecessary (and not recommended) to do this manually from now on.
markInputCoordinates(const int X, const int Y)
now throws ifcheckInputCoordinates(const int X, const int Y)
orcreateMinesAndNums(const int initChosenX, const int initChosenY)
has not been called before it.- Added getters for grid height, width and number of mines.
- Added some tests.
- Added verifications to some methods.
- Updated
minesweeper_examples.cpp
. - Slightly edited
README.MD
.
- Renamed the
Grid
class toGame
.- Might cause historical inconsistencies and confusion, since the original console game version had a class with this name. (v6.1.1 and lower)
- Should increase clarity for further releases of this library.
- Changed file naming convention from
PascalCase
tosnake_case
. - Changed namespace naming convention from
PascalCase
tolowercase
. - Added missing
#include\<vector\>
toi_random.h
. - Slightly edited
README.MD
.
- Separated original Minesweeper game (on console) into:
- minesweeper (game library) and
- console-minesweeper (console version of the game which uses the aforementioned library).
- Turned VS solution into CMake library.
- Added (google)testing. (Not implemented yet.)
- Added
examples
executable to allow showcasing library.- Added some usage instructions and examples.
- New classes
IRandom
andRandom
:- Separating randomising part of creating mines from rest of the
Grid
. - IRandom is an abstract class which provides
Grid
with ability to shuffle a vector of ints. - You can create your own class which implements
IRandom
or use providedRandom
class for simplicity. - You can pass
IRandom
via constructor or setdefaultRandom
static property. (Class field set by constructor has the priority.)
- Separating randomising part of creating mines from rest of the
- Slightly improved readability of code.
- Added validity check for the number of mines in the constructor of
Grid
. - Created static methods in
Grid
class to tell the maximum and minimum number of mines allowed in a grid of given size.
- Separated
gridSize
intogridHeight
andgridWidth
to allow 'non-square' grids both inGrid
andGame
.
- Moved print functionality from
Grid
toGame
. - Changed
cerr
's into asserts and throws. - Moved and changed some of the game logic.
- Slightly improved readability of the code and fixed minor things.
- Changed minimum size of grid into 4x4 to stop softlock when choosing number of mines for smaller grids.
- Added win condition (all non mines visible/checked).
- Made impossible to mark a cell on the first turn.
- Slightly improved readability of the code.
- Updated program from C-style to OOP.
- New
Game
,Grid
andCell
classes.
- New
- Improved readability and efficiency of some parts of code.
- Changed variable naming convention from pascal to camel and made names easier to understand.
- Changed pseudo-random number generator from
rand
tostd::mt19937
(Mersenne Twister 19937) to improve randomness.
- Continued with improvements on the input system.
- Increased maximum size of the grid up to 99x99. (I do not recommend grids larger than 50x50.)
- Program now shows your last grid spot input.
- Made function
TryInputToCoordinates
mostly future proof.- can handle grid sizes up to 675 (overkill tbh)
- able to give error messages and decide when new input is needed.
- Improved games structure for all the different possibilities.
- Added and made HELP menu optional. (show up in the beginning and later upon request)
- Improved instructions and other text output.
- Added ability to play again.
- Made sure that you cannot lose on the first turn.
- Creation of the grid has been moved to take into account players first choice, making sure player will make some progress.
- Slightly improved readability of the code.
- Started to deal with proper handling of wrong inputs.
- Added initial win screen and win condition, if you manage to mark all mines.
- Ability to unmark grid spots by marking them again (in case you made a mistake).
- Initial options/special input menu implemented.
- Fixed some visual mistakes and made the game look prettier.
- Added automatic mine check for squares around, when choosing a grid location with no surrounding mines.
- Fixes input for 2 digit numbers.
- Initial losing screen.
- More convenient input system.
- + Background work to make next additions/fixes easier to implement.
Initial version of the game. Mostly in working condition.
- Add more serialisation options.
- Add verifications to deserialisation methods to check validity of the given game.
- Make
Game
's deserialise method safer by guaranteeing thatGame
is left in valid condition even if if throws. - Add more tests.
- Implement Pimpl to clear up the public API.
- Add Doxygen.