diff options
author | HampusM <hampus@hampusmat.com> | 2022-02-13 20:54:02 +0100 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2022-02-13 20:54:02 +0100 |
commit | 176d6141c87a180b251bacaee656808bad17498b (patch) | |
tree | 9d3893014eeb8be293cf8928044925c379739d24 /src | |
parent | b0c265ee3d94921f55266a679d3801a4d2b4505b (diff) |
refactor: add random number generation abstraction
Diffstat (limited to 'src')
-rw-r--r-- | src/maze.hpp | 5 | ||||
-rw-r--r-- | src/maze.tpp | 30 | ||||
-rw-r--r-- | src/mazerator.cpp | 37 | ||||
-rw-r--r-- | src/random_generator.cpp | 20 | ||||
-rw-r--r-- | src/random_generator.hpp | 34 |
5 files changed, 99 insertions, 27 deletions
diff --git a/src/maze.hpp b/src/maze.hpp index e525d70..650e60a 100644 --- a/src/maze.hpp +++ b/src/maze.hpp @@ -2,8 +2,8 @@ #include "engine/matrix.hpp" #include "engine/vector2.hpp" +#include "random_generator.hpp" #include <memory> -#include <random> #include <string> /** @@ -16,6 +16,7 @@ */ template <typename Element> void matrix_to_maze(Matrix<Element> *matrix, std::shared_ptr<Vector2> start_pos, - Element space_element, std::mt19937 random_gen); + Element space_element, + std::shared_ptr<RandomNumberGenerator> random_gen); #include "maze.tpp" diff --git a/src/maze.tpp b/src/maze.tpp index 19390cc..2edb60d 100644 --- a/src/maze.tpp +++ b/src/maze.tpp @@ -22,7 +22,9 @@ std::vector<std::shared_ptr<Vector2>> get_neighbours(Matrix<Element> *matrix, auto pos_down = (*pos - Vector2(0U, 2U)).copy(); if (matrix->get(*pos_down) != space_element) + { neighbours.push_back(pos_down); + } } if (pos->y() != matrix->rows() - 2U) @@ -30,7 +32,9 @@ std::vector<std::shared_ptr<Vector2>> get_neighbours(Matrix<Element> *matrix, auto pos_up = (*pos + Vector2(0U, 2U)).copy(); if (matrix->get(*pos_up) != space_element) + { neighbours.push_back(pos_up); + } } if (pos->x() != 1U) @@ -38,7 +42,9 @@ std::vector<std::shared_ptr<Vector2>> get_neighbours(Matrix<Element> *matrix, auto pos_left = (*pos - Vector2(2U, 0U)).copy(); if (matrix->get(*pos_left) != space_element) + { neighbours.push_back(pos_left); + } } if (pos->x() != matrix->columns() - 2U) @@ -46,7 +52,9 @@ std::vector<std::shared_ptr<Vector2>> get_neighbours(Matrix<Element> *matrix, auto pos_right = (*pos + Vector2(2U, 0U)).copy(); if (matrix->get(*pos_right) != space_element) + { neighbours.push_back(pos_right); + } } return neighbours; @@ -75,14 +83,19 @@ void pos_to_between(std::shared_ptr<Vector2> between_pos, unsigned int coord, unsigned int away_coord, Vector2 diff) { if (away_coord > coord) + { *between_pos += diff; + } else + { *between_pos -= diff; + } } template <typename Element> void matrix_to_maze(Matrix<Element> *matrix, std::shared_ptr<Vector2> start_pos, - Element space_element, std::mt19937 random_gen) + Element space_element, + std::shared_ptr<RandomNumberGenerator> random_gen) { Stack<std::shared_ptr<Vector2>> path_stack(get_maze_size(matrix)); @@ -95,13 +108,14 @@ void matrix_to_maze(Matrix<Element> *matrix, std::shared_ptr<Vector2> start_pos, matrix->set(*pos, space_element); - std::vector<std::shared_ptr<Vector2>> neighbours = - get_neighbours(matrix, pos, space_element); + auto neighbours = get_neighbours(matrix, pos, space_element); if (neighbours.empty()) { if (visited_pos_cnt == get_maze_size(matrix) - 1U) + { break; + } // Go back a step path_stack.pop(); @@ -110,18 +124,20 @@ void matrix_to_maze(Matrix<Element> *matrix, std::shared_ptr<Vector2> start_pos, visited_pos_cnt++; - auto random_dist = std::uniform_int_distribution<unsigned int>( - 0U, static_cast<unsigned int>(neighbours.size()) - 1U); - - auto next_pos = neighbours[random_dist(random_gen)]; + auto next_pos = neighbours[random_gen->in_range( + 0U, static_cast<unsigned int>(neighbours.size()) - 1U)]; auto between_pos = pos->copy(); if (next_pos->y() != pos->y()) + { pos_to_between(between_pos, pos->y(), next_pos->y(), Vector2(0U, 1U)); + } if (next_pos->x() != pos->x()) + { pos_to_between(between_pos, pos->x(), next_pos->x(), Vector2(1U, 0U)); + } matrix->set(*between_pos, space_element); diff --git a/src/mazerator.cpp b/src/mazerator.cpp index 33ef1b1..b30124f 100644 --- a/src/mazerator.cpp +++ b/src/mazerator.cpp @@ -2,10 +2,10 @@ #include "engine/vector2.hpp" #include "getopt.h" #include "maze.hpp" +#include "random_generator.hpp" #include "utils.hpp" #include <iostream> #include <memory> -#include <random> #include <string> void optarg_error(int arg, std::string error) @@ -19,11 +19,15 @@ void validate_start_coords(unsigned int start_x, unsigned int start_y, unsigned unsigned int height) { if (start_x >= width) + { throw "The x start coordinate cannot be higher than or equal to the maze's width"; + } if (start_y >= height) + { throw "The y start coordinate cannot be higher than or equal to the maze's " "height"; + } } /** @@ -40,7 +44,9 @@ void parse_uint_arg(unsigned int *num_dst, int arg, bool check_zero = false) *num_dst = str_to_uint(std::string(optarg)); if (check_zero && *num_dst == 0) + { throw "It should not be 0"; + } } catch (const char *error) { @@ -62,10 +68,10 @@ int main(int argc, char *argv[]) unsigned int maze_width = 40U; unsigned int maze_height = 20U; - std::shared_ptr<unsigned int> start_x = nullptr; - std::shared_ptr<unsigned int> start_y = nullptr; + std::unique_ptr<unsigned int> start_x = nullptr; + std::unique_ptr<unsigned int> start_y = nullptr; - std::unique_ptr<std::mt19937> random_gen = nullptr; + std::shared_ptr<RandomNumberGenerator> random_gen = nullptr; std::string wall = "█"; @@ -81,11 +87,11 @@ int main(int argc, char *argv[]) parse_uint_arg(&maze_height, arg, true); break; case 'x': - start_x = std::make_shared<unsigned int>(); + start_x = std::make_unique<unsigned int>(); parse_uint_arg(start_x.get(), arg); break; case 'y': - start_y = std::make_shared<unsigned int>(); + start_y = std::make_unique<unsigned int>(); parse_uint_arg(start_y.get(), arg); break; case 'W': @@ -95,7 +101,7 @@ int main(int argc, char *argv[]) unsigned int seed; parse_uint_arg(&seed, arg, true); - random_gen = std::make_unique<std::mt19937>(seed); + random_gen = std::make_shared<RandomNumberGenerator>(seed); break; case 0: std::cout @@ -126,24 +132,19 @@ int main(int argc, char *argv[]) if (random_gen == nullptr) { - std::random_device random_device; - random_gen = std::make_unique<std::mt19937>(random_device()); + random_gen = std::make_shared<RandomNumberGenerator>(); } if (start_x == nullptr) { - auto random_dist = - std::uniform_int_distribution<unsigned int>(0, maze_width - 1U); - - start_x = std::make_unique<unsigned int>(random_dist(*random_gen)); + start_x = + std::make_unique<unsigned int>(random_gen->in_range(0, maze_width - 1U)); } if (start_y == nullptr) { - auto random_dist = - std::uniform_int_distribution<unsigned int>(0, maze_height - 1U); - - start_y = std::make_unique<unsigned int>(random_dist(*random_gen)); + start_y = + std::make_unique<unsigned int>(random_gen->in_range(0, maze_height - 1U)); } try @@ -162,7 +163,7 @@ int main(int argc, char *argv[]) auto start_pos = std::make_shared<Vector2>(*start_x * 2U + 1U, *start_y * 2U + 1U); - matrix_to_maze<std::string>(&matrix, start_pos, " ", *random_gen); + matrix_to_maze<std::string>(&matrix, start_pos, " ", random_gen); matrix.print(); } diff --git a/src/random_generator.cpp b/src/random_generator.cpp new file mode 100644 index 0000000..1f17a88 --- /dev/null +++ b/src/random_generator.cpp @@ -0,0 +1,20 @@ +#include "random_generator.hpp" + +RandomNumberGenerator::RandomNumberGenerator(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(unsigned int a, unsigned int b) +{ + auto random_distribution = std::uniform_int_distribution<unsigned int>(a, b); + + return random_distribution(*this->_generator); +} diff --git a/src/random_generator.hpp b/src/random_generator.hpp new file mode 100644 index 0000000..a4c1331 --- /dev/null +++ b/src/random_generator.hpp @@ -0,0 +1,34 @@ +#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 + */ + RandomNumberGenerator(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 + */ + unsigned int in_range(unsigned int a, unsigned int b); + +private: + std::unique_ptr<std::mt19937> _generator; +}; |