Reputation:
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
Upvotes: 2
Views: 88
Reputation: 19330
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.
Upvotes: 1
Reputation: 415630
You need to shuffle the array, and the best way to do this is the Fisher-Yates algorithm:
If you want to preserver the original, just make a copy first and shuffle the copy.
Upvotes: 1