diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/conversion.cpp | 41 | ||||
| -rw-r--r-- | src/conversion.hpp | 13 | ||||
| -rw-r--r-- | src/game/options.hpp | 10 | ||||
| -rw-r--r-- | src/game_of_life.cpp | 108 | ||||
| -rw-r--r-- | src/randomization.cpp | 21 | ||||
| -rw-r--r-- | src/randomization.hpp | 35 | 
6 files changed, 228 insertions, 0 deletions
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; +};  | 
