chording support

This commit is contained in:
TheRedBlueCube3 2025-06-22 13:08:52 +03:00 committed by thorium1256
parent dda721f8e9
commit c1e89c5122
7 changed files with 77 additions and 50 deletions

3
.gitignore vendored
View File

@ -1,4 +1,5 @@
lib lib
.vscode .vscode
bin bin
build build
Makefile

View File

@ -10,6 +10,16 @@ Marking all mines with flags isn't necessary, but helps.
### Clear all non-mine cells to win! ### Clear all non-mine cells to win!
## Controls
Arrows to move.
Z to reveal.
X to flag.
C to chord.
R to restart.
P to pause.
Q to quit.
## Compilation ## Compilation
By default, the Makefile compiles in debug mode, so to compile both, use `make both`. By default, the Makefile compiles in debug mode, so to compile both, use `make both`.
@ -56,12 +66,3 @@ sudo dnf install ncurses-devel
Search engines are your best friend. Search engines are your best friend.
Then rename `Makefile.unix`, press the make button, and a moment later, you got it. Then rename `Makefile.unix`, press the make button, and a moment later, you got it.
## Controls
Arrows to move.
Z to reveal.
X to flag.
R to restart.
P to pause.
Q to quit.

View File

@ -20,6 +20,7 @@ public:
int getMineCount() const; int getMineCount() const;
void regenerateBoard(); void regenerateBoard();
bool isGameWon() const; bool isGameWon() const;
std::vector<Cell> getNeighborsOf(int x, int y);
private: private:
Vector2 size; Vector2 size;

View File

@ -38,6 +38,7 @@ public:
void toggleFlag(); void toggleFlag();
Content getContent() const; Content getContent() const;
void setContent(Content newContent); void setContent(Content newContent);
Vector2 getPosition() const;
private: private:
State state = State::Hidden; State state = State::Hidden;

View File

@ -40,21 +40,12 @@ Board::Board(int w, int h, short mines) : size(w, h), mines(mines), isFirstClick
if (cell.getContent() != Cell::Content::Mine) if (cell.getContent() != Cell::Content::Mine)
{ {
int count = 0; int count = 0;
for (int dx = -1; dx <= 1; dx++) std::vector<Cell> neighbors = getNeighborsOf(x, y);
for (const Cell &neighbor : neighbors)
{ {
for (int dy = -1; dy <= 1; dy++) if (neighbor.getContent() == Cell::Content::Mine)
{ {
if (dx == 0 && dy == 0) count++;
continue;
int nx = x + dx;
int ny = y + dy;
if (nx >= 0 && nx < w && ny >= 0 && ny < h)
{
if (cells[ny][nx].getContent() == Cell::Content::Mine)
{
count++;
}
}
} }
} }
cell.setContent(static_cast<Cell::Content>(count)); cell.setContent(static_cast<Cell::Content>(count));
@ -63,6 +54,24 @@ Board::Board(int w, int h, short mines) : size(w, h), mines(mines), isFirstClick
} }
} }
std::vector<Cell> Board::getNeighborsOf(int x, int y)
{
std::vector<Cell> neighbors;
for (int dx = -1; dx <= 1; dx++)
{
for (int dy = -1; dy <= 1; dy++)
{
if (dx == 0 && dy == 0)
continue;
int nx = x + dx;
int ny = y + dy;
if (nx >= 0 && nx < size.x && ny >= 0 && ny < size.y)
neighbors.push_back(cells[ny][nx]);
}
}
return neighbors;
}
bool Board::isGameOver() bool Board::isGameOver()
{ {
return b_gameOver; return b_gameOver;
@ -130,22 +139,30 @@ void Board::revealEmptyCells(int x, int y)
if (current.getContent() == Cell::Content::Empty) if (current.getContent() == Cell::Content::Empty)
{ {
for (int dx = -1; dx <= 1; dx++) // for (int dx = -1; dx <= 1; dx++)
// {
// for (int dy = -1; dy <= 1; dy++)
// {
// if (dx == 0 && dy == 0)
// continue;
// int nx = pos.x + dx;
// int ny = pos.y + dy;
// if (nx >= 0 && nx < size.x && ny >= 0 && ny < size.y)
// {
// Cell &neighbor = cells[ny][nx];
// if (neighbor.getState() == Cell::State::Hidden)
// {
// q.push(Vector2(nx, ny));
// }
// }
// }
// }
std::vector<Cell> neighbors = getNeighborsOf(pos.x, pos.y);
for (const Cell &neighbor : neighbors)
{ {
for (int dy = -1; dy <= 1; dy++) if (neighbor.getState() == Cell::State::Hidden)
{ {
if (dx == 0 && dy == 0) q.push(Vector2(neighbor.position.x, neighbor.position.y));
continue;
int nx = pos.x + dx;
int ny = pos.y + dy;
if (nx >= 0 && nx < size.x && ny >= 0 && ny < size.y)
{
Cell &neighbor = cells[ny][nx];
if (neighbor.getState() == Cell::State::Hidden)
{
q.push(Vector2(nx, ny));
}
}
} }
} }
} }
@ -229,21 +246,12 @@ void Board::regenerateBoard()
if (cell.getContent() != Cell::Content::Mine) if (cell.getContent() != Cell::Content::Mine)
{ {
int count = 0; int count = 0;
for (int dx = -1; dx <= 1; dx++) std::vector<Cell> neighbors = getNeighborsOf(x, y);
for (const Cell &neighbor : neighbors)
{ {
for (int dy = -1; dy <= 1; dy++) if (neighbor.getContent() == Cell::Content::Mine)
{ {
if (dx == 0 && dy == 0) count++;
continue;
int nx = x + dx;
int ny = y + dy;
if (nx >= 0 && nx < size.x && ny >= 0 && ny < size.y)
{
if (cells[ny][nx].getContent() == Cell::Content::Mine)
{
count++;
}
}
} }
} }
cell.setContent(static_cast<Cell::Content>(count)); cell.setContent(static_cast<Cell::Content>(count));

View File

@ -35,4 +35,9 @@ Cell::Content Cell::getContent() const
void Cell::setContent(Content newContent) void Cell::setContent(Content newContent)
{ {
content = newContent; content = newContent;
}
Vector2 Cell::getPosition() const
{
return position;
} }

View File

@ -188,6 +188,16 @@ void startGame(Board &board)
startPauseTime = time(NULL); startPauseTime = time(NULL);
} }
isPaused = !isPaused; isPaused = !isPaused;
break;
case 'c':
auto neighbors = board.getNeighborsOf(cursorX, cursorY);
for (const Cell &neighbor : neighbors)
{
if (neighbor.getState() == Cell::State::Flagged)
continue;
board.revealCellAt(neighbor.getPosition().x, neighbor.getPosition().y);
}
break;
} }
if (isPaused) if (isPaused)