diff options
Diffstat (limited to 'Games/Minesweeper')
-rw-r--r-- | Games/Minesweeper/Field.cpp | 54 | ||||
-rw-r--r-- | Games/Minesweeper/Field.h | 11 | ||||
-rw-r--r-- | Games/Minesweeper/main.cpp | 8 |
3 files changed, 60 insertions, 13 deletions
diff --git a/Games/Minesweeper/Field.cpp b/Games/Minesweeper/Field.cpp index 92714174d4..25deb47b03 100644 --- a/Games/Minesweeper/Field.cpp +++ b/Games/Minesweeper/Field.cpp @@ -24,8 +24,9 @@ public: } }; -Field::Field(GWidget* parent) +Field::Field(GButton& face_button, GWidget* parent) : GFrame(parent) + , m_face_button(face_button) { set_frame_thickness(2); set_frame_shape(FrameShape::Container); @@ -38,12 +39,30 @@ Field::Field(GWidget* parent) set_fill_with_background_color(true); set_background_color(Color::LightGray); reset(); + + m_face_button.on_click = [this] (auto&) { reset(); }; + set_face(Face::Default); } Field::~Field() { } +void Field::set_face(Face face) +{ + switch (face) { + case Face::Default: + m_face_button.set_icon(GraphicsBitmap::load_from_file("/res/icons/minesweeper/face-default.png")); + break; + case Face::Good: + m_face_button.set_icon(GraphicsBitmap::load_from_file("/res/icons/minesweeper/face-good.png")); + break; + case Face::Bad: + m_face_button.set_icon(GraphicsBitmap::load_from_file("/res/icons/minesweeper/face-bad.png")); + break; + } +} + template<typename Callback> void Field::for_each_neighbor_of(const Square& square, Callback callback) { @@ -70,12 +89,16 @@ void Field::for_each_neighbor_of(const Square& square, Callback callback) void Field::reset() { set_greedy_for_hits(false); + set_face(Face::Default); srand(time(nullptr)); m_squares.resize(rows() * columns()); HashTable<int> mines; - for (int i = 0; i < m_mine_count; ++i) - mines.set(rand() % (rows() * columns())); + while (mines.size() != m_mine_count) { + int location = rand() % (rows() * columns()); + if (!mines.contains(location)) + mines.set(location); + } int i = 0; for (int r = 0; r < rows(); ++r) { @@ -123,6 +146,8 @@ void Field::reset() } } + m_unswept_empties = rows() * columns() - m_mine_count; + update(); } @@ -141,15 +166,21 @@ void Field::on_square_clicked(Square& square) return; if (square.has_flag) return; + update(); square.is_swept = true; square.button->set_visible(false); square.label->set_visible(true); if (square.has_mine) { square.label->set_fill_with_background_color(true); game_over(); - } else if (square.number == 0) { - flood_fill(square); + } else { + --m_unswept_empties; + if (square.number == 0) + flood_fill(square); } + + if (!m_unswept_empties) + win(); } void Field::on_square_right_clicked(Square& square) @@ -161,9 +192,22 @@ void Field::on_square_right_clicked(Square& square) square.button->update(); } +void Field::win() +{ + set_greedy_for_hits(true); + set_face(Face::Good); + reveal_mines(); +} + void Field::game_over() { set_greedy_for_hits(true); + set_face(Face::Bad); + reveal_mines(); +} + +void Field::reveal_mines() +{ for (int r = 0; r < rows(); ++r) { for (int c = 0; c < columns(); ++c) { auto& square = this->square(r, c); diff --git a/Games/Minesweeper/Field.h b/Games/Minesweeper/Field.h index 1a7d8b8de6..3626e611ab 100644 --- a/Games/Minesweeper/Field.h +++ b/Games/Minesweeper/Field.h @@ -3,6 +3,7 @@ #include <LibGUI/GFrame.h> class SquareButton; +class GButton; class GLabel; struct Square { @@ -18,7 +19,7 @@ struct Square { class Field final : public GFrame { public: - explicit Field(GWidget* parent); + Field(GButton& face_button, GWidget* parent); virtual ~Field() override; int rows() const { return m_rows; } @@ -32,6 +33,8 @@ private: void on_square_clicked(Square&); void on_square_right_clicked(Square&); void game_over(); + void win(); + void reveal_mines(); Square& square(int row, int column) { return m_squares[row * columns() + column]; } const Square& square(int row, int column) const { return m_squares[row * columns() + column]; } @@ -40,11 +43,17 @@ private: template<typename Callback> void for_each_neighbor_of(const Square&, Callback); + enum class Face { Default, Good, Bad }; + void set_face(Face); + int m_rows { 9 }; int m_columns { 9 }; int m_mine_count { 10 }; + int m_unswept_empties { 0 }; Vector<Square> m_squares; RetainPtr<GraphicsBitmap> m_mine_bitmap; RetainPtr<GraphicsBitmap> m_flag_bitmap; RetainPtr<GraphicsBitmap> m_number_bitmap[8]; + GButton& m_face_button; + Face m_face { Face::Default }; }; diff --git a/Games/Minesweeper/main.cpp b/Games/Minesweeper/main.cpp index 3330793a5a..b3299b992e 100644 --- a/Games/Minesweeper/main.cpp +++ b/Games/Minesweeper/main.cpp @@ -25,13 +25,7 @@ int main(int argc, char** argv) container->set_preferred_size({ 0, 36 }); container->set_layout(make<GBoxLayout>(Orientation::Horizontal)); auto* face_button = new GButton(container); - face_button->set_icon(GraphicsBitmap::load_from_file("/res/icons/minesweeper/face-default.png")); - - auto* field = new Field(widget); - - face_button->on_click = [field] (auto&) { - field->reset(); - }; + auto* field = new Field(*face_button, widget); auto menubar = make<GMenuBar>(); |