From cc3869ac0b24a97dbadc6b837b3c23af28baa627 Mon Sep 17 00:00:00 2001 From: HampusM Date: Sat, 19 Feb 2022 17:30:16 +0100 Subject: feat: add basic program stuff --- CMakeLists.txt | 5 ++- src/conversion.cpp | 41 +++++++++++++++++++ src/conversion.hpp | 13 ++++++ src/game/options.hpp | 10 +++++ src/game_of_life.cpp | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/randomization.cpp | 21 ++++++++++ src/randomization.hpp | 35 ++++++++++++++++ 7 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 src/conversion.cpp create mode 100644 src/conversion.hpp create mode 100644 src/game/options.hpp create mode 100644 src/randomization.cpp create mode 100644 src/randomization.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 278d57e..616ab2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,10 @@ set(CMAKE_CXX_STANDARD 20) project(game-of-life CXX) -file(GLOB SOURCES src/game_of_life.cpp) +file(GLOB SOURCES + src/game_of_life.cpp + src/conversion.cpp + src/randomization.cpp) add_executable(${PROJECT_NAME} ${SOURCES}) diff --git a/src/conversion.cpp b/src/conversion.cpp new file mode 100644 index 0000000..79b3587 --- /dev/null +++ b/src/conversion.cpp @@ -0,0 +1,41 @@ +#include "conversion.hpp" + +#include +#include + +unsigned int str_to_uint(const std::string_view &str) +{ + if (str.at(0) == '-') + { + throw "Less than 0"; + } + + std::size_t waste_pos = 0; + + uint64_t num = 0; + + try + { + num = std::stoul(str.data(), &waste_pos, NUMBER_BASE); + } + catch (const std::invalid_argument &exc) + { + throw "Not a number"; + } + catch (const std::out_of_range &exc) + { + throw "Out of range"; + } + + if (waste_pos != str.length()) + { + throw "Not a number"; + } + + if (num > UINT_MAX) + { + throw "Out of range"; + } + + return static_cast(num); +} diff --git a/src/conversion.hpp b/src/conversion.hpp new file mode 100644 index 0000000..4ae5b7c --- /dev/null +++ b/src/conversion.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include + +constexpr unsigned int NUMBER_BASE = 10U; + +/** + * Converts a string to a unsigned integer. + * + * @param str A string that possibly is a unsigned integer + * @returns A unsigned integer + */ +unsigned int str_to_uint(const std::string_view &str); diff --git a/src/game/options.hpp b/src/game/options.hpp new file mode 100644 index 0000000..98360b8 --- /dev/null +++ b/src/game/options.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include "randomization.hpp" + +#include + +struct GameOptions +{ + std::shared_ptr random_gen; +}; diff --git a/src/game_of_life.cpp b/src/game_of_life.cpp index e69de29..32d393e 100644 --- a/src/game_of_life.cpp +++ b/src/game_of_life.cpp @@ -0,0 +1,108 @@ +#include "conversion.hpp" +#include "game/options.hpp" +#include "randomization.hpp" + +#include +#include +#include +#include +#include + +namespace +{ +void optarg_error(char arg, const std::string_view &error) +{ + std::cout << "Error: Invalid option argument for -" << arg << ". " << error + << std::endl; + exit(EXIT_FAILURE); +} + +/** + * Returns the current optarg as a string view. + */ +std::string_view get_str_optarg() +{ + return std::string_view(optarg); +} + +/** + * Returns the current optarg as a unsigned integer. + * + * @param arg The current command-line argument character + * @param check_zero Whether or not to make sure that the result is not zero + */ +unsigned int get_uint_optarg(char arg, bool check_zero = false) +{ + unsigned int num = 0; + + try + { + num = str_to_uint(get_str_optarg()); + + if (check_zero && num == 0) + { + throw "It should not be 0"; + } + } + catch (const char *error) + { + optarg_error(arg, std::string_view(error)); + } + + return num; +} +} // namespace + +constexpr std::array options = { + option({"seed", required_argument, nullptr, 's'}), + option({"help", no_argument, nullptr, 0}), option({nullptr, 0, nullptr, 0})}; + +int main(int argc, char *argv[]) +{ + auto args = std::vector(argv, argv + argc); + + GameOptions game_options; + + char arg = 0; + while ((arg = static_cast( + getopt_long(argc, argv, "s:", options.data(), nullptr))) != -1) + { + switch (arg) + { + case 's': + { + auto seed = get_uint_optarg(arg, true); + + game_options.random_gen = std::make_shared(seed); + break; + } + case 0: + { + std::cout << "Usage: " << args[0] + << " [OPTION]...\n\n" + "Options:\n" + << " -s, --seed SEED The randomization seed used\n" + " --help Displays usage information" + << std::endl; + return EXIT_SUCCESS; + } + case '?': + { + std::cout << "\nTry '" << args[0] << " --help' for more information" + << std::endl; + return EXIT_FAILURE; + } + default: + abort(); + } + } + + if (game_options.random_gen == nullptr) + { + game_options.random_gen = std::make_shared(); + } + + // auto game = Game(game_options); + + // game.run(); +} diff --git a/src/randomization.cpp b/src/randomization.cpp new file mode 100644 index 0000000..8f233d2 --- /dev/null +++ b/src/randomization.cpp @@ -0,0 +1,21 @@ +#include "randomization.hpp" + +RandomNumberGenerator::RandomNumberGenerator(const unsigned int &seed) +{ + this->_generator = std::make_unique(seed); +} + +RandomNumberGenerator::RandomNumberGenerator() +{ + std::random_device random_device; + + this->_generator = std::make_unique(random_device()); +} + +unsigned int RandomNumberGenerator::in_range(const unsigned int &a, + const unsigned int &b) const +{ + auto random_distribution = std::uniform_int_distribution(a, b); + + return random_distribution(*this->_generator); +} diff --git a/src/randomization.hpp b/src/randomization.hpp new file mode 100644 index 0000000..b4931d7 --- /dev/null +++ b/src/randomization.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +/** + * Pseudo-random unsigned integer generator. + */ +class RandomNumberGenerator +{ +public: + /** + * Creates a pseudo-random number generator. + * + * @param seed A number generation seed + */ + explicit RandomNumberGenerator(const unsigned int &seed); + + /** + * Creates a pesudo-random number generator. + */ + RandomNumberGenerator(); + + /** + * Generates a number in the range of a to b. + * + * @param a A number lower than b + * @param b A number greater than a + */ + [[nodiscard]] unsigned int in_range(const unsigned int &a, + const unsigned int &b) const; + +private: + std::unique_ptr _generator; +}; -- cgit v1.2.3-18-g5258