#include "sweeper.h"
const int xDir[8] {0, 1, 0, -1, 1, 1, -1, -1};
const int yDir[8] {1, 0, -1, 0, 1, -1, 1, -1};
// Initializes/Resets the Grid
void Game::initialize(int GRID_WIDTH, int GRID_HEIGHT, int NB_MINES) {
grid->clear();
this->GRID_WIDTH = GRID_WIDTH;
this->GRID_HEIGHT = GRID_HEIGHT;
this->NB_MINES = NB_MINES;
for (int x = 0; x < GRID_WIDTH; x++)
{
grid->push_back(new CellList);
for (int y = 0; y < GRID_HEIGHT; y++)
{
Cell* cell = new Cell;
cell->x = x;
cell->y = y;
grid->at(x)->push_back(cell);
}
}
state = GameState::Initiated;
}
// Add Mines + Calulcate Numbers adjacent to Mines, to the Grid
void Game::populateGrid(Cell* &exception)
{
// Generate mines
int generated = 0;
while (generated != NB_MINES)
{
int x = rand() % GRID_WIDTH;
int y = rand() % GRID_HEIGHT;
Cell* cell = grid->at(x)->at(y);
if (cell->isMine) continue;
if (
abs(exception->x - cell->x) y - cell->y) isMine = true;
generated++;
}
FLAGS_LEFT = generated;
// Generate adjacent numbered cells
// NSWE + Diagonals
for (int x = 0; x < GRID_WIDTH; x++)
{
for (int y = 0; y < GRID_HEIGHT; y++)
{
Cell* cell = grid->at(x)->at(y);
if (!(cell->isMine)) continue;
CellList* adjs = getAdjacentCells(cell);
for(auto it = adjs->begin(); it != adjs->end(); it++)
if (!(*it)->isMine) (*it)->num++;
}
}
}
// Gets 8 cells surrounding the root cell
CellList* Game::getAdjacentCells(Cell* &root)
{
CellList* adjs = new CellList;
// Up, Down, Left, Right, + Diagonals -> 8 Squares total
for (int d = 0; d < 8; d++)
{
int nX = root->x + xDir[d];
int nY = root->y + yDir[d];
if (
nX >= GRID_WIDTH ||
nX < 0 ||
nY >= GRID_HEIGHT ||
nY < 0
) continue;
adjs->push_back(grid->at(nX)->at(nY));
}
return adjs;
}
// Flags a cell (False flag is cell isnt a Mine, else is it Valid (Not known to user))
void Game::flagCell(Cell* &cell)
{
if (cell->isRevealed) return;
cell->isFlagged = !(cell->isFlagged);
if (cell->isFlagged) FLAGS_LEFT--;
else FLAGS_LEFT++;
}
// Recursively reveals an area that is purely mine-free
void Game::revealCell(Cell* &cell)
{
if (!cell->isRevealed && !cell->isFlagged && state == GameState::Initiated) {
cell->isRevealed = true;
// End the game if the Cell is a mine
if (cell->isMine) {
state = GameState::Lost;
} else if (cell->num == 0) {
// If the cell has 0 adjacent mines, we need to recurse to clear out all adjacent 0 cells
CellList* adjs = getAdjacentCells(cell);
for(auto it = adjs->begin(); it != adjs->end(); it++)
if (!(*it)->isMine) revealCell(*it);
}
}
}
// Reveals all cells (End game)
void Game::revealAll()
{
for (int x = 0; x < GRID_WIDTH; x++)
{
for (int y = 0; y < GRID_HEIGHT; y++)
{
grid->at(x)->at(y)->isRevealed = true;
}
}
}
// Checks if user has successfully guessed all Mines
bool Game::checkWin()
{
if (FLAGS_LEFT != 0) return false;
for (int x = 0; x < GRID_WIDTH; x++)
{
for (int y = 0; y < GRID_HEIGHT; y++)
{
Cell* cell = grid->at(x)->at(y);
if (cell->isMine && !cell->isFlagged) return false;
if (!cell->isRevealed && !cell->isMine) return false;
}
}
return true;
}
// ...
void Game::printGrid()
{
for (int y = 0; y < GRID_WIDTH; y++)
{
std::cout at(x)->at(y);
if (cell->isMine) std::cout