@@ -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