0

after reading some C# tutorials I decided to make a minigame of Heads/Tails. It generates a random number, 0 or 1, and writes out the result. Using a loop I repeat this a thousand times. The problem is that it would only write "heads" or "tails" depending on whether 0 or 1 gets generated more. For example if there are 535 "0s" and 465 "1s" it would only write down "Heads". Here is my code:

//variables
int count = 0;
int tails = 0;
int heads = 0;

while(count < 1000)
{
    Random rnd = new Random();
    int result = rnd.Next(0,2);
    if(result == 1)
    {
        Console.WriteLine("Tails!");
        tails = tails + 1;
        count = count + 1;

    }
    else if(result == 0)
    {
        Console.WriteLine("Heads!");
        heads = heads + 1;
        count = count + 1;
    }
}
Console.WriteLine("Heads = " + heads + "Tails = " + tails + " Counts = " + count);
Console.ReadLine();
rory.ap
  • 34,009
  • 10
  • 83
  • 174
Zlatev
  • 49
  • 1
  • 3
  • Don't create a new Random() inside your loop. Create it once at the start of the method, and call rnd.Next() inside the while loop. – Jon Apr 17 '15 at 14:59
  • Yet an other duplicate of [Random.Next returns always the same values](http://stackoverflow.com/questions/1654887/random-next-returns-always-the-same-values) – Pierre-Luc Pineault Apr 17 '15 at 15:01
  • possible duplicate of [Random number generator only generating one random number](http://stackoverflow.com/questions/767999/random-number-generator-only-generating-one-random-number) – Matthew Frontino Apr 17 '15 at 15:01
  • 1
    Why the downvotes? This is a real question, and is certainly on topic.... – Cullub Apr 17 '15 at 15:06
  • 2
    @cullub There's probably over 20 duplicates, on this site alone. Sounds pretty much like 'does not show any research effort' to me. – Pierre-Luc Pineault Apr 17 '15 at 15:10
  • @cullub -- yes, I agree. I didn't DV but it's definitely (well, probably) due to lack of research effort. – rory.ap Apr 17 '15 at 15:13
  • 1
    That's true. However, the nature of the question seems to point out that he was on the wrong trail - he thought it had to do with how many of each. – Cullub Apr 17 '15 at 15:14
  • @cullub -- Good point. +1 – rory.ap Apr 17 '15 at 15:15
  • Don't forget about the height of your console buffer... Just because you can only see that last few (hundred?) entries doesn't mean they all came out like that – James Apr 17 '15 at 15:19

2 Answers2

4

Try moving Random rnd = new Random(); outside of the while loop:

Random rnd = new Random();

while (count < 1000)
//...

The problem is that there are no true random numbers in computers; they all work off of a list of previously-generated random numbers. Since you are instantiating Random every loop, you're essentially picking the same start seed every time. By using just one instance of Random, created outside of the loop, then your application will truly behave as if the numbers are being generated randomly.

EDIT: To echo what Solal Pirelli said in the comments, the instance of Random is actually being seeded using the current computer system's time (if you don't give it any seed value in the constructor); however, since the loop iterations are happening so quickly, each instance created for each loop iteration has the same seed.

EDIT #2: As CalebB pointed out, it's also a good practice to provide your own seed to your Random instance via its other constructor. I would suggest using the hash value from a GUID:

Random rnd = new Random(Guid.NewGuid().GetHashCode());

This essentially guarantees that each of your instances of Random will always be seeded differently, even if you create new instances in quick succession. I say essientially because, while statistically very VERY low in probability, there is some chance that two GUID values could be the same.

rory.ap
  • 34,009
  • 10
  • 83
  • 174
  • 1
    To be more precise, `Random` is seeded with the current system time by default. Since iterations of a simple loop are very fast, all `Random` instances in that loop will have the same seed. – Solal Pirelli Apr 17 '15 at 15:02
  • In addition to that adding a seed to the Random instance wouldn't hurt: `Random rnd = new Random("Integer Seed for random number generation");` possibly basing it off the day of year against the time of day or whatever dynamic value. – CalebB Apr 17 '15 at 15:05
0

Fixed! :

using System;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        public static void Main(string[] args)
        {
            Random rand = new Random();
            Console.WriteLine(String.Join("\n",Enumerable.Repeat(0, 1000).Select(i => rand.Next(0,2) == 1 ? "Tails" : "Heads").GroupBy(i=>i).Select(g=> g.Key + " " + g.Count())));
            Console.ReadLine();
        }
    }
}
Ewan
  • 1,261
  • 1
  • 14
  • 25