Jordan Velez
Jordan Velez

Reputation: 1

Non-Repeating Random Number Generator in VB Problems

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

Answers (3)

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

Nikos Tsokos
Nikos Tsokos

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

Josh
Josh

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

Related Questions