diff --git a/src/game.cpp b/src/game.cpp index 28b9b3d2..a3d099be 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -207,7 +207,8 @@ void Game::drawBoard() { std::cout << " "; } else { std::cout << currentTile.tileColor(currentTile.value) << bold_on - << std::setw(4) << currentTile.value << bold_off << def; + << std::setw(4) << theme.themedOutput(currentTile.value) + << bold_off << def; } } @@ -544,7 +545,7 @@ void Game::statistics() { endl(); std::cout << " Final score: " << bold_on << score << bold_off; endl(); - std::cout << " Largest Tile: " << bold_on << largestTile << bold_off; + std::cout << " Largest Tile: " << bold_on << theme.themedOutput(largestTile) << bold_off; endl(); std::cout << " Number of moves: " << bold_on << moveCount << bold_off; endl(); @@ -577,7 +578,7 @@ void Game::saveScore() { s.score = score; s.win = win; s.moveCount = moveCount; - s.largestTile = largestTile; + s.largestTile = theme.themedOutput(largestTile); s.duration = duration; s.save(); } @@ -688,6 +689,8 @@ void Game::startGame() { } setBoardSize(); + loadThemes(themeController); + theme = themeController.chooseTheme(); initialiseBoardArray(); addTile(); diff --git a/src/headers/game.hpp b/src/headers/game.hpp index 185d09a8..31bd37e3 100644 --- a/src/headers/game.hpp +++ b/src/headers/game.hpp @@ -5,6 +5,7 @@ #include "global.hpp" #include "scores.hpp" #include "statistics.hpp" +#include "themes.hpp" #include #include #include @@ -62,6 +63,8 @@ class Game { RandInt randInt; bool stateSaved; bool noSave; + Theme theme; + ThemeController themeController; enum ContinueStatus { STATUS_END_GAME = 0, STATUS_CONTINUE = 1 }; enum KeyInputErrorStatus { STATUS_INPUT_VALID = 0, STATUS_INPUT_ERROR = 1 }; diff --git a/src/headers/scores.hpp b/src/headers/scores.hpp index 0197b8b7..b4073cdc 100644 --- a/src/headers/scores.hpp +++ b/src/headers/scores.hpp @@ -14,7 +14,7 @@ struct Score { std::string name; ull score; bool win; - ull largestTile; + std::string largestTile; long long moveCount; double duration; }; @@ -31,7 +31,7 @@ class Scoreboard { public: ull score = 0; bool win; - ull largestTile; + std::string largestTile; long long moveCount; double duration; void printScore(); diff --git a/src/headers/themes.hpp b/src/headers/themes.hpp new file mode 100644 index 00000000..3071f549 --- /dev/null +++ b/src/headers/themes.hpp @@ -0,0 +1,53 @@ +#ifndef THEMES_H +#define THEMES_H + +#include "color.hpp" +#include "global.hpp" +#include +#include +#include +#include +#include +#include + +std::vector intv_to_strv(std::vector intv); + +class Theme { +public: + Theme() = default; + Theme(std::string _theme_name, std::vector _themed_output) + : theme_name(std::move(_theme_name)), + themed_output_vector(std::move(_themed_output)){}; + Theme(std::string _theme_name, + std::function _themed_output_function) + : theme_name(std::move(_theme_name)), themed_output_vector(), + themed_output_function(std::move(_themed_output_function)){}; + bool operator==(const Theme &t) const { + if (!themed_output_vector.empty()) + return themed_output_vector == t.themed_output_vector; + return false; + } + std::string themedOutput(ull value); + std::string themedOutputByIndex(int index); + std::string menuentry(); + +private: + std::string theme_name; + std::vector themed_output_vector; + std::function themed_output_function; +}; + +class ThemeController { +public: + ThemeController() = default; + Theme chooseTheme(); + void addTheme(Theme xTheme); + +private: + int theme_code = 0; + std::vector registry; +}; + +void loadThemes(ThemeController &controller); + +#endif diff --git a/src/scores.cpp b/src/scores.cpp index 552ad5f9..4f191485 100644 --- a/src/scores.cpp +++ b/src/scores.cpp @@ -40,7 +40,7 @@ void Scoreboard::printScore() { ull playerScore = scoreList[i].score; std::string won = scoreList[i].win ? "Yes" : "No"; long long moveCount = scoreList[i].moveCount; - ull largestTile = scoreList[i].largestTile; + std::string largestTile = scoreList[i].largestTile; double duration = scoreList[i].duration; if (i == size - 1) { @@ -143,7 +143,7 @@ void Scoreboard::readFile() { std::string playerName; ull playerScore; bool win; - ull largestTile; + std::string largestTile; long long moveCount; double duration; diff --git a/src/themes.cpp b/src/themes.cpp new file mode 100644 index 00000000..f69f24f8 --- /dev/null +++ b/src/themes.cpp @@ -0,0 +1,85 @@ +#include "themes.hpp" +#include "menu.hpp" +#include + +std::string Theme::themedOutput(ull value) { + return themedOutputByIndex(int(log2(value) - 1)); +} + +std::string Theme::themedOutputByIndex(int index) { + if (!themed_output_vector.empty()) + return themed_output_vector[index]; + return themed_output_function(index); +} + +std::string Theme::menuentry() { + std::ostringstream ret; + ret << theme_name << ": "; + for (int i = 0; i < 3; ++i) + ret << themedOutputByIndex(i) << ", "; + ret << "..."; + return ret.str(); +} + +Theme ThemeController::chooseTheme() { + bool err = false; + ull themeCount = registry.size(); + while ((theme_code > themeCount || theme_code < 1)) { + clearScreen(); + drawAscii(); + + if (err) { + std::cout << red + << " Invalid input. Theme number should range from 1 to " + << themeCount << "." << def; + endl(2); + } + + std::cout << bold_on; + for (int i = 1; i <= themeCount; ++i) + std::cout << " " << i << ". " << registry[i - 1].menuentry() + << std::endl; + std::cout << " Enter theme number: " << bold_off; + + std::cin >> theme_code; + std::cin.clear(); + std::cin.ignore(std::numeric_limits::max(), '\n'); + err = true; + } + return registry[theme_code - 1]; +} + +void ThemeController::addTheme(Theme xTheme) { + for (auto &r : registry) + if (r == xTheme) + return; + registry.push_back(xTheme); +} + +std::vector intv_to_strv(std::vector intv) { + std::vector strv; + strv.reserve(intv.size()); + for (auto &i : intv) { + strv.push_back(std::to_string(i)); + } + return strv; +} + +void loadThemes(ThemeController &controller) { + controller.addTheme(Theme( + "Standard", [](int index) { return std::to_string(ull(2) << index); })); + + controller.addTheme(Theme("Elements", {"H", "He", "Li", "Be", "B", "C", "N", + "O", "F", "Ne", "Na", "Ca", "Sc"})); + controller.addTheme(Theme("Fibonacci Numbers", [](int index) { + ull DP[index + 2]; + DP[0] = 1; + DP[1] = 2; + for (int i = 2; i <= index; ++i) + DP[i] = DP[i - 1] + DP[i - 2]; + return std::to_string(DP[index]); + })); + controller.addTheme(Theme("Programming Languages", + {"C", "C++", "PHP", "C#", "Py", "Bash", "Java", + "SQL", "CSS", "HTML", "JS", "Go", "Rust"})); +} \ No newline at end of file