2

I want to generate some random colors in wpf and store them in an array.

Random r;
Color[] colarr = new Color[6];
for (int i = 0; i < colarr.Length; i++)
{
   Color c=new Color();
   r=new Random();
   r.Next();
   c.R = (byte)r.Next(1, 255);
   c.G = (byte)r.Next(1, 255);
   c.B = (byte)r.Next(1, 255);
   c.A = (byte)r.Next(1, 255);
   c.B = (byte)r.Next(1, 255);          
   colarr[i] = c;
}

but all the elements of the array represent one single color. When I debugged the code, I found random colors for every element, but when the code is executed(not in debug mode) same color is generated. This makes clear that the code is correct, there is some problem while execution.

EDIT :

How can I increase the randomness of the colors generated?

Tanuj Wadhwa
  • 2,025
  • 9
  • 35
  • 57
  • 1
    [c# - Why Random makes same selection always?](http://stackoverflow.com/questions/15611906/why-random-makes-same-selection-always/15611958#15611958) – Sina Iravanian May 18 '13 at 11:44

3 Answers3

4

The problem is that you are making a new instance of random each run. You should set it once.

The default seed for a Random is the system time, which will be the same if you repeat a very fast loop; the time won't change a lot. If you only set it at the start, the Random will work as expected.

I would also suggest you use r.Next(0, 256), since that will give you any value ranging from 0 to 255.

Also, the call to r.Next() after the definition of Color c is completely unnecessary, since you don't use its value.

Random r = new Random();
Color[] colarr = new Color[6];
for (int i = 0; i < colarr.Length; i++)
{
   Color c=new Color();
   c.R = (byte)r.Next(0, 256);
   c.G = (byte)r.Next(0, 256);
   c.B = (byte)r.Next(0, 256);
   c.A = (byte)r.Next(0, 256);
   //c.B = (byte)r.Next(1, 255);  This line isn't needed btw        
   colarr[i] = c;
}
antonijn
  • 5,702
  • 2
  • 26
  • 33
  • thanks it solved the problem. But I have more issues now. This also generates same or almost same colors for two or more indexes. Is there anything predefined for generating some different colors or I will have to keep a check after generating each color? – Tanuj Wadhwa May 18 '13 at 11:46
  • @TanujWadhwa "almost same" is not subjective. I won't be able to help without concrete data. – antonijn May 18 '13 at 13:15
  • the difference in between two colors should be identifiable. – Tanuj Wadhwa May 18 '13 at 13:26
  • @TanujWadhwa Define identifiable. Again, I need concrete data. – antonijn May 18 '13 at 13:32
  • 1
    @TanujWadhwa: This is a question and answer site, so use it like one. Start a new question: How can I generate random colours that are subjectively distinct? – Eric Lippert May 18 '13 at 14:42
3

Try like this;

Random r = new Random();
Color[] colarr = new Color[6];
for (int i = 0; i < colarr.Length; i++)
{
   Color c=new Color();
   c.R = (byte)r.Next(0, 256);
   c.G = (byte)r.Next(0, 256);
   c.B = (byte)r.Next(0, 256);
   c.A = (byte)r.Next(0, 256);
   c.B = (byte)r.Next(0, 256);          
   colarr[i] = c;
}

From Marc's answer;

Every time you do new Random() it is initialized using the clock. This means that in a tight loop you get the same value lots of times. You should keep a single Random instance and keep using Next on the same instance.

Read: Random number generator only generating one random number

Community
  • 1
  • 1
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
2

If you want a different approach to selecting random colours, you could use reflection. You'd have to compare performance depending on how often it's called but it might return less similar results. Note the rnd value is not stored within the function otherwise you'll have the same problem as you had in your original question of the same value being returned when the method is called in quick succession (such as from a for loop).

Random rnd = new Random();

private Color GetRandomColour()
{
    var colorProperties = typeof(Colors).GetProperties(BindingFlags.Static | BindingFlags.Public);
    var colors = colorProperties.Select(prop => (Color)prop.GetValue(null, null));

    int index = rnd.Next(colors.Count());

    return colors.ElementAt(index);
}

You can use it like this

for (int i = 0; i < colarr.Length; i++)
{          
   colarr[i] = GetRandomColour();
}
keyboardP
  • 68,824
  • 13
  • 156
  • 205