2

I have this array of text (colors)

 Dim ArrayColor As String() = {"Red", "Green", "Yellow", "Blue"}

As from this array, I need a new random array and do not repeat colors. Ej:

Dim ArrayRandomColor As String() = {"Green", "Yellow","Red" "Blue"}

Another EJ:

Dim ArrayRandomColor As String() = {"Yellow", "Blue","Green" "Red"}

I'm working on a mastermind "game" in vb.net 2010 And I'm first assigning the secret code

3
  • Use a random object Private rng As New Random() then randomColors = ArrayColor.OrderBy(Function(r) rng.Next).ToArray() Commented Nov 23, 2015 at 23:43
  • My original answer works but I looked again and pulled my hair. I added a better way of doing it. Please check it out in my answer. Thank you Commented Jan 9, 2016 at 18:38
  • thanks, really there are so many ways, to each his own Commented Jan 11, 2016 at 19:36

2 Answers 2

1

I was actually playing with this method a little bit. Not saying it is most efficient because of GUID... (read comments)

' Consider that each of your colors is assigned specific position in sort order
dim d as new  dictionary(of integer, string) 
d.Add(0,"Green")
d.Add(1,"Red")
d.Add(2,"Blue")
d.Add(3,"Yellow")

' Now we have to create random sort order
Dim colors = Enumerable.Range(0, 4).Select(Function(i) new with {.k = i, .g= Guid.newguid.tostring()}).ToList()
' The line above creates 4 elements with matching keys and unique GUIDs

' since guids are unique and "random", each time when you sort them, your keys will take different positions
' And this will effectively shuffle your colors by dictionary key
for each c in colors.OrderBy(function(x)x.g)    ' sort by guid  
    Console.WriteLine(d(c.k))
next 

Update

I looked at this answer again and I believe it was too much beer that made me write that code. It definitely works but it could be better. First of all, you could write that idea (using GUID) without using Dictionary

Dim colors() As String = {"Red", "Green", "Yellow", "Blue"}
' Logic: convert to object with unique GUID, sort by GUID
colors.Select(Function(c) New With { .color = c, .guid = Guid.NewGuid.ToString() }).
    OrderBy(Function(c) c.guid).ToList().
    ForEach(Sub(item) Console.WriteLine(item.color))

But as I stated earlier, this is not as efficient. So, here is more efficient way.

Usually, if you want to randomize a small number of items, first that comes into mind get them ordered 1,2,3,4... But with this thinking using Random is a problem because r.Next(1, 5) may really gets you 1,1,1,1. Here is the idea that if you run random with large range, twice for each item, and divide numbers along the way, you will get completely random numbers for sure.

colors.Select(Function(c) new with {.color = c, .num = r.Next(1, 1000000) / r.Next(1, 1000000) }).
    OrderBy(Function(c) c.num).ToList().
    ForEach(Sub(item)Console.WriteLine(item.color))

Last method tested to execute twice faster. Enjoy.

Sign up to request clarification or add additional context in comments.

2 Comments

thanks, so I can understand it better, although the method seems attractive shuffle
@Cazs Enjoy. Also, yes - you can use Random but random may not give you 4 distinct values. Random can randomly generate 1,1,1,1 - yes , this is possible
1

You need to shuffle the array, and the best way to do this is the Fisher-Yates algorithm:

Shuffle with Fisher–Yates

If you want to preserver the original, just make a copy first and shuffle the copy.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.