From 75734aa00377bd1f29dd4e1fd805fe0928e5d6a5 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 28 Apr 2019 13:55:41 +0200 Subject: [PATCH] Minesweeper: Add considering feature, where middle clicking marks with '?' This is useful in the harder modes, for trying out different possibilities. --- Base/res/icons/minesweeper/consider.png | Bin 0 -> 101 bytes Games/Minesweeper/Field.cpp | 46 +++++++++++++++++++++++- Games/Minesweeper/Field.h | 5 ++- 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 Base/res/icons/minesweeper/consider.png diff --git a/Base/res/icons/minesweeper/consider.png b/Base/res/icons/minesweeper/consider.png new file mode 100644 index 0000000000000000000000000000000000000000..2e12c4e740f2ad47e5e1ec7a1ad428c32e486be3 GIT binary patch literal 101 zcmeAS@N?(olHy`uVBq!ia0y~yVBiN~4mJh`2J356y%-o6bUa-gLp07OCrD@<=x~2$ zKk?OvtRu(Nqm=y$)v8*~{y(^MVrSxprvE&L`571{9_RR%vnFXC0|Nttr>mdKI;Vst E0Anp72mk;8 literal 0 HcmV?d00001 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;