C++ Random number issue

Started by
5 comments, last by Rutin 6 years, 3 months ago

I'm struggling to get random numbers, in the below code, If I take out the time seed, I get different random numbers each roll, however they are the same on each play through.

If I leave the time seed in, the rolls are always 1 and 1. Please can someone advise what I am doing wrong? I've tried making the game sleep a few seconds to change the results of time time seed call


void dicegame::battle(character *a, character *b)
{
    int rollone = this->roll(); int rolltwo = this->roll(); int total1 = rollone+rolltwo; Sleep(5000);

    int rollone2 = this->roll(); int rolltwo2 = this->roll(); int total2 = rollone2+rolltwo2;  Sleep(5000);
}

int dicegame::roll()
{
    static std::uniform_int_distribution<int> u(1, 6);
    static std::default_random_engine e;
    e.seed(time(0));
    int roll = (u(e));
    return roll;
}

 

 

Advertisement

e.seed(time(0));

Try to comment out this line - it's reinitializing seed.

 
Quote

 

Seed engine

Re-initializes the internal state value:

 

 

and move `e` and `u` init code somewhere else.

I'm guessing what you want is this: 


static std::uniform_int_distribution<int> u(1, 6);
// Seed the engine only *once*
static std::default_random_engine e(time(0));
int roll = (u(e));
return roll;

ie, you want to initialize the engine with a seed **once**. And let it generate random values from there.

Might be wrong syntax for that though, I don't know if std::default_random_engine has a constructor where you can pass it a seed value. Someone with more C++ experience can tell you how to do that properly. EDIT: Nvm, it's fine.

The seed in that case will be the current time of the system. So it should vary enough across playthroughs to be useful.

If you take out the seed, what happens is that the generator gets initialized with a default seed every single time, and these random number generators are deterministic. ie, if you seed it with the same number, they'll produce the same sequence of values. That's pretty useful because it allows you to reproduce them if you keep around the seed that originated them.

"I AM ZE EMPRAH OPENGL 3.3 THE CORE, I DEMAND FROM THEE ZE SHADERZ AND MATRIXEZ"

My journals: dustArtemis ECS framework and Making a Terrain Generator

Thanks TheChubu, that's exactly what I needed

Just to be clear: a pseudorandom number generator (PRNG) is a mathematical operation that generates a series of numbers by applying a function to a state vector, replacing the state vector with new value each time.  The state vector needs to be initialized to something at the start of the sequence (a process called seeding), and if you manually change the state on each iteration you're messing up the sequence and you're going to have problems.

The size of the state vector for the classic std::minstd_rand0 is 32 bits.  The size of the state vector for std::mt19937 is 19968 bits.  The std::default_random_engine is likely one of those two PRNGs (I have not seen a standard library use anything else, but it's possible).  If you seed std::mt19937 with an unsigned int (which is what you would be doing if you use time(0) and your library has implemented std::default_random_engine using std::mt19937), then it actually uses that seed value to initialize a std::minstd_rand0 engine to generate the seed vector.  Fun facts.

I don't recommend using time(0) as a seed.  Use std::random_device instead, at least on desktop systems.

Stephen M. Webb
Professional Free Software Developer

I personally use the following to generate random numbers.

 


#include <iostream>
#include <random>

int main()
{
	std::random_device rd;
	std::mt19937 mt(rd());

	int randomNumber = 0;

	for (int a = 0; a < 10; a++)
	{
		std::uniform_int_distribution<unsigned> u(1, 100);
		randomNumber = u(mt);
		std::cout << randomNumber << std::endl;
	}

	std::cin.get();

	return 0;
}

 

This will run a for loop 10 times, generating a number randomly between 1 and 100.

Avoid using time() like @Bregma stated. Use random_device.

Programmer and 3D Artist

This topic is closed to new replies.

Advertisement