Terminal Games
Simple games that run in the terminal.
Loading...
Searching...
No Matches
Terminal.cpp
1// NOLINTBEGIN(misc-include-cleaner)
2#include <cstdint>
3#include <cstdlib>
4#include <iostream>
5#include <string>
6#include <tuple>
7#include <vector>
8
9#ifdef _WIN32
10 #include "conio.h"
11 #include "Windows.h"
12#endif
13
14#include "helpers/Globals.hpp"
15#include "helpers/PageBuilder.hpp"
16
17#include "helpers/Terminal.hpp"
18
19namespace TerminalGames
20{
21 bool Terminal::GetUserChoiceFromHomepage(const std::vector<std::string>& p_menus, const bool& p_useAnsiEscapeCodes)
22 {
23 // Yes option selected is at index 0 and No option selected is at index 1. Therefore, can convert the current selected
24 // index to a bool and invert it to get whether to use ANSI escape codes.
25 uint32_t currentSelection = static_cast<uint32_t>(!p_useAnsiEscapeCodes);
26
27 while (true)
28 {
29 PrintOutput(p_menus[currentSelection]);
30
31 switch (GetNextKeyPress())
32 {
35
37 return !static_cast<bool>(currentSelection);
38
40 currentSelection == 0 ? currentSelection = (p_menus.size() - 1) : --currentSelection;
41 break;
42
44 currentSelection == (p_menus.size() - 1) ? currentSelection = 0 : ++currentSelection;
45 break;
46
47 default:
48 break;
49 }
50 }
51 }
52
53 uint32_t Terminal::GetUserChoiceFromMainMenus(const std::vector<std::string>& p_menus)
54 {
55 uint32_t currentSelection = 0;
56
57 while (true)
58 {
59 PrintOutput(p_menus[currentSelection]);
60
61 switch (GetNextKeyPress())
62 {
65
67 return currentSelection;
68
70 currentSelection == 0 ? currentSelection = (p_menus.size() - 1) : --currentSelection;
71 break;
72
74 currentSelection == (p_menus.size() - 1) ? currentSelection = 0 : ++currentSelection;
75 break;
76
77 default:
78 break;
79 }
80 }
81 }
82
83 uint32_t Terminal::GetUserChoiceFromGameMenus(const std::vector<std::string>& p_menus, const std::vector<std::string>& p_quitOptionMenus)
84 {
85 uint32_t currentSelection = 0;
86
87 while (true)
88 {
89 PrintOutput(p_menus[currentSelection]);
90
91 switch (GetNextKeyPress())
92 {
94 Terminal::GetUserChoiceFromQuitMenus(p_quitOptionMenus);
95 break;
96
98 return currentSelection;
99
101 currentSelection == 0 ? currentSelection = (p_menus.size() - 1) : --currentSelection;
102 break;
103
105 currentSelection == (p_menus.size() - 1) ? currentSelection = 0 : ++currentSelection;
106 break;
107
108 default:
109 break;
110 }
111 }
112 }
113
114 std::tuple<uint32_t, uint32_t> Terminal::GetUserCommandFromGameGrid(
115 const std::tuple<uint32_t, uint32_t>& p_startingGridLocation,
116 const PageBuilder& p_pageBuilder,
117 const GameInformation& p_gameInformation,
118 const bool& p_displayGetUserCommandPage)
119 {
121 {
122 return GetUserCommandFromGameGridWindows(p_startingGridLocation, p_pageBuilder, p_gameInformation, p_displayGetUserCommandPage);
123 }
124
125 return GetUserCommandFromGameGridNonWindows(p_startingGridLocation, p_pageBuilder, p_gameInformation, p_displayGetUserCommandPage);
126 }
127
128 std::tuple<uint32_t, uint32_t> Terminal::GetUserCommandFromGameGridWindows(
129 const std::tuple<uint32_t, uint32_t>& p_startingGridLocation,
130 const PageBuilder& p_pageBuilder,
131 const GameInformation& p_gameInformation,
132 const bool& p_displayGetUserCommandPage)
133 {
134 PageBuilder pageBuilder = p_pageBuilder;
135 uint32_t currentRow = std::get<0>(p_startingGridLocation);
136 uint32_t currentColumn = std::get<1>(p_startingGridLocation);
137 uint32_t maxRow = 0;
138 uint32_t maxColumn = 0;
139 uint32_t gridLeftPad = 0;
140 uint32_t gridTopPad = 0;
141 uint32_t gridElementWidth = 0;
142 uint32_t gridElementHeight = 0;
143
144 switch (p_pageBuilder.GetCurrentPageType())
145 {
146 case Pages::TICTACTOE:
147 {
148 maxColumn = Globals::G_TICTACTOE_GRID_WIDTH - 1; // -1 to account for zero-indexing
149 maxRow = Globals::G_TICTACTOE_GRID_HEIGHT - 1; // -1 to account for zero-indexing
152 gridElementWidth = Globals::G_TICTACTOE_GRID_ELEMENT_WIDTH + 1; // +1 to account for the grid divider '|'
153 gridElementHeight = Globals::G_TICTACTOE_GRID_ELEMENT_HEIGHT + 1; // +1 to account for the grid divider '───'
154 break;
155 }
156
158 {
159 maxColumn = Globals::G_BATTLESHIPS_BOARD_WIDTH - 1; // -1 to account for zero-indexing
160 maxRow = Globals::G_BATTLESHIPS_BOARD_HEIGHT - 1; // -1 to account for zero-indexing
163 gridElementWidth = Globals::G_BATTLESHIPS_GRID_ELEMENT_WIDTH + 1; // +1 to account for the grid divider '|'
164 gridElementHeight = Globals::G_BATTLESHIPS_GRID_ELEMENT_HEIGHT + 1; // +1 to account for the grid divider '───'
165 break;
166 }
167
168 default:
170 }
171
172 if (p_displayGetUserCommandPage)
173 {
174 PrintOutput(pageBuilder.GetUserCommandPage(p_gameInformation));
175 }
176
177 while (true)
178 {
180 SetCursorPosition(static_cast<int16_t>(gridLeftPad + (currentColumn * gridElementWidth)), static_cast<int16_t>(gridTopPad + (currentRow * gridElementHeight)));
181
182 switch (GetNextKeyPress())
183 {
185 SetCursorVisibility(false);
188 break;
189
191 SetCursorVisibility(false);
193
195 SetCursorVisibility(false);
196 return {currentRow, currentColumn};
197
199 currentRow == 0 ? currentRow = maxRow : --currentRow;
200 break;
201
203 currentRow == maxRow ? currentRow = 0 : ++currentRow;
204 break;
205
207 currentColumn == 0 ? currentColumn = maxColumn : --currentColumn;
208 break;
209
211 currentColumn == maxColumn ? currentColumn = 0 : ++currentColumn;
212 break;
213
214 default:
215 break;
216 }
217 }
218 }
219
221 const std::tuple<uint32_t, uint32_t>& p_startingGridLocation,
222 const PageBuilder& p_pageBuilder,
223 const GameInformation& p_gameInformation,
224 const bool& p_displayGetUserCommandPage)
225 {
226 const Pages CURRENT_PAGE_TYPE = p_pageBuilder.GetCurrentPageType();
227 PageBuilder pageBuilder = p_pageBuilder;
228 uint32_t currentRow = std::get<0>(p_startingGridLocation);
229 uint32_t currentColumn = std::get<1>(p_startingGridLocation);
230 uint32_t maxRow = 0;
231 uint32_t maxColumn = 0;
232
233 switch (CURRENT_PAGE_TYPE)
234 {
235 case Pages::TICTACTOE:
236 maxColumn = Globals::G_TICTACTOE_GRID_WIDTH - 1; // -1 to account for zero-indexing
237 maxRow = Globals::G_TICTACTOE_GRID_HEIGHT - 1; // -1 to account for zero-indexing
238 break;
239
241 maxColumn = Globals::G_BATTLESHIPS_BOARD_WIDTH - 1; // -1 to account for zero-indexing
242 maxRow = Globals::G_BATTLESHIPS_BOARD_HEIGHT - 1; // -1 to account for zero-indexing
243 break;
244
245 default:
247 }
248
249 while (true)
250 {
251 GameInformation currentGameInformation = p_gameInformation;
252
253 if (CURRENT_PAGE_TYPE == Pages::TICTACTOE)
254 {
255 currentGameInformation.m_ticTacToeGameInformation.m_gameGrid.at(currentRow).at(currentColumn) = "#" + std::string(1, currentGameInformation.m_ticTacToeGameInformation.m_gameGrid.at(currentRow).at(currentColumn).at(1)) + "#";
256 }
257
258 else if (CURRENT_PAGE_TYPE == Pages::BATTLESHIPS && p_displayGetUserCommandPage)
259 {
260 currentGameInformation.m_battleshipsGameInformation.m_boardPlayerTwo.at(currentRow).at(currentColumn) = "#" + std::string(1, currentGameInformation.m_battleshipsGameInformation.m_boardPlayerTwo.at(currentRow).at(currentColumn).at(0)) + "#";
261 }
262
263 else if (CURRENT_PAGE_TYPE == Pages::BATTLESHIPS)
264 {
265 currentGameInformation.m_battleshipsGameInformation.m_boardPlayerOne.at(currentRow).at(currentColumn) = "#" + std::string(1, currentGameInformation.m_battleshipsGameInformation.m_boardPlayerOne.at(currentRow).at(currentColumn).at(0)) + "#";
266 }
267
268 if (p_displayGetUserCommandPage)
269 {
270 PrintOutput(pageBuilder.GetUserCommandPage(currentGameInformation));
271 }
272
273 switch (GetNextKeyPress())
274 {
276 SetCursorVisibility(false);
279 break;
280
282 SetCursorVisibility(false);
284
286 SetCursorVisibility(false);
287 return {currentRow, currentColumn};
288
290 currentRow == 0 ? currentRow = maxRow : --currentRow;
291 break;
292
294 currentRow == maxRow ? currentRow = 0 : ++currentRow;
295 break;
296
298 currentColumn == 0 ? currentColumn = maxColumn : --currentColumn;
299 break;
300
302 currentColumn == maxColumn ? currentColumn = 0 : ++currentColumn;
303 break;
304
305 default:
306 break;
307 }
308 }
309 }
310
311 void Terminal::GetUserChoiceFromGameOverMenu(const std::string& p_gameOverPage, const std::vector<std::string>& p_quitOptionMenus)
312 {
313 while (true)
314 {
315 PrintOutput(p_gameOverPage);
316
317 switch (GetNextKeyPress())
318 {
320 GetUserChoiceFromQuitMenus(p_quitOptionMenus);
321 break;
322
325
326 default:
328 }
329 }
330 }
331
332 void Terminal::GetUserChoiceFromQuitMenus(const std::vector<std::string>& p_menus)
333 {
334 uint32_t currentSelection = 0;
335
336 while (true)
337 {
338 PrintOutput(p_menus[currentSelection]);
339
340 switch (GetNextKeyPress())
341 {
343 switch (currentSelection)
344 {
347
350
353
356
359
361 return;
362
363 default:
364 break;
365 }
366
368 currentSelection == 0 ? currentSelection = (p_menus.size() - 1) : --currentSelection;
369 break;
370
372 currentSelection == (p_menus.size() - 1) ? currentSelection = 0 : ++currentSelection;
373 break;
374
375 default:
376 break;
377 }
378 }
379 }
380
381 void Terminal::PrintOutput(const std::string& p_output)
382 {
383 Clear();
384 std::cout << p_output;
385 }
386
388 {
389#ifdef _WIN32
390 // Windows API method taken from https://www.cplusplus.com/articles/4z18T05o
391 const COORD HOME_COORDS = {0, 0};
392 CONSOLE_SCREEN_BUFFER_INFO consoleScreenBufferInfo;
393 DWORD count = 0;
394 DWORD cellCount = 0;
395
396 HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
397 if (hStdOut == INVALID_HANDLE_VALUE)
398 {
399 std::exit(1);
400 }
401
402 // Get the number of cells in the current buffer
403 if (!static_cast<bool>(GetConsoleScreenBufferInfo(hStdOut, &consoleScreenBufferInfo)))
404 {
405 std::exit(2);
406 }
407
408 cellCount = consoleScreenBufferInfo.dwSize.X * consoleScreenBufferInfo.dwSize.Y;
409
410 // Fill the entire buffer with spaces
411 if (!FillConsoleOutputCharacter(hStdOut, ' ', cellCount, HOME_COORDS, &count))
412 {
413 std::exit(3);
414 }
415
416 // Fill the entire buffer with the current colors and attributes
417 if (!static_cast<bool>(FillConsoleOutputAttribute(hStdOut, consoleScreenBufferInfo.wAttributes, cellCount, HOME_COORDS, &count)))
418 {
419 std::exit(4);
420 }
421
422 // Move the cursor home
423 SetConsoleCursorPosition(hStdOut, HOME_COORDS);
424#else
425 std::cout << "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
426#endif
427 }
428
430 {
431#ifdef _WIN32
432 FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
433 return _getch();
434#else
435 std::string inputString;
436
437 while (true)
438 {
439 std::getline(std::cin, inputString);
440
441 if (inputString.size() != 1)
442 {
443 continue;
444 }
445
446 switch (inputString[0])
447 {
450
453
456
459
462
465
466 default:
467 return inputString[0];
468 }
469 }
470#endif
471 }
472
473 void Terminal::SetCursorVisibility(const bool& p_cursorVisibility)
474 {
475#ifdef _WIN32
476 const CONSOLE_CURSOR_INFO CURSOR_INFO(Globals::G_TERMINAL_CURSOR_WIDTH_PERCENTAGE, static_cast<int32_t>(p_cursorVisibility));
477 SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &CURSOR_INFO);
478#endif
479 }
480
481 void Terminal::SetCursorPosition(const int16_t& p_xCoord, const int16_t& p_yCoord)
482 {
483#ifdef _WIN32
484 const COORD CURSOR_POSITION(p_xCoord, p_yCoord);
485 SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), CURSOR_POSITION);
486#endif
487 }
488
490 {
491 Clear();
492 SetCursorVisibility(false);
493 }
494
496 {
497 Clear();
499 }
500}
501
502// NOLINTEND(misc-include-cleaner)
Used when the backspace key is pressed.
Definition Globals.hpp:61
Used for functionality that has not been implemented.
Definition Globals.hpp:68
Used to reset a game which prompts the user for new options.
Definition Globals.hpp:47
Used to restart a game with the same user options.
Definition Globals.hpp:54
Builds pages (i.e. strings) to be printed to the terminal.
std::vector< std::string > GetQuitOptionSelectionPage() const
Creates the quit option selection page.
Pages GetCurrentPageType() const
Get the current page type.
std::string GetUserCommandPage(const GameInformation &p_gameInformation)
Creates the game user command page which should prompt the user to enter a command.
static void GetUserChoiceFromGameOverMenu(const std::string &p_gameOverPage, const std::vector< std::string > &p_quitOptionMenus)
Get the user choice whether to restart the game, reset the game or a choice from the GetUserChoiceFro...
Definition Terminal.cpp:311
static void SetCursorVisibility(const bool &p_cursorVisibility)
Wrapper around the <Windows.h> API for the SetConsoleCursorInfo() function.
Definition Terminal.cpp:473
static std::tuple< uint32_t, uint32_t > GetUserCommandFromGameGridWindows(const std::tuple< uint32_t, uint32_t > &p_startingGridLocation, const PageBuilder &p_pageBuilder, const GameInformation &p_gameInformation, const bool &p_displayGetUserCommandPage)
(Windows) Gets a user command based on the currently displayed game grid.
Definition Terminal.cpp:128
static uint32_t GetNextKeyPress()
Wrapper for <Windows.h> API for the FlushConsoleInputBuffer() and _getch() functions.
Definition Terminal.cpp:429
static void PrintOutput(const std::string &p_output)
Clears and then prints to the terminal.
Definition Terminal.cpp:381
static uint32_t GetUserChoiceFromGameMenus(const std::vector< std::string > &p_menus, const std::vector< std::string > &p_quitOptionMenus)
Get the user choice from a list of game menus screens that are printed to the terminal.
Definition Terminal.cpp:83
static void ResetTerminal()
Resets the terminal to its original state before the program was run.
Definition Terminal.cpp:495
static uint32_t GetUserChoiceFromMainMenus(const std::vector< std::string > &p_menus)
Get the user choice from a list of main menus screens that are printed to the terminal.
Definition Terminal.cpp:53
static std::tuple< uint32_t, uint32_t > GetUserCommandFromGameGridNonWindows(const std::tuple< uint32_t, uint32_t > &p_startingGridLocation, const PageBuilder &p_pageBuilder, const GameInformation &p_gameInformation, const bool &p_displayGetUserCommandPage)
(Non-window) Gets a user command based on the currently displayed game grid.
Definition Terminal.cpp:220
static void Clear()
Clears the terminal based on this article: https://www.cplusplus.com/articles/4z18T05o.
Definition Terminal.cpp:387
static std::tuple< uint32_t, uint32_t > GetUserCommandFromGameGrid(const std::tuple< uint32_t, uint32_t > &p_startingGridLocation, const PageBuilder &p_pageBuilder, const GameInformation &p_gameInformation, const bool &p_displayGetUserCommandPage)
Gets a user command based on the currently displayed game grid (wrapper function around the platform-...
Definition Terminal.cpp:114
static bool GetUserChoiceFromHomepage(const std::vector< std::string > &p_menus, const bool &p_useAnsiEscapeCodes)
Get the user choice from a list of homepage screens that are printed to the terminal.
Definition Terminal.cpp:21
static void InitialiseTerminal()
Initialises the terminal for the program.
Definition Terminal.cpp:489
static void SetCursorPosition(const int16_t &p_xCoord, const int16_t &p_yCoord)
Wrapper around the <Windows.h> API for the SetConsoleCursorPosition() function.
Definition Terminal.cpp:481
static void GetUserChoiceFromQuitMenus(const std::vector< std::string > &p_menus)
Gets the user choice from the quit menu. All user choices result in a different custom exception bein...
Definition Terminal.cpp:332
static const uint32_t G_BATTLESHIPS_GRID_ELEMENT_HEIGHT
Battleships board attributes.
Definition Globals.hpp:1579
static const uint32_t G_TERMINAL_ALTERNATIVE_DOWN_ARROW_KEY
Keyboard values when getting user input other platforms.
Definition Globals.hpp:366
static const uint32_t G_TERMINAL_ALTERNATIVE_LEFT_ARROW_KEY
Keyboard values when getting user input other platforms.
Definition Globals.hpp:367
static const bool G_PLATFORM_IS_WINDOWS
Used by PageBuilder to display the current platform being used and used by Terminal to decided whethe...
Definition Globals.hpp:166
static const uint32_t G_QUIT_MENU_QUIT_GAME_INDEX
Quit menu options.
Definition Globals.hpp:331
static const uint32_t G_QUIT_MENU_QUIT_PROGRAM_INDEX
Quit menu options.
Definition Globals.hpp:333
static const uint32_t G_BATTLESHIPS_GRID_TOP_PAD
Battleships board attributes.
Definition Globals.hpp:1582
static const uint32_t G_TERMINAL_ENTER_KEY
Keyboard values when getting user input on Windows.
Definition Globals.hpp:349
static const uint32_t G_TERMINAL_RIGHT_ARROW_KEY
Keyboard values when getting user input on Windows.
Definition Globals.hpp:354
static const uint32_t G_BATTLESHIPS_BOARD_WIDTH
Battleships board attributes.
Definition Globals.hpp:1576
static const uint32_t G_TICTACTOE_GRID_WIDTH
TicTacToe grid attributes.
Definition Globals.hpp:394
static const uint32_t G_QUIT_MENU_QUIT_MAIN_MENU_INDEX
Quit menu options.
Definition Globals.hpp:332
static const uint32_t G_TERMINAL_ALTERNATIVE_RIGHT_ARROW_KEY
Keyboard values when getting user input other platforms.
Definition Globals.hpp:368
static const uint32_t G_TERMINAL_CURSOR_WIDTH_PERCENTAGE
The cursor width while running on windows.
Definition Globals.hpp:374
static const uint32_t G_TICTACTOE_GRID_ELEMENT_HEIGHT
TicTacToe grid attributes.
Definition Globals.hpp:397
static const uint32_t G_TERMINAL_ALTERNATIVE_BACKSPACE_KEY
Keyboard values when getting user input other platforms.
Definition Globals.hpp:364
static const uint32_t G_TICTACTOE_GRID_LEFT_PAD
TicTacToe grid attributes.
Definition Globals.hpp:398
static const uint32_t G_TERMINAL_LEFT_ARROW_KEY
Keyboard values when getting user input on Windows.
Definition Globals.hpp:353
static const uint32_t G_BATTLESHIPS_GRID_ELEMENT_WIDTH
Battleships board attributes.
Definition Globals.hpp:1578
static const uint32_t G_TICTACTOE_GRID_TOP_PAD
TicTacToe grid attributes.
Definition Globals.hpp:399
static const uint32_t G_QUIT_MENU_RESTART_GAME_INDEX
Quit menu options.
Definition Globals.hpp:329
static const uint32_t G_TERMINAL_UP_ARROW_KEY
Keyboard values when getting user input on Windows.
Definition Globals.hpp:351
static const uint32_t G_QUIT_MENU_CANCEL_INDEX
Quit menu options.
Definition Globals.hpp:334
static const uint32_t G_TERMINAL_ALTERNATIVE_UP_ARROW_KEY
Keyboard values when getting user input other platforms.
Definition Globals.hpp:365
static const uint32_t G_QUIT_MENU_RESET_GAME_INDEX
Quit menu options.
Definition Globals.hpp:330
static const uint32_t G_BATTLESHIPS_GRID_PLAYER_ONE_BOARD_LEFT_PAD
Battleships board attributes.
Definition Globals.hpp:1580
static const uint32_t G_TICTACTOE_GRID_ELEMENT_WIDTH
TicTacToe grid attributes.
Definition Globals.hpp:396
static const uint32_t G_BATTLESHIPS_GRID_PLAYER_TWO_BOARD_LEFT_PAD
Battleships board attributes.
Definition Globals.hpp:1581
static const uint32_t G_TERMINAL_RESTART_KEY
Keyboard values when getting user input on Windows.
Definition Globals.hpp:356
static const uint32_t G_TERMINAL_DOWN_ARROW_KEY
Keyboard values when getting user input on Windows.
Definition Globals.hpp:352
static const uint32_t G_TERMINAL_BACKSPACE_KEY
Keyboard values when getting user input on Windows.
Definition Globals.hpp:350
static const uint32_t G_TERMINAL_ALTERNATIVE_ENTER_KEY
Keyboard values when getting user input other platforms.
Definition Globals.hpp:363
static const uint32_t G_TERMINAL_QUIT_KEY
Keyboard values when getting user input on Windows.
Definition Globals.hpp:355
static const uint32_t G_BATTLESHIPS_BOARD_HEIGHT
Battleships board attributes.
Definition Globals.hpp:1577
static const uint32_t G_TICTACTOE_GRID_HEIGHT
TicTacToe grid attributes.
Definition Globals.hpp:395
Contains all Terminal-Games objects.
Pages
Represents the page types that are supported by PageBuilder.
@ TICTACTOE
Page supported by PageBuilder.
@ BATTLESHIPS
Page supported by PageBuilder.
std::array< std::array< std::string, Globals::G_BATTLESHIPS_BOARD_WIDTH >, Globals::G_BATTLESHIPS_BOARD_HEIGHT > m_boardPlayerOne
Refer to the member data documentation in Battleships.
std::array< std::array< std::string, Globals::G_BATTLESHIPS_BOARD_WIDTH >, Globals::G_BATTLESHIPS_BOARD_HEIGHT > m_boardPlayerTwo
Refer to the member data documentation in Battleships.
std::array< std::array< std::string, Globals::G_TICTACTOE_GRID_WIDTH >, Globals::G_TICTACTOE_GRID_HEIGHT > m_gameGrid
Refer to the member data documentation in TicTacToe.
Used by game objects to package themselves into a format that can be used by PageBuilder to construct...
struct TerminalGames::GameInformation::BattleshipsGameInformation m_battleshipsGameInformation
Used to package the Battleships current game state.
struct TerminalGames::GameInformation::TicTacToeGameInformation m_ticTacToeGameInformation
Used to package the TicTacToe current game state.