Minesweeper: Add considering feature, where middle clicking marks with '?'
This is useful in the harder modes, for trying out different possibilities.
This commit is contained in:
parent
ed957ca2e1
commit
75734aa003
Notes:
sideshowbarker
2024-07-19 14:34:09 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/75734aa0037
3 changed files with 49 additions and 2 deletions
BIN
Base/res/icons/minesweeper/consider.png
Normal file
BIN
Base/res/icons/minesweeper/consider.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 101 B |
|
@ -15,6 +15,7 @@ public:
|
|||
}
|
||||
|
||||
Function<void()> on_right_click;
|
||||
Function<void()> 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<typename Callback>
|
||||
void Field::for_each_square(Callback callback)
|
||||
{
|
||||
for (auto& square : m_squares) {
|
||||
callback(*square);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<typename Callback> void for_each_neighbor_of(const Square&, Callback);
|
||||
template<typename Callback> void for_each_square(Callback);
|
||||
|
||||
enum class Face { Default, Good, Bad };
|
||||
void set_face(Face);
|
||||
|
@ -76,6 +78,7 @@ private:
|
|||
RetainPtr<GraphicsBitmap> m_mine_bitmap;
|
||||
RetainPtr<GraphicsBitmap> m_flag_bitmap;
|
||||
RetainPtr<GraphicsBitmap> m_badflag_bitmap;
|
||||
RetainPtr<GraphicsBitmap> m_consider_bitmap;
|
||||
RetainPtr<GraphicsBitmap> m_default_face_bitmap;
|
||||
RetainPtr<GraphicsBitmap> m_good_face_bitmap;
|
||||
RetainPtr<GraphicsBitmap> m_bad_face_bitmap;
|
||||
|
|
Loading…
Add table
Reference in a new issue