-1

I am making a simple game in C# and using Random class to generate a random number every 2 seconds, but it gives numbers that I can guess in advance because it increments by a certain number each time.

private int RandomNumber;

//This Timer function runs every 2 seconds
private void TmrGenerateRandomNum(object sender, EventArgs e)
{
    Random r = new Random();
    RandomNumber = r.Next(50, 200); //Trying to get random values between 50 and 200
    Label1.Text = RandomNumber.ToString();
}

This is literally the only code I have, and I am displaying the value each time through Label1. The problem is, for example, if I first get 52, the next "randomly"-generated value is 71 or 72, and the next one is 91 or 92, and the next one is 111 or 112. As you can see, it is incrementing by 20ish. Then it suddenly gets a real random value again like, say, 163. But then the next generated number is 183, again incremented by 20. Since 183+20 exceeds the range, it gets a real random value again, say 83. But the next number generated is again 103, or 104, and then 123 or 124...

This is not "Random" because you can tell around what number the next one is going to be... and this is driving me crazy. Do you know why it does this, and is there a fix for this?

Erik Philips
  • 53,428
  • 11
  • 128
  • 150
Mika Jones
  • 287
  • 1
  • 5
  • 13
  • 1
    Move `Random r = new Random();` outside that method. – LarsTech Dec 22 '17 at 22:04
  • 1
    You need to make your `Random r` static, or at least more global, not local, because you'r creating it with same seed each time.. – sTrenat Dec 22 '17 at 22:04
  • that makes sense... I just moved `Random r = new Random()` outside and it is giving me really-random values each time. I was thinking, if you move this line outside and make it global, `r` will get assigned a random number only once when the form is created, and it won't change again unless you assign a new value in a function. Just like initializing it. Why does it get a random value each time still? – Mika Jones Dec 22 '17 at 22:09
  • 1
    @MikaJones `Random` is not random number, but random number **generator**. You only need one generator to (pseudo-)random sequence. You do not need separate generator for each (pseudo-)random number. – user4003407 Dec 22 '17 at 22:16
  • Thank you everyone! I got it fixed and I now see why it was happening! – Mika Jones Dec 22 '17 at 22:18
  • 1
    Possible duplicate of [Random number generator only generating one random number](https://stackoverflow.com/questions/767999/random-number-generator-only-generating-one-random-number) – Ňɏssa Pøngjǣrdenlarp Dec 22 '17 at 22:34
  • 1
    Your code/comment is wrong as well. `r.Next(50, 200)` will generate a value between 50 and 199 inclusive – Ňɏssa Pøngjǣrdenlarp Dec 22 '17 at 22:35

4 Answers4

0

While true random numbers are relatively difficult to generate, you should be able to get much better results than you are. The problem you're likely having right now, as suggested by comments, is that you should not be "starting over" every time the function is called. As a test, you can try passing some value like 5 as a parameter to the Random constructor. Then you will notice your results are really not random. To fix this, as the comments suggest, you should move the construction of the Random object somewhere global so that the randomness can "build" on itself over time instead of always being reset. Once you confirm that you can get different values with repeated calls, then remove the parameter to the Random constructor so that you don't get the same sequence of random numbers every time you restart your program.

BlueMonkMN
  • 25,079
  • 9
  • 80
  • 146
0

More of an in-depth explanation: Basically, it's pretty much impossible to generate truly random values in a computer, all of the random values you get are pseudo random and are based off of values like:

  1. User input, like how many keys were pressed in the last 2 minuts
  2. Memory usage, how many KB of memory is being used at this very moment
  3. The most common one: Using the current time in mili seconds to generate a "seed" that's used to generate a series of numbers that are mathematical as randomized as possible

This is where the problem comes from. For example, if you were to have the following code

Random r1 = new Random();
Random r2 = new Random();

Console.WriteLine(r1.next())
Console.WriteLine(r2.next())

Miraculously, you will always get the same number from r1 and r2 despite them being two separate instances. It's because the code block is execute in a time window of <1 ms, which gives these two random number generators the same seed, thus they will generate the same list of numbers.

In your case, the number generator is instantiated every 2 seconds, thus they get an incrementing seed. It's hard to say if that will result in an incrementing starting number, but it might be a start.

So instead, try initializing a single Random() and always call the .next() function on it, and you should be getting a much more random list of numbers

Yifei Xu
  • 777
  • 1
  • 6
  • 14
0

Random numbers use a seedvalue to start the sequence. If you give nothing, it takes to current datetime.now value. if you supply the same value (like 3842) you will get the same sequence of random values guaranteed. Your series seemed to be very closely related so you see the same values. All this can be read in the documentation on msdn, see Instantiate pseudo random :

Instantiating the random number generator

You instantiate the random number generator by providing a seed value (a starting value for the pseudo-random number generation algorithm) to a Random class constructor. You can supply the seed value either explicitly or implicitly:

The Random(Int32) constructor uses an explicit seed value that you supply.

The Random() constructor uses the system clock to provide a seed value. This is the most common way of instantiating the random number generator.

If the same seed is used for separate Random objects, they will generate the same series of random numbers. This can be useful for creating a test suite that processes random values, or for replaying games that derive their data from random numbers. However, note that Random objects in processes running under different versions of the .NET Framework may return different series of random numbers even if they're instantiated with identical seed values.

Source: https://msdn.microsoft.com/en-us/library/system.random(v=vs.110).aspx#Instantiate

You find more information and even methods to "better" cryptographical random methods linked above the source I cited.

Community
  • 1
  • 1
Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
0

The best you can do is use a CPRNG or Cryptograph Psudo Random Number Generator, it does not need to be seeded by tyhe user and in generally continnualy updates with system events.

To generate a cryptographically secure random number use the RNGCryptoServiceProvider class or derive a class from System.Security.Cryptography.RandomNumberGenerator.

See MSDN Random Class.

zaph
  • 111,848
  • 21
  • 189
  • 228