user3289583
user3289583

Reputation: 25

VB.NET Random unique generator

I'l trying to generate a unique random number generator with the snippet of code from below, but it's not working. The IF section is suppose to test if it's the first random number generated, if it is, it's suppose to add the first random number to the ArrayList, if it's not the first random number, it's supposed to check if the random number is already in the ArrayList and if it's in the ArrayList it's suppose to MsgBox and generate a new unique random number that is not already in the ArrayList and add it to the ArrayList, but it's not doing any of those. Any help would be greatly appreciated.

Public Class Form1
    Dim r As New Random
    Dim dLowestVal As Integer = 1
    Dim dHighestVal As Integer = 26
    Dim dItemAmount As Integer = 1
    Dim RollCheck As New HashSet(Of Integer)

    Private Sub btnExit_Click(sender As Object, e As EventArgs) Handles btnExit.Click
        End
    End Sub

    Private Sub btnRollDice_Click(sender As Object, e As EventArgs) Handles btnRollDice.Click
        lblRandomNo.Text = r.Next(dLowestVal, dHighestVal)

        lblItemAmount.Text = dItemAmount

        If dItemAmount = 1 Then
            RollCheck.Add(Val(lblRandomNo.Text))
        ElseIf (RollCheck.Contains(Val(lblRandomNo.Text))) Then
            MsgBox("Already Exists")
            lblRandomNo.Text = r.Next(dLowestVal, dHighestVal)
            RollCheck.Add(Val(lblRandomNo.Text))
        End If

        dItemAmount = dItemAmount + 1

Thanks in advance.

Upvotes: 1

Views: 1662

Answers (2)

Visual Vincent
Visual Vincent

Reputation: 18310

The point of the HashSet is that since it doesn't allow duplicates you can just check the return value of Add() to determine whether the number was successfully inserted or if it already exists in the list.

If you want to keep trying until it succeeds all you have to do is wrap it in a loop:

If dHighestVal - dLowestVal >= RollCheck.Count Then
    'If the above check passes all unique values are MOST LIKELY already in the list. Exit to avoid infinite loop.
    MessageBox.Show("List is full!")
    Return 'Do not continue.
End If

Dim Num As Integer = r.Next(dLowestVal, dHighestVal)

'Iterate until a unique number was generated.
While Not RollCheck.Add(Num)
    MessageBox.Show("Already exists!")
    Num = r.Next(dLowestVal, dHighestVal)
End While

lblRandomNo.Text = Num

An alternative way of writing the loop is: While RollCheck.Add(Num) = False.

Upvotes: 2

Steve
Steve

Reputation: 216293

You could replace your whole method with this simple one

' This is globally declared at the top of your form
Dim values As New List(Of Integer)

' This is called when you construct your form
' It will store consecutive integers from 1 to 25 (25 elements)
values = Enumerable.Range(1, 25).ToList()

This is the method that extract an integer from your values that is not already used

Private Sub Roll()
    ' Get an index in the values list
    Dim v = r.Next(0, values.Count)

    ' insert the value at that index to your RollCheck HashSet
    RollCheck.Add(values(v))

    ' Remove the found value from the values list, so the next call 
    ' cannot retrieve it again. 
    values.Remove(values(v))
End Sub

And you can call it from the previous event handler in this way

Private Sub btnRollDice_Click(sender As Object, e As EventArgs) Handles btnRollDice.Click
  if values.Count = 0 Then
      MessageBox("No more roll available")
  else
      Roll()
  End Sub
End Sub

Upvotes: 6

Related Questions