mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 20:47:45 +00:00
Minesweeper: Add "Custom game..." difficulty
This adds a dialog window which allows us to customize the size of the board and the amount of mines that will be placed. The current max amount of mines is 50% of the total number of cells due to the fact that the generator algorithm takes too long to create a board for higher percentages of mines.
This commit is contained in:
parent
42071f69cf
commit
557075465c
5 changed files with 201 additions and 0 deletions
|
@ -4,7 +4,11 @@ serenity_component(
|
||||||
TARGETS Minesweeper
|
TARGETS Minesweeper
|
||||||
)
|
)
|
||||||
|
|
||||||
|
compile_gml(MinesweeperCustomGameWindow.gml MinesweeperCustomGameWindowGML.h minesweeper_custom_game_window_gml)
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
|
MinesweeperCustomGameWindowGML.h
|
||||||
|
CustomGameDialog.cpp
|
||||||
Field.cpp
|
Field.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
)
|
)
|
||||||
|
|
80
Userland/Games/Minesweeper/CustomGameDialog.cpp
Normal file
80
Userland/Games/Minesweeper/CustomGameDialog.cpp
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Pedro Pereira <pmh.pereira@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CustomGameDialog.h"
|
||||||
|
#include "Field.h"
|
||||||
|
#include <Games/Minesweeper/MinesweeperCustomGameWindowGML.h>
|
||||||
|
|
||||||
|
int CustomGameDialog::show(GUI::Window* parent_window, Field& field)
|
||||||
|
{
|
||||||
|
auto dialog = CustomGameDialog::construct(parent_window);
|
||||||
|
|
||||||
|
if (parent_window) {
|
||||||
|
dialog->set_icon(parent_window->icon());
|
||||||
|
dialog->center_within(*parent_window);
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog->m_columns_spinbox->set_value(field.columns());
|
||||||
|
dialog->m_rows_spinbox->set_value(field.rows());
|
||||||
|
dialog->m_mines_spinbox->set_value(field.mine_count());
|
||||||
|
|
||||||
|
auto result = dialog->exec();
|
||||||
|
|
||||||
|
if (result != GUI::Dialog::ExecOK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
field.set_field_size(dialog->m_rows_spinbox->value(), dialog->m_columns_spinbox->value(), dialog->m_mines_spinbox->value());
|
||||||
|
|
||||||
|
return GUI::Dialog::ExecOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CustomGameDialog::set_max_mines()
|
||||||
|
{
|
||||||
|
// Generating a field with > 50% mines takes too long.
|
||||||
|
// FIXME: Allow higher amount of mines to be placed.
|
||||||
|
m_mines_spinbox->set_max((m_rows_spinbox->value() * m_columns_spinbox->value()) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomGameDialog::CustomGameDialog(Window* parent_window)
|
||||||
|
: Dialog(parent_window)
|
||||||
|
{
|
||||||
|
resize(305, 90);
|
||||||
|
center_on_screen();
|
||||||
|
set_resizable(false);
|
||||||
|
set_title("Custom game");
|
||||||
|
|
||||||
|
auto& main_widget = set_main_widget<GUI::Widget>();
|
||||||
|
if (!main_widget.load_from_gml(minesweeper_custom_game_window_gml))
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
|
||||||
|
m_columns_spinbox = *main_widget.find_descendant_of_type_named<GUI::SpinBox>("columns_spinbox");
|
||||||
|
m_rows_spinbox = *main_widget.find_descendant_of_type_named<GUI::SpinBox>("rows_spinbox");
|
||||||
|
m_mines_spinbox = *main_widget.find_descendant_of_type_named<GUI::SpinBox>("mines_spinbox");
|
||||||
|
m_ok_button = *main_widget.find_descendant_of_type_named<GUI::Button>("ok_button");
|
||||||
|
m_cancel_button = *main_widget.find_descendant_of_type_named<GUI::Button>("cancel_button");
|
||||||
|
|
||||||
|
m_columns_spinbox->on_change = [this](auto) {
|
||||||
|
set_max_mines();
|
||||||
|
};
|
||||||
|
|
||||||
|
m_rows_spinbox->on_change = [this](auto) {
|
||||||
|
set_max_mines();
|
||||||
|
};
|
||||||
|
|
||||||
|
m_ok_button->on_click = [this](auto) {
|
||||||
|
done(ExecResult::ExecOK);
|
||||||
|
};
|
||||||
|
|
||||||
|
m_cancel_button->on_click = [this](auto) {
|
||||||
|
done(ExecResult::ExecCancel);
|
||||||
|
};
|
||||||
|
|
||||||
|
set_max_mines();
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomGameDialog::~CustomGameDialog()
|
||||||
|
{
|
||||||
|
}
|
32
Userland/Games/Minesweeper/CustomGameDialog.h
Normal file
32
Userland/Games/Minesweeper/CustomGameDialog.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Pedro Pereira <pmh.pereira@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <LibGUI/Button.h>
|
||||||
|
#include <LibGUI/Dialog.h>
|
||||||
|
#include <LibGUI/SpinBox.h>
|
||||||
|
|
||||||
|
class Field;
|
||||||
|
|
||||||
|
class CustomGameDialog : public GUI::Dialog {
|
||||||
|
C_OBJECT(CustomGameDialog);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static int show(GUI::Window* parent_window, Field& field);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CustomGameDialog(GUI::Window* parent_window);
|
||||||
|
virtual ~CustomGameDialog() override;
|
||||||
|
|
||||||
|
void set_max_mines();
|
||||||
|
|
||||||
|
RefPtr<GUI::Button> m_ok_button;
|
||||||
|
RefPtr<GUI::Button> m_cancel_button;
|
||||||
|
RefPtr<GUI::SpinBox> m_columns_spinbox;
|
||||||
|
RefPtr<GUI::SpinBox> m_rows_spinbox;
|
||||||
|
RefPtr<GUI::SpinBox> m_mines_spinbox;
|
||||||
|
};
|
80
Userland/Games/Minesweeper/MinesweeperCustomGameWindow.gml
Normal file
80
Userland/Games/Minesweeper/MinesweeperCustomGameWindow.gml
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
@GUI::Widget {
|
||||||
|
fill_with_background_color: true
|
||||||
|
|
||||||
|
layout: @GUI::VerticalBoxLayout {
|
||||||
|
margins: [4]
|
||||||
|
}
|
||||||
|
|
||||||
|
@GUI::GroupBox {
|
||||||
|
title: "Field"
|
||||||
|
autosize: true
|
||||||
|
|
||||||
|
layout: @GUI::HorizontalBoxLayout {
|
||||||
|
margins: [16, 6, 6]
|
||||||
|
}
|
||||||
|
|
||||||
|
@GUI::Label {
|
||||||
|
text: "Columns: "
|
||||||
|
autosize: true
|
||||||
|
}
|
||||||
|
|
||||||
|
@GUI::SpinBox {
|
||||||
|
name: "columns_spinbox"
|
||||||
|
min: 10
|
||||||
|
max: 50
|
||||||
|
fixed_width: 40
|
||||||
|
}
|
||||||
|
|
||||||
|
@GUI::VerticalSeparator {
|
||||||
|
}
|
||||||
|
|
||||||
|
@GUI::Label {
|
||||||
|
text: "Rows: "
|
||||||
|
autosize: true
|
||||||
|
}
|
||||||
|
|
||||||
|
@GUI::SpinBox {
|
||||||
|
name: "rows_spinbox"
|
||||||
|
min: 10
|
||||||
|
max: 50
|
||||||
|
fixed_width: 40
|
||||||
|
}
|
||||||
|
|
||||||
|
@GUI::VerticalSeparator {
|
||||||
|
}
|
||||||
|
|
||||||
|
@GUI::Label {
|
||||||
|
text: "Mines: "
|
||||||
|
autosize: true
|
||||||
|
}
|
||||||
|
|
||||||
|
@GUI::SpinBox {
|
||||||
|
name: "mines_spinbox"
|
||||||
|
min: 1
|
||||||
|
max: 2500
|
||||||
|
fixed_width: 50
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GUI::Widget {
|
||||||
|
max_height: 24
|
||||||
|
|
||||||
|
layout: @GUI::HorizontalBoxLayout {
|
||||||
|
}
|
||||||
|
|
||||||
|
@GUI::Widget {
|
||||||
|
}
|
||||||
|
|
||||||
|
@GUI::Button {
|
||||||
|
name: "ok_button"
|
||||||
|
text: "OK"
|
||||||
|
max_width: 75
|
||||||
|
}
|
||||||
|
|
||||||
|
@GUI::Button {
|
||||||
|
name: "cancel_button"
|
||||||
|
text: "Cancel"
|
||||||
|
max_width: 75
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "CustomGameDialog.h"
|
||||||
#include "Field.h"
|
#include "Field.h"
|
||||||
#include <LibConfig/Client.h>
|
#include <LibConfig/Client.h>
|
||||||
#include <LibGUI/Action.h>
|
#include <LibGUI/Action.h>
|
||||||
|
@ -131,6 +132,10 @@ int main(int argc, char** argv)
|
||||||
difficulty_menu.add_action(GUI::Action::create("&Madwoman", { Mod_Ctrl, Key_M }, [&](auto&) {
|
difficulty_menu.add_action(GUI::Action::create("&Madwoman", { Mod_Ctrl, Key_M }, [&](auto&) {
|
||||||
field.set_field_size(32, 60, 350);
|
field.set_field_size(32, 60, 350);
|
||||||
}));
|
}));
|
||||||
|
difficulty_menu.add_separator();
|
||||||
|
difficulty_menu.add_action(GUI::Action::create("&Custom game...", { Mod_Ctrl, Key_C }, [&](auto&) {
|
||||||
|
CustomGameDialog::show(window, field);
|
||||||
|
}));
|
||||||
|
|
||||||
auto& help_menu = window->add_menu("&Help");
|
auto& help_menu = window->add_menu("&Help");
|
||||||
help_menu.add_action(GUI::CommonActions::make_about_action("Minesweeper", app_icon, window));
|
help_menu.add_action(GUI::CommonActions::make_about_action("Minesweeper", app_icon, window));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue