Reputation: 1
I can't seem to figure out exactly how to generate a non-repeating random number in an array. I have tried using a do loop if the value was already in the array, it should reassign a new random number in that position until the number wasn't in the array anymore, and it works until about the third or fourth run-through. Here's what I have right now:
Module Lab4_Lottery
Sub Main()
Dim wins(9) As Integer
For m = 0 To 9
wins(m) = -1 ' Initialized to -1 to distinguish elements that have not been given lottery numbers yet
Next m
Dim numsSoFar As Integer = 0 ' Counter variable
Dim temp As Integer = 0 ' Random number holder
Dim r As New Random
Dim userInput As Integer
While numsSoFar < 10
Dim flag As Boolean = False
temp = r.Next(100)
If wins(numsSoFar) = temp Then
flag = True
Do ' Here, the do loop should've generated a random number
temp = r.Next(100) ' that wasn't already in the array
wins(numsSoFar) = temp
Loop Until temp <> wins(numsSoFar)
End If
If flag = False Then
wins(numsSoFar) = temp
End If
Console.Write(temp & " ") ' Testing purposes to see if numbers are being repeated
numsSoFar += 1
flag = False
End While
Console.WriteLine("Please enter your lottery number")
userInput = Console.ReadLine()
Dim blnFound As Boolean = False
numsSoFar = 0
Do While Not blnFound And numsSoFar < wins.Length
If userInput = wins(numsSoFar) Then
blnFound = True
End If
numsSoFar += 1
Loop
If blnFound Then
Console.WriteLine("Congratulations! You won the lottery!")
Else
Console.WriteLine("Sorry, you lose. Better luck next time!")
End If
For i As Integer = 0 To 9
Console.Write(wins(i) & " ")
Next i
End Sub
End Module
Upvotes: 0
Views: 3635
Reputation: 38875
It sounds like you want 10 numbers from a pool of 100 with no repeats. That involves a Shuffle. Here is an easy way to do that:
' an array of all possible values 1-100
Dim Lotto As Int32() = Enumerable.Range(1, 100).ToArray()
' shuffle the array to a random order
Shuffle(Lotto)
' pick 10 winning numbers for this drawing:
Dim winners = Lotto.Take(10).ToArray()
For the next drawing, just re-shuffle and take 10 again. The shuffler is simple:
' class level random object
Private myRand As New Random()
' std Fisher-Yates shuffle
Private Sub Shuffle(arry() As Integer)
Dim tmp As Integer
Dim j As Integer
For n As Integer = arry.Length - 1 To 0 Step -1
j = myRand.Next(0, n + 1)
tmp = arry(j)
' swap item(j) and item(n)
arry(j) = arry(n)
arry(n) = tmp
Next
End Sub
The standard Fisher-Yates shuffle is something every programmer should at least know about. It is extremely efficient and fast. As an alternative, in many cases, this produces a good-enough-shuffle:
Lotto = Lotto.OrderBy(Function(r) myRand.Next).ToArray()
You can also glue them together for one step:
Dim winners = Enumerable.Range(0, 100).
OrderBy(Function(r) myRand.Next).
Take(10).ToArray()
Contrary to the advice in another answer, it is a very bad idea to create a new Random
object each time, especially in a loop - that is a good way to ensure that you get a repeat. Nor do you ever need to provide a seed.
Upvotes: 1
Reputation: 3356
You have to create a new instance of random using a new seed just like the following example
For index = 1 To 1000
Dim r = New Random(Guid.NewGuid().GetHashCode())
Dim randomNumber = r.Next(100)
Console.WriteLine(randomNumber)
Next
Console.ReadKey()
Upvotes: 0
Reputation: 1093
Do ' Here, the do loop should've generated a random number
temp = r.Next(100) ' that wasn't already in the array
wins(numsSoFar) = temp
Loop Until temp <> wins(numsSoFar)
This loop is only checking the last number in the array for a match. Even though this loop is nested within another that iterates through every number in the array, this isn't sufficient to check every number for a repeat. As written, it will only prevent consecutive numbers from matching. To fix it, I would change the last line to:
Loop Until Array.IndexOf(wins, temp) > -1
Upvotes: 0