Your problem is that you create a new object of the class Random
every time you enter the function. First of all, this is wasteful: The garbage collector at some point must destroy all the lost instances of Random
which will slow down your game. Try to avoid creating new objects and re-use existing ones as much as possible.
In this particular case, this is also the underlying reason that you get the same "random" number every time: Random
is a misnomer and should have been called PseudoRandom
or the like instead. Subsequent calls of Random.Next()
for the same Random
object yield a pre-determined sequence of numbers which just look as if they were random. There is a large number of sequences to choose from with the constructor's integer argument, when supplied. If you don't supply one, the class uses a timer tick, and that's the catch. Quoting from the Microsoft documentation (hint ;-) ):
However, on the .NET Framework only, because the clock has finite resolution, using the parameterless constructor to create different Random objects in close succession creates random number generators that produce identical sequences of random numbers.
"Finite resolution" means that if the time between calls to the function is smaller than the timer interval, the timer value used to choose the specific number sequence can be the same for two or more calls. This is probably the case here. Your Next()
call always returns only the first number of the pre-determined sequence this specific new Random
object produces; two Random
objects producing the same sequence will return the same number when Next()
is called on them for the first time.
The "proper" way to use Random
would be to use the same object every time. For example, create a Random
object before your loop and supply it to the function in each iteration. Then Next()
indeed will return the "next" number in the pre-determined, random-looking sequence chosen by the (more or less unpredictable) timer value at the time of the instantiation of the one Random
object. A bit further down in the mentioned article Microsoft recommends exactly that:
On the .NET Framework, initializing two random number generators in a tight loop or in rapid succession creates two random number generators that can produce identical sequences of random numbers. In most cases, this is not the developer's intent and can lead to performance issues, because instantiating and initializing a random number generator is a relatively expensive process.
Both to improve performance and to avoid inadvertently creating separate random number generators that generate identical numeric sequences, we recommend that you create one Random object to generate many random numbers over time, instead of creating new Random objects to generate one random number.
Addendum:
When I asked ChatGPT about your program it spotted an error that I didn't know about: The second parameter to the Next()
call, even though it is called maxValue
, is the exclusive upper bound. That is, Next(1,5)
will produce 1, 2, 3 or 4, but never 5.
As an aside, when I then told ChatGPT that I always get the same "random" number, ChatGPT spotted the "same sequence" problem correctly as well.