diff options
author | Daniel Jones <admin@danieljon.es> | 2020-06-12 00:03:37 +0930 |
---|---|---|
committer | Daniel Jones <admin@danieljon.es> | 2020-06-12 00:03:37 +0930 |
commit | 6739115f07b39da3ed59572faf393f9846bd4784 (patch) | |
tree | fef79a608906f46267b0e7e498cc81e058579aa8 /Board.cpp | |
parent | 49d97e71dae1955317a316cea16f9987585ef256 (diff) | |
download | foxminesweeper-6739115f07b39da3ed59572faf393f9846bd4784.tar.gz foxminesweeper-6739115f07b39da3ed59572faf393f9846bd4784.zip |
basic game working
Diffstat (limited to 'Board.cpp')
-rw-r--r-- | Board.cpp | 158 |
1 files changed, 157 insertions, 1 deletions
@@ -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); + +} |