diff --git a/Base/res/icons/minesweeper/consider.png b/Base/res/icons/minesweeper/consider.png new file mode 100644 index 0000000000..2e12c4e740 Binary files /dev/null and b/Base/res/icons/minesweeper/consider.png differ diff --git a/Games/Minesweeper/Field.cpp b/Games/Minesweeper/Field.cpp index 81b825b850..3850ca5763 100644 --- a/Games/Minesweeper/Field.cpp +++ b/Games/Minesweeper/Field.cpp @@ -15,6 +15,7 @@ public: } Function on_right_click; + Function on_middle_click; virtual void mousedown_event(GMouseEvent& event) override { @@ -22,6 +23,10 @@ public: if (on_right_click) on_right_click(); } + if (event.button() == GMouseButton::Middle) { + if (on_middle_click) + on_middle_click(); + } GButton::mousedown_event(event); } }; @@ -44,6 +49,14 @@ public: m_square.field->set_chord_preview(m_square, true); } } + if (event.button() == GMouseButton::Middle) { + m_square.field->for_each_square([] (auto& square) { + if (square.is_considering) { + square.is_considering = false; + square.button->set_icon(nullptr); + } + }); + } GLabel::mousedown_event(event); } @@ -95,6 +108,7 @@ Field::Field(GLabel& flag_label, GLabel& time_label, GButton& face_button, GWidg m_mine_bitmap = GraphicsBitmap::load_from_file("/res/icons/minesweeper/mine.png"); m_flag_bitmap = GraphicsBitmap::load_from_file("/res/icons/minesweeper/flag.png"); m_badflag_bitmap = GraphicsBitmap::load_from_file("/res/icons/minesweeper/badflag.png"); + m_consider_bitmap = GraphicsBitmap::load_from_file("/res/icons/minesweeper/consider.png"); m_default_face_bitmap = GraphicsBitmap::load_from_file("/res/icons/minesweeper/face-default.png"); m_good_face_bitmap = GraphicsBitmap::load_from_file("/res/icons/minesweeper/face-good.png"); m_bad_face_bitmap = GraphicsBitmap::load_from_file("/res/icons/minesweeper/face-bad.png"); @@ -182,6 +196,7 @@ void Field::reset() square.column = c; square.has_mine = mines.contains(i); square.has_flag = false; + square.is_considering = false; square.is_swept = false; if (!square.label) square.label = new SquareLabel(square, this); @@ -203,6 +218,9 @@ void Field::reset() square.button->on_right_click = [this, &square] { on_square_right_clicked(square); }; + square.button->on_middle_click = [this, &square] { + on_square_middle_clicked(square); + }; square.label->on_chord_click = [this, &square] { on_square_chorded(square); }; @@ -267,6 +285,8 @@ void Field::on_square_clicked(Square& square) return; if (square.has_flag) return; + if (square.is_considering) + return; if (!m_timer.is_active()) m_timer.start(); update(); @@ -313,6 +333,8 @@ void Field::on_square_right_clicked(Square& square) if (!square.has_flag && !m_flags_left) return; + square.is_considering = false; + if (!square.has_flag) { --m_flags_left; square.has_flag = true; @@ -326,6 +348,20 @@ void Field::on_square_right_clicked(Square& square) square.button->update(); } +void Field::on_square_middle_clicked(Square& square) +{ + if (square.is_swept) + return; + if (square.has_flag) { + ++m_flags_left; + square.has_flag = false; + m_flag_label.set_text(String::format("%u", m_flags_left)); + } + square.is_considering = !square.is_considering; + square.button->set_icon(square.is_considering ? m_consider_bitmap : nullptr); + square.button->update(); +} + void Field::win() { m_timer.stop(); @@ -368,7 +404,7 @@ void Field::set_chord_preview(Square& square, bool chord_preview) m_chord_preview = chord_preview; square.for_each_neighbor([&] (auto& neighbor) { neighbor.button->set_checked(false); - if (!neighbor.has_flag) + if (!neighbor.has_flag && !neighbor.is_considering) neighbor.button->set_checked(chord_preview); }); } @@ -395,3 +431,11 @@ Square::~Square() delete label; delete button; } + +template +void Field::for_each_square(Callback callback) +{ + for (auto& square : m_squares) { + callback(*square); + } +} diff --git a/Games/Minesweeper/Field.h b/Games/Minesweeper/Field.h index 6461e0f0a2..4aa9118101 100644 --- a/Games/Minesweeper/Field.h +++ b/Games/Minesweeper/Field.h @@ -20,6 +20,7 @@ public: bool is_swept { false }; bool has_mine { false }; bool has_flag { false }; + bool is_considering { false }; int row { 0 }; int column { 0 }; int number { 0 }; @@ -52,6 +53,7 @@ private: void on_square_clicked(Square&); void on_square_right_clicked(Square&); + void on_square_middle_clicked(Square&); void on_square_chorded(Square&); void game_over(); void win(); @@ -63,7 +65,7 @@ private: void flood_fill(Square&); - template void for_each_neighbor_of(const Square&, Callback); + template void for_each_square(Callback); enum class Face { Default, Good, Bad }; void set_face(Face); @@ -76,6 +78,7 @@ private: RetainPtr m_mine_bitmap; RetainPtr m_flag_bitmap; RetainPtr m_badflag_bitmap; + RetainPtr m_consider_bitmap; RetainPtr m_default_face_bitmap; RetainPtr m_good_face_bitmap; RetainPtr m_bad_face_bitmap;