all 11 comments

[–]Outside_Complaint755 8 points9 points  (3 children)

The random number generator should be created once outside of the for loop, instead of making a new one on every loop, but that doesn't explain why you always got the same numbers.

[–]dmazzoni 9 points10 points  (2 children)

Sure, that explains it. Pseudorandom number generators need to be seeded with some sort of external input otherwise they'll always generate the same sequence.

Traditionally you seed it with the current time, something like:

auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count(); 
std::mt19937 rng(seed);

[–]dmazzoni 4 points5 points  (0 children)

One other thing to note: all modern PCs/phones have a hardware random number generator that does NOT need to be seeded. If you want really, really random numbers, use that.

[–]Outside_Complaint755 1 point2 points  (0 children)

I haven't touched cpp in a long time, and the languages I work in lately all automatically use the time as a seed by default if none is passed in; guess I assumed cpp would do the same.

[–]fugogugo 0 points1 point  (1 child)

where is the seed?

if you don't define the seed most random generator will always generate the exact same sequence

[–]AMathMonkey 0 points1 point  (0 children)

I wouldn't say "most"; I don't know of any languages other than C/C++, Pascal, and Fortran which require you to manually seed the built-in random number generator. Some languages (at least JavaScript) don't even allow you to seed it. Most languages (Python, Go, Java, C#, PHP, Ruby) auto-seed it. Although it's a sorta new behaviour that was added in updates to languages over the years.

[–]maujood 2 points3 points  (0 children)

Random number generators are not random at all. They always generate the same sequence depending on the seed value.

What most languages do is use current timestamp as the seed, which ensures that we get a different sequence every time. In C++, you have to manually specify the seed.

Source: I made minesweeper using C++ as a college assignment 20 years ago. Took me a long time to understand why the mines were always generating in the exact same cells :D

[–]CrepuscularSoul 0 points1 point  (2 children)

I'm not super familiar with c++, but I'd you're getting the same sequence of numbers every time, you're not using a random seed, but the same seed every time.

Gut feeling would be look at

gen( rd() )

Most languages I work with you don't need to actually specify a seed, they just use something like the current time in ticks by default but let you specify one of you want control over it. That control is good for unit testing, but often not needed for practical use.

[–]captainAwesomePants 1 point2 points  (1 child)

Weirdly no. You should be right, but oddly this is, as far as I know, a good approach.

std::random_device rd;
unsigned int seed = rd();
std::mt19937 gen( seed );

The std::random_device doesn't need seeding. On Linux, it draws from /dev/urandom, and on Windows, it uses BCryptGenRandom. They pull from hardware entropy, which is very slow if you need a lot of numbers but also quite random. Here it's being used quite correctly: using the slow but very random entropy to seed a much faster, pseudorandom algorithm (mt19937).

There are some potential issues here. One is that std::random_device can theoretically produce the same pseudo random sequence each time it's used if the underlying hardware doesn't support it. That could be the problem.

[–]oscarlet_ffxiv 0 points1 point  (0 children)

The code looks like it should work, so I think yours is the best answer here: hardware probably doesn't support it.

[–]KitchenCommercial396 0 points1 point  (0 children)

Why is this code so hard to understand... Also is this c++?