refactoring

This commit is contained in:
Bernardo Magri
2025-03-07 07:23:59 +00:00
parent 2c13567747
commit 052690fede
6 changed files with 454 additions and 92 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -4,6 +4,7 @@ MineField::MineField(int cols, int rows, int mines): m_rows(rows),
m_cols(cols),
m_totalMines(mines),
m_remainingFlags(mines),
m_openCells(0),
m_exploded(false) {
for(int i=0; i< m_cols*m_rows; i++) {
std::shared_ptr<Cell> cell = std::make_shared<Cell>();
@@ -21,7 +22,7 @@ void MineField::initBombs(int x, int y) {
while(remainingMines > 0) {
int position = rand() % (m_cols * m_rows);
if(isBomb(position % m_cols, position / m_rows) || position == startPos) {
if(isBomb(position % m_cols, position / m_cols) || position == startPos) {
continue;
}
m_cells.at(position)->isBomb = true;
@@ -29,14 +30,16 @@ void MineField::initBombs(int x, int y) {
}
}
bool MineField::clearCell(int x, int y) {
setClearCell(x, y);
bool MineField::openCell(int x, int y) {
if(isBomb(x, y)) {
m_exploded = true;
return false;
gameOverSignal.emit();
return false;
}
setOpenCell(x, y);
if (bombsNearby(x, y) == 0) {
openNeighboorhood(x, y);
}
@@ -63,8 +66,8 @@ void MineField::openNeighboorhood(int x, int y) {
for(int i=-1; i<2; i++) {
for(int j=-1; j<2; j++) {
if(x+i >= 0 && x+i < m_cols && y+j >= 0 && y+j < m_rows) {
if((isCleared(x+i, y+j) == false) && (isBomb(x+i, y+j) == false)){
setClearCell((x+i), (y+j));
if((isOpened(x+i, y+j) == false) && (isBomb(x+i, y+j) == false)){
setOpenCell((x+i), (y+j));
if(bombsNearby(x+i, y+j) == 0) {
openNeighboorhood(x+i, y+j);
}
@@ -74,7 +77,7 @@ void MineField::openNeighboorhood(int x, int y) {
}
}
bool MineField::isCleared(int x, int y) {
bool MineField::isOpened(int x, int y) {
return m_cells.at(x + y * m_rows)->isCleared;
}
@@ -93,22 +96,25 @@ int MineField::bombsNearby(int x, int y) {
return m_cells.at(x + y * m_rows)->bombsNearby;
}
void MineField::setClearCell(int x, int y) {
void MineField::setOpenCell(int x, int y) {
m_cells.at(x + y * m_rows)->isCleared = true;
clearCellSignal.emit(x, y);
openCellSignal.emit(x, y);
if((++m_openCells == (m_cols * m_rows - m_totalMines)) && (m_exploded == false)) {
gameWonSignal.emit();
}
}
bool MineField::toggleFlag(int x, int y) {
if(m_cells.at(x + y * m_rows)->isFlagged == true) {
m_cells.at(x + y * m_rows)->isFlagged = false;
++m_remainingFlags;
remainingFlagsChangedSignal.emit(m_remainingFlags);
remainingFlagsSignal.emit(m_remainingFlags);
return true;
}
else if(m_remainingFlags > 0) {
m_cells.at(x + y * m_rows)->isFlagged = true;
--m_remainingFlags;
remainingFlagsChangedSignal.emit(m_remainingFlags);
remainingFlagsSignal.emit(m_remainingFlags);
return true;
}
return false;

View File

@@ -2,6 +2,7 @@
// #include <emmintrin.h>
#include <sigc++/signal.h>
#include <utility>
#include <vector>
#include <cstdlib>
#include <ctime>
@@ -18,22 +19,25 @@ struct Cell {
class MineField {
std::vector<std::shared_ptr<Cell>> m_cells;
int m_rows;
int m_cols;
int m_totalMines;
int m_remainingFlags;
int m_rows;
int m_cols;
int m_totalMines;
int m_remainingFlags;
int m_openCells;
bool m_exploded;
void computeBombsNearby(int x, int y);
void openNeighboorhood(int x, int y);
void setClearCell(int x, int y);
void setOpenCell(int x, int y);
//bint vecToPosition(int x, int y) {return (x + y * m_rows); };
//std::pair<int, int> positionToVec(int pos) {return std::make_pair(pos % m_cols, pos / m_cols); };
public:
MineField(int cols, int rows, int mines);
void initBombs(int x, int y);
bool isBomb(int x, int y);
bool isFlagged(int x, int y);
bool isCleared(int x, int y);
bool clearCell(int x, int y);
bool isOpened(int x, int y);
bool openCell(int x, int y);
int bombsNearby(int x, int y);
bool isGameOver() {return m_exploded; };
int getCols() {return m_cols; };
@@ -41,6 +45,10 @@ public:
bool toggleFlag(int x, int y);
int getRemainingFlags() {return m_remainingFlags; };
int getTotalMines() {return m_totalMines; };
sigc::signal<void(int, int)> clearCellSignal;
sigc::signal<void(int)> remainingFlagsChangedSignal;
void startNewGame(int cols, int rows, int mines);
sigc::signal<void(int, int)> openCellSignal;
sigc::signal<void(int)> remainingFlagsSignal;
sigc::signal<void(void)> gameWonSignal;
sigc::signal<void(void)> gameOverSignal;
};

View File

@@ -12,31 +12,30 @@
void MainWindow::OnCellRightClick(int n_press, double n_x, double n_y, int index) {
(void)n_press, (void)n_x, (void)n_y;
int x = index % field.getCols();
int y = index / field.getRows();
int y = index / field.getCols();
int pos = x + y * field.getRows();
if(field.isCleared(x, y) == false) {
if(field.isOpened(x, y) == false) {
field.toggleFlag(x, y);
if(field.isFlagged(x, y)) {
auto imgflag = Gtk::make_managed<Gtk::Image>();
imgflag->set(m_pixbufFlag);
buttons.at(x + y * field.getRows())->set_child(*imgflag);
buttons.at(x + y * field.getRows())->set_active(true);
buttons.at(pos)->set_child(*imgflag);
buttons.at(pos)->set_active(true);
}
else {
buttons.at(x + y * field.getRows())->unset_child();
buttons.at(x+ y * field.getRows())->queue_draw();
buttons.at(x + y * field.getRows())->set_active(false);
buttons.at(pos)->unset_child();
buttons.at(pos)->queue_draw();
buttons.at(pos)->set_active(false);
}
}
// Glib::ustring msg = Glib::ustring::compose("Remaining flags: %1", field.getRemainingFlags());
// flagLabel.set_label(msg);
}
void MainWindow::updateFlagsLabel(int flags) {
Glib::ustring msg = Glib::ustring::compose("Remaining flags: %1", flags);
flagLabel.set_label(msg);
}
// void MainWindow::OnNewButtonClick() {
// newGame = true;
// gameOver = false;
@@ -47,7 +46,7 @@ void MainWindow::updateFlagsLabel(int flags) {
// button->set_label("");
// }
// field->remainingFlags = MINES;
// //field->remainingFlags = MINES;
// Glib::ustring msg = Glib::ustring::compose("Remaining flags: %1", field->remainingFlags);
// flagLabel.set_label(msg);
@@ -57,41 +56,6 @@ void MainWindow::updateFlagsLabel(int flags) {
// }
// void MainWindow::OpenNearCells(int index, std::set<int> &visited) {
// int cols = field->Cols();
// int x = index % cols;
// int y = index / cols;
// if (visited.count(index)) return;
// Cell* cell = field->GetCell(x, y);
// if (!cell || cell->bombsNearby > 0 || cell->type == CellType::Bomb) return;
// visited.insert(index);
// buttons[index]->set_active(true);
// for (int i = -1; i <= 1; i++) {
// for (int j = -1; j <= 1; j++) {
// if (i == 0 && j == 0) continue; // Skip the current cell
// int nx = x + i;
// int ny = y + j;
// int newIndex = ny * cols + nx;
// Cell* neighborCell = field->GetCell(nx, ny);
// // Bounds check before recursive call
// if (nx >= 0 && nx < cols && ny >= 0 && ny < cols) {
// if (visited.count(newIndex) == 0) {
// OpenNearCells(newIndex, visited);
// }
// if (neighborCell && !buttons[newIndex]->get_active() && !neighborCell->isFlag) {
// OpenNearCells(newIndex, visited);
// }
// }
// }
// }
// }
void MainWindow::OnCellClick(int x, int y) {
@@ -107,7 +71,7 @@ void MainWindow::OnCellClick(int x, int y) {
openBombs();
}
else {
field.clearCell(x, y);
field.openCell(x, y);
}
}
@@ -115,7 +79,7 @@ void MainWindow::OnCellClick(int x, int y) {
void MainWindow::openBombs() {
for(int i=0; i < field.getCols() * field.getRows(); i++) {
int x = i % field.getCols();
int y = i / field.getRows();
int y = i / field.getCols();
buttons.at(i)->set_sensitive(false);
@@ -136,38 +100,39 @@ void MainWindow::openBombs() {
}
void MainWindow::updateCell(int x, int y) {
if(field.isCleared(x, y)) {
int pos = x + y * field.getRows();
if(field.isOpened(x, y)) {
if (field.bombsNearby(x, y) > 0) {
switch(field.bombsNearby(x, y)) {
case 1:
buttons.at(x + y * field.getRows())->get_style_context()->add_class("label-1");
buttons.at(pos)->get_style_context()->add_class("label-1");
break;
case 2:
buttons.at(x + y * field.getRows())->get_style_context()->add_class("label-2");
buttons.at(pos)->get_style_context()->add_class("label-2");
break;
case 3:
buttons.at(x + y * field.getRows())->get_style_context()->add_class("label-3");
buttons.at(pos)->get_style_context()->add_class("label-3");
break;
case 4:
buttons.at(x + y * field.getRows())->get_style_context()->add_class("label-4");
buttons.at(pos)->get_style_context()->add_class("label-4");
break;
case 5:
buttons.at(x + y * field.getRows())->get_style_context()->add_class("label-5");
buttons.at(pos)->get_style_context()->add_class("label-5");
break;
case 6:
buttons.at(x + y * field.getRows())->get_style_context()->add_class("label-6");
buttons.at(pos)->get_style_context()->add_class("label-6");
break;
case 7:
buttons.at(x + y * field.getRows())->get_style_context()->add_class("label-7");
buttons.at(pos)->get_style_context()->add_class("label-7");
break;
case 8:
buttons.at(x + y * field.getRows())->get_style_context()->add_class("label-8");
buttons.at(pos)->get_style_context()->add_class("label-8");
break;
}
buttons.at(x + y * field.getRows())->set_label(Glib::ustring::format(field.bombsNearby(x, y)));
buttons.at(pos)->set_label(Glib::ustring::format(field.bombsNearby(x, y)));
}
buttons.at(x + y * field.getRows())->set_active(true);
buttons.at(x + y * field.getRows())->set_sensitive(false);
buttons.at(pos)->set_active(true);
buttons.at(pos)->set_sensitive(false);
}
}
// void MainWindow::ShowGameWonAnimation() {
@@ -299,9 +264,8 @@ MainWindow::MainWindow()
grid.attach(*button, x, y);
}
field.clearCellSignal.connect(sigc::bind(sigc::mem_fun(*this, &MainWindow::updateCell)));
field.remainingFlagsChangedSignal.connect(sigc::bind(sigc::mem_fun(*this, \
&MainWindow::updateFlagsLabel)));
field.openCellSignal.connect(sigc::bind(sigc::mem_fun(*this, &MainWindow::updateCell)));
field.remainingFlagsSignal.connect(sigc::bind(sigc::mem_fun(*this, &MainWindow::updateFlagsLabel)));
//newGameButton.set_label("New");
//newGameButton.add_css_class("suggested-action");
//newGameButton.signal_clicked().connect(sigc::mem_fun(*this, &MainWindow::OnNewButtonClick));