One way to handle this would be to shuffle the items in the array, then choose the items sequentially. The Fisher-Yates shuffle is typically regarded as the best algorithm for this:
private static Color[] colors =
{
Color.Red, Color.Blue, Color.Green, Color.Purple, Color.Black, Color.Aqua
};
private static Random random = new Random();
private static void ShuffleColors()
{
for (int index = 0; index < colors.Length; index++)
{
var randomIndex = index + random.Next(colors.Length - index);
var temp = colors[randomIndex];
colors[randomIndex] = colors[index];
colors[index] = temp;
}
}
But what happens when you get to the end of the array? It seems there are 3 possibilities:
- Just start at the beginning again (but then you'll have a non-random pattern)
- Shuffle the array and start at the beginning again
- Shuffle the array but make sure the last color used is not the first item
I think the last one may be preferable, since it will give the most random output, so let's implement that one.
What we can do is keep track of the last index we displayed, and then when it represents the last item in the array, we can shuffle the array again. Then, before we continue, we want to check to make sure the first item in the array isn't the last item we displayed. If it is, then we swap it with some other random element, so we never have a repeating item.
private static int nextIndex = 0;
private static SolidBrush GetNextColoredBrush()
{
// If we've displayed all the items, shuffle the deck
if (nextIndex == colors.Length)
{
var lastColorUsed = colors[nextIndex - 1];
ShuffleColors();
// If the first color is the same as the last color
// we displayed, swap it with a random color
if (colors[0].Name == lastColorUsed.Name)
{
var rndIndex = random.Next(1, colors.Length);
colors[0] = colors[rndIndex];
colors[rndIndex] = lastColorUsed;
}
// Reset our index tracker
nextIndex = 0;
}
// Return the next color and increment our index
return new SolidBrush(colors[nextIndex++]);
}
Now we can call this method in a loop to see what the output will look like:
private static void Main()
{
// Output our random colors. Note that even though we
// only we only have 6 colors, they are consistently
// output in a random order (but with no duplicates).
for (int i = 0; i < 20; i++)
{
Console.WriteLine(GetNextColoredBrush().Color.ToKnownColor());
}
GetKeyFromUser("\nDone! Press any key to exit...");
}
Output
Notice that there are no repeating elements until 6 have been displayed, and then the next six elements are in a different order:

Usage in your code
Oh, finally, to use this in your code, you would just do something like:
p.block.brush_color = GetNextColoredBrush();
However you may notice that I changed the output slightly so that it output a KnownColor
. If you want to maintain your original code, you should modify the line that returns a value in the GetNextColoredBrush
method:
return new SolidBrush(Color.FromArgb(100, colors[nextIndex++]));