Winterpixel
3/1/2019 - 12:09 AM

Random Number Generator

#pragma once

#include <random>
#include <iostream>
#include <stdexcept>
#include <cstdint>

class RNG
{
public:
	/* Constructor for RNG class.
	 * 
	 * @param Amount of numbers to generate
	 * @param Minimum number in range to generate
	 * @param Maximum number in range to generate
	 *
	 * The constructor also instanstiates the variable m_generator
	 * with a new random_device.
	 */
	RNG(const uint64_t &amount, const uint64_t &min, const uint64_t &max)
		: m_generator((std::random_device())())
		, m_floor(min)
		, m_numLeft(amount)
		, m_lastInt(min)
		, m_ceiling(max)
	{
	}

	// Return a bool to determine if there are any numbers left to generate
	const bool HasNext()
	{
		return m_numLeft > 0;
	}

	// Generate the next random number
	const uint64_t NextInt()
	{
		if (m_numLeft > 0)
		{
			// Partition the range of numbers to generate from
			uint64_t rangeSize = (m_ceiling - m_lastInt) / m_numLeft;

			// Initialize random generator
			std::uniform_int_distribution<uint64_t> rg(m_floor, rangeSize);

			// Generate random number
			uint64_t randomNumber = rg(m_generator) + m_lastInt + 1;

			// Set m_lastInt to randomNumber so that randomNumber is not generated again
			m_lastInt = randomNumber;
			m_numLeft--;
			return randomNumber;
		}
		else
		{
			throw std::out_of_range("Exceeded amount of random numbers to generate.");
		}
	}
private:
	uint64_t m_floor;
	uint64_t m_ceiling;
	uint64_t m_lastInt;
	uint64_t m_numLeft;
	std::mt19937_64 m_generator;
};