From 3e8bb08b1b5cef4b94df474594ea78e46dbe731d Mon Sep 17 00:00:00 2001 From: Joseph Aquino Date: Sun, 5 Apr 2026 00:48:28 -0400 Subject: [PATCH] added Random.h --- include/Random.h | 74 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 include/Random.h diff --git a/include/Random.h b/include/Random.h new file mode 100644 index 0000000..28c2beb --- /dev/null +++ b/include/Random.h @@ -0,0 +1,74 @@ +#pragma once + +#ifndef RANDOM_MT_H +#define RANDOM_MT_H + +#include +#include + +// This header-only Random namespace implements a self-seeding Mersenne Twister. +// Requires C++17 or newer. +// It can be #included into as many code files as needed (The inline keyword avoids ODR violations) +// Freely redistributable, courtesy of learncpp.com (https://www.learncpp.com/cpp-tutorial/global-random-numbers-random-h/) +namespace Random +{ + // Returns a seeded Mersenne Twister + // Note: we'd prefer to return a std::seed_seq (to initialize a std::mt19937), but std::seed can't be copied, so it can't be returned by value. + // Instead, we'll create a std::mt19937, seed it, and then return the std::mt19937 (which can be copied). + inline std::mt19937 generate() + { + std::random_device rd{}; + + // Create seed_seq with clock and 7 random numbers from std::random_device + std::seed_seq ss{ + static_cast(std::chrono::steady_clock::now().time_since_epoch().count()), + rd(), rd(), rd(), rd(), rd(), rd(), rd() }; + + return std::mt19937{ ss }; + } + + // Here's our global std::mt19937 object. + // The inline keyword means we only have one global instance for our whole program. + inline std::mt19937 mt{ generate() }; // generates a seeded std::mt19937 and copies it into our global object + + // Generate a random int between [min, max] (inclusive) + // * also handles cases where the two arguments have different types but can be converted to int + inline int get(int min, int max) + { + return std::uniform_int_distribution{min, max}(mt); + } + + // The following function templates can be used to generate random numbers in other cases + + // See https://www.learncpp.com/cpp-tutorial/function-template-instantiation/ + // You can ignore these if you don't understand them + + // Generate a random value between [min, max] (inclusive) + // * min and max must have the same type + // * return value has same type as min and max + // * Supported types: + // * short, int, long, long long + // * unsigned short, unsigned int, unsigned long, or unsigned long long + // Sample call: Random::get(1L, 6L); // returns long + // Sample call: Random::get(1u, 6u); // returns unsigned int + template + T get(T min, T max) + { + return std::uniform_int_distribution{min, max}(mt); + } + + // Generate a random value between [min, max] (inclusive) + // * min and max can have different types + // * return type must be explicitly specified as a template argument + // * min and max will be converted to the return type + // Sample call: Random::get(0, 6); // returns std::size_t + // Sample call: Random::get(0, 6u); // returns std::size_t + // Sample call: Random::get(0, 6u); // returns int + template + R get(S min, T max) + { + return get(static_cast(min), static_cast(max)); + } +} + +#endif \ No newline at end of file