2

I need to get some random colors to draw a pie. My code works but it can take the same color again and again

    Random r = new Random();

    for (int i = 0; i < 20; i++)
    {
        int min = 0;
        int max = 255;
        int rand1 = r.Next(min, max);
        int rand2 = r.Next(min, max);
        int rand3 = r.Next(min, max);
        Color myColor = Color.FromArgb(rand1, rand2, rand3);  
        //drawing the pie here
   }

How can I rework it so that it's not going to pick the same color again.

zoul
  • 102,279
  • 44
  • 260
  • 354
Rene
  • 27
  • 1
  • 3
  • 6

3 Answers3

3

It’s usually a better idea to create some nice palette beforehand and then pick the colors from the palette. In pseudocode:

var Palette = new Array(Color(r1, g1, b1), Color(r2, g2, b2), …);
for (var i=0; i<numberOfPieSegments; i++)
    drawPieSegment(Palette[i % Palette.length], …);
zoul
  • 102,279
  • 44
  • 260
  • 354
  • This is a good solution, but some times the amount of colors if big and manually create it require times that a random generator spare us – Elvis Jr May 11 '19 at 21:53
2

You could put the random colors you generate in a container, then check if a similar color by a certain delta has already been inserted in the container.

This way you won't risk to pick up a different color but very similar, like: RGB(0, 0, 0) and RGB(10, 2, 3)

const int DELTA_PERCENT = 10;
List<Color> alreadyChoosenColors = new List<Color>();

// initialize the random generator
Random r = new Random();

for (int i = 0; i < 20; i++)
{
    bool chooseAnotherColor = true;      
    while ( chooseAnotherColor )
    {
       // create a random color by generating three random channels
       //
       int redColor = r.Next(0, 255);
       int greenColor = r.Next(0, 255);
       int blueColor = r.Next(0, 255);
       Color tmpColor = Color.FromArgb(redColor, greenColor, blueColor);  

       // check if a similar color has already been created
       //
       chooseAnotherColor = false;
       foreach (Color c in alreadyChoosenColors)
       {
          int delta = c.R * DELTA_PERCENT / 100;
          if ( c.R-delta <= tmpColor.R && tmpColor.R <= c.R+delta )
          {
             chooseAnotherColor = true;
             break;
          }

          delta = c.G * DELTA_PERCENT / 100;
          if ( c.G-delta <= tmpColor.G && tmpColor.G <= c.G+delta )
          {
             chooseAnotherColor = true;
             break;
          }

          delta = c.B * DELTA_PERCENT / 100;
          if ( c.B-delta <= tmpColor.B && tmpColor.B <= c.B+delta )
          {
             chooseAnotherColor = true;
             break;
          }
        }
    }

    alreadyChoosenColors.Add(tmpColor);
    // you can safely use the tmpColor here

   }
vulkanino
  • 9,074
  • 7
  • 44
  • 71
-2

see msdn for descripton of Random class, check this: However, 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.
For this reason, you should use a different seed to initialize Random instance each time. I recommend the timestamp.

hago
  • 1,700
  • 2
  • 16
  • 18
  • This is not what's happening here. The OP's constructing only one instance of `Random` and using it. OP's probably picking similar colors (looking equal even if the numbers are different). – vulkanino Mar 05 '12 at 09:58