summaryrefslogtreecommitdiff
path: root/Board.cpp
diff options
context:
space:
mode:
authorDaniel Jones <admin@danieljon.es>2020-06-12 00:03:37 +0930
committerDaniel Jones <admin@danieljon.es>2020-06-12 00:03:37 +0930
commit6739115f07b39da3ed59572faf393f9846bd4784 (patch)
treefef79a608906f46267b0e7e498cc81e058579aa8 /Board.cpp
parent49d97e71dae1955317a316cea16f9987585ef256 (diff)
downloadfoxminesweeper-6739115f07b39da3ed59572faf393f9846bd4784.tar.gz
foxminesweeper-6739115f07b39da3ed59572faf393f9846bd4784.zip
basic game working
Diffstat (limited to 'Board.cpp')
-rw-r--r--Board.cpp158
1 files changed, 157 insertions, 1 deletions
diff --git a/Board.cpp b/Board.cpp
index 83117d7..39caacf 100644
--- a/Board.cpp
+++ b/Board.cpp
@@ -15,11 +15,14 @@
#include "Board.h"
-Board:: Board(int width, int height)
+Board:: Board(int width, int height, int minecount)
{
this->width = width;
this->height = height;
this->tilecount = width*height;
+ this->minecount = minecount;
+ this->game_running = true;
+ this->game_won = false;
/* create tiles */
for (int x = 0; x < height; x++)
@@ -30,6 +33,8 @@ Board:: Board(int width, int height)
tiles.push_back(t);
}
}
+ generate_mines();
+ retrieve_neighbors();
}
Board::~Board()
@@ -45,6 +50,24 @@ Board::reveal_tile_at(int x, int y)
{
Tile *tile = get_tile_at(x, y);
printf("revealing x: %d y: %d\n", tile->get_x(), tile->get_y());
+ if (tile->is_mine())
+ {
+ /* lose */
+ reveal_all_mines();
+ game_running = false;
+ game_won = false;
+ return false;
+ }
+ tile->reveal();
+ reveal_neighbor_tiles(tile->get_x(), tile->get_y());
+ if (check_win())
+ {
+ /* win */
+ reveal_all_mines();
+ game_won = true;
+ game_running = false;
+ }
+
return true;
}
@@ -53,4 +76,137 @@ Board::new_game(int x, int y)
{
}
+void
+Board::reveal_all_mines()
+{
+ Tile *tile;
+ for(auto t = tiles.begin(); t != tiles.end(); ++t)
+ {
+ tile = (*t).get();
+ /* explicitly unflag tile */
+ tile->clear_flag(Tile::FLAGGED); // FIXME: doesnt work as intended, it should unflag all tiles
+ if (tile->is_mine())
+ {
+ tile->set_flag(Tile::REVEALED);
+ }
+ }
+}
+void
+Board::retrieve_neighbors()
+{
+ Tile *tile;
+ for(auto t = tiles.begin(); t != tiles.end(); ++t)
+ {
+ tile = (*t).get();
+ int badup = 0, baddown = 0, badleft = 0, badright = 0;
+ if (tile->get_x()-1<0) badleft = 1;
+ if (tile->get_x()+1>width-1) badright = 1;
+
+ if (tile->get_y()-1<0) badup = 1;
+ if (tile->get_y()+1>height-1) baddown = 1;
+
+ if (!badleft && !badup) tile->neighbors[0] = get_tile_at(tile->get_x()-1, tile->get_y()-1);
+ if (!badup) tile->neighbors[1] = get_tile_at(tile->get_x(), tile->get_y()-1);
+ if (!badright && !badup) tile->neighbors[2] = get_tile_at(tile->get_x()+1, tile->get_y()-1);
+
+ if (!badleft) tile->neighbors[3] = get_tile_at(tile->get_x()-1, tile->get_y());
+ if (!badright) tile->neighbors[4] = get_tile_at(tile->get_x()+1, tile->get_y());
+
+ if (!badleft && !baddown) tile->neighbors[5] = get_tile_at(tile->get_x()-1, tile->get_y()+1);
+ if (!baddown) tile->neighbors[6] = get_tile_at(tile->get_x(), tile->get_y()+1);
+ if (!badright && !baddown) tile->neighbors[7] = get_tile_at(tile->get_x()+1, tile->get_y()+1);
+ count_neighbor_mines(tile);
+ }
+}
+
+void
+Board::count_neighbor_mines(Tile *tile)
+{
+ Tile *neighbor;
+ int mines = 0;
+ for (int i = 0; i < 8; i++)
+ {
+ neighbor = tile->get_neighbor(i);
+ if (neighbor)
+ {
+ if (neighbor->is_mine())
+ {
+ mines++;
+ }
+ }
+ }
+ tile->set_neighbor_mine_count(mines);
+ printf("init tile: x: %d, y: %d, neighbor mines: %d\n", tile->get_x(), tile->get_y(), tile->get_neighbor_mine_count());
+}
+
+void
+Board::generate_mines()
+{
+ srand(time(NULL));
+ int mx, my;
+ Tile *tile;
+ for (int i = 0; i < minecount; i++)
+ {
+replace_mine:
+ mx = rand() % width;
+ my = rand() % height;
+ tile = get_tile_at(mx, my);
+ if (tile->is_mine()) /* don't overwrite mines */
+ goto replace_mine;
+ tile->set_flag(Tile::MINE);
+ }
+}
+
+bool
+Board::reveal_neighbor_tiles(int x, int y)
+{
+ /*
+ * reveal all neighbor tiles that are empty, recursively
+ */
+
+ Tile *tile, *neighbor;
+ tile = get_tile_at(x, y);
+
+ /* always reveal the first tile even if it has a neighbor mines */
+ tile->set_flag(Tile::REVEALED);
+ if (tile->is_mine())
+ return false;
+ if (tile->get_neighbor_mine_count() == 0)
+ {
+ /* if our tile is empty we want to reveal its immediate neighbors */
+ for (int nc = 0; nc < 8; nc++)
+ {
+ neighbor = tile->get_neighbor(nc);
+ if (neighbor != nullptr && !neighbor->is_mine() && !neighbor->is_revealed())
+ {
+ reveal_neighbor_tiles(neighbor->get_x(), neighbor->get_y());
+ }
+ }
+ }
+ return true;
+}
+
+bool
+Board::check_win()
+{
+ int allowedmines = minecount;
+ int safetiles = (height * width) - minecount;
+ int correctflags = 0;
+ int correcttiles = 0;
+
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ Tile *tile = get_tile_at(x, y);
+ if (tile->is_mine() && tile->is_flagged())
+ correctflags++;
+ else if (!(tile->is_mine()) && (tile->is_revealed()))
+ correcttiles++;
+ }
+ }
+
+ return (correctflags == allowedmines) || (correcttiles == safetiles);
+
+}