Skip to content

Commit 2035d93

Browse files
committed
Make game state more obvious, playable
1 parent 9036cfc commit 2035d93

File tree

1 file changed

+50
-21
lines changed

1 file changed

+50
-21
lines changed

src/main.cpp

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,29 @@ static constexpr auto USAGE =
2626
)";
2727

2828

29-
struct GameBoard
29+
template<std::size_t Width, std::size_t Height> struct GameBoard
3030
{
31-
static constexpr std::size_t width = 5;
32-
static constexpr std::size_t height = 5;
31+
static constexpr std::size_t width = Width;
32+
static constexpr std::size_t height = Height;
3333

3434
std::array<std::array<std::string, height>, width> strings;
3535
std::array<std::array<bool, height>, width> values{};
3636

37+
std::size_t move_count{0};
38+
39+
std::string &get_string(std::size_t x, std::size_t y) {
40+
return strings.at(x).at(y);
41+
}
42+
43+
3744
void set(std::size_t x, std::size_t y, bool new_value)
3845
{
39-
values[x][y] = new_value;
46+
get(x,y) = new_value;
4047

4148
if (new_value) {
42-
strings[x][y] = " ON";
49+
get_string(x,y) = " ON";
4350
} else {
44-
strings[x][y] = "OFF";
51+
get_string(x,y) = "OFF";
4552
}
4653
}
4754

@@ -52,7 +59,9 @@ struct GameBoard
5259
}
5360
}
5461

55-
bool get(std::size_t x, std::size_t y) const { return values[x][y]; }
62+
[[nodiscard]] bool get(std::size_t x, std::size_t y) const { return values.at(x).at(y); }
63+
64+
[[nodiscard]] bool &get(std::size_t x, std::size_t y) { return values.at(x).at(y); }
5665

5766
GameBoard()
5867
{
@@ -70,13 +79,15 @@ struct GameBoard
7079

7180
void press(std::size_t x, std::size_t y)
7281
{
82+
++move_count;
83+
toggle(x, y);
7384
if (x > 0) { toggle(x - 1, y); }
7485
if (y > 0) { toggle(x, y - 1); }
7586
if (x < width - 1) { toggle(x + 1, y); }
7687
if (y < height - 1) { toggle(x, y + 1); }
7788
}
7889

79-
bool solved() const
90+
[[nodiscard]] bool solved() const
8091
{
8192
for (std::size_t x = 0; x < width; ++x) {
8293
for (std::size_t y = 0; y < height; ++y) {
@@ -99,18 +110,24 @@ int main(int argc, const char **argv)
99110
myproject::cmake::project_version));// version string, acquired
100111
// from config.hpp via CMake
101112

102-
using namespace ftxui;
103-
auto screen = ScreenInteractive::TerminalOutput();
113+
auto screen = ftxui::ScreenInteractive::TerminalOutput();
114+
115+
GameBoard<3, 3> gb;
104116

105-
GameBoard gb;
117+
std::string quit_text;
118+
119+
const auto update_quit_text = [&quit_text](const auto &game_board) {
120+
quit_text = fmt::format("Quit ({} moves)", game_board.move_count);
121+
if (game_board.solved()) { quit_text += " Solved!"; }
122+
};
106123

107124
const auto make_buttons = [&] {
108125
std::vector<ftxui::Component> buttons;
109126
for (std::size_t x = 0; x < gb.width; ++x) {
110127
for (std::size_t y = 0; y < gb.height; ++y) {
111-
buttons.push_back(ftxui::Button(&gb.strings[x][y], [x, y, &gb, &screen] {
112-
gb.press(x, y);
113-
if (gb.solved()) { screen.ExitLoopClosure()(); }
128+
buttons.push_back(ftxui::Button(&gb.get_string(x,y), [=, &gb] {
129+
if (!gb.solved()) { gb.press(x, y); }
130+
update_quit_text(gb);
114131
}));
115132
}
116133
}
@@ -119,10 +136,10 @@ int main(int argc, const char **argv)
119136

120137
auto buttons = make_buttons();
121138

122-
auto container = Container::Horizontal(buttons);
139+
auto quit_button = ftxui::Button(&quit_text, screen.ExitLoopClosure());
123140

124141
auto make_layout = [&] {
125-
std::vector<ftxui::Element> columns;
142+
std::vector<ftxui::Element> rows;
126143

127144
std::size_t idx = 0;
128145

@@ -132,23 +149,35 @@ int main(int argc, const char **argv)
132149
row.push_back(buttons[idx]->Render());
133150
++idx;
134151
}
135-
columns.push_back(ftxui::hbox(std::move(row)));
152+
rows.push_back(ftxui::hbox(std::move(row)));
136153
}
137154

138-
return ftxui::vbox(std::move(columns));
155+
rows.push_back(ftxui::hbox({ quit_button->Render() }));
156+
157+
return ftxui::vbox(std::move(rows));
139158
};
140159

141-
std::mt19937 gen32;
160+
161+
static constexpr int randomization_iterations = 100;
162+
static constexpr int random_seed = 42;
163+
164+
std::mt19937 gen32{random_seed}; // NOLINT
142165
std::uniform_int_distribution<std::size_t> x(static_cast<std::size_t>(0), gb.width - 1);
143166
std::uniform_int_distribution<std::size_t> y(static_cast<std::size_t>(0), gb.height - 1);
144167

145-
for (int i = 0; i < 100; ++i) { gb.press(x(gen32), y(gen32)); }
168+
for (int i = 0; i < randomization_iterations; ++i) { gb.press(x(gen32), y(gen32)); }
169+
gb.move_count = 0;
170+
update_quit_text(gb);
146171

147-
auto renderer = Renderer(container, make_layout);
172+
auto all_buttons = buttons;
173+
all_buttons.push_back(quit_button);
174+
auto container = ftxui::Container::Horizontal(all_buttons);
148175

176+
auto renderer = ftxui::Renderer(container, make_layout);
149177

150178
screen.Loop(renderer);
151179

180+
152181
} catch (const std::exception &e) {
153182
fmt::print("Unhandled exception in main: {}", e.what());
154183
}

0 commit comments

Comments
 (0)