aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt5
-rw-r--r--src/conversion.cpp41
-rw-r--r--src/conversion.hpp13
-rw-r--r--src/game/options.hpp10
-rw-r--r--src/game_of_life.cpp108
-rw-r--r--src/randomization.cpp21
-rw-r--r--src/randomization.hpp35
7 files changed, 232 insertions, 1 deletions
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 <climits>
+#include <stdexcept>
+
+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<unsigned int>(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 <string_view>
+
+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 <memory>
+
+struct GameOptions
+{
+ std::shared_ptr<RandomNumberGenerator> 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 <getopt.h>
+#include <iostream>
+#include <memory>
+#include <string_view>
+#include <vector>
+
+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<option, 8> 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<std::string_view>(argv, argv + argc);
+
+ GameOptions game_options;
+
+ char arg = 0;
+ while ((arg = static_cast<char>(
+ 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<RandomNumberGenerator>(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<RandomNumberGenerator>();
+ }
+
+ // 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<std::mt19937>(seed);
+}
+
+RandomNumberGenerator::RandomNumberGenerator()
+{
+ std::random_device random_device;
+
+ this->_generator = std::make_unique<std::mt19937>(random_device());
+}
+
+unsigned int RandomNumberGenerator::in_range(const unsigned int &a,
+ const unsigned int &b) const
+{
+ auto random_distribution = std::uniform_int_distribution<unsigned int>(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 <memory>
+#include <random>
+
+/**
+ * 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<std::mt19937> _generator;
+};