数组中的随机数,没有任何重复

时间:2013-07-16 00:35:40

标签: vb.net loops

我正在尝试使用循环将数字从0到51随机化,但我似乎无法将其拉下来。我的想法是那个

  1. 生成随机数
  2. 通过将前一个数字存储在数组中来检查是否已使用此随机数
  3. 如果使用了此随机数,则生成新的随机数,直到它不重复
  4. 如果不重复,请将其存储
  5. 我的尝试:

        Dim list(51) As Integer
        Dim templist(51) As Integer
    
        For i As Integer = 0 To 51 Step 1
            list(i) = i
        Next i
    
        Do While counter <= 51
            p = rand.Next(0, 52)
            templist(counter) = p
            For n As Integer = 0 To 51 Step 1
                p = rand.Next(0, 52)
                If templist(n) = p Then
                    Do While templist(n) = p
                        p = rand.Next(0, 52)
                    Loop
                    templist(n) = p
                Else
                    templist(n) = p
                End If
    
            Next
    
            counter += 1
        Loop
    
        For n As Integer = 0 To 51 Step 1
            ListBox1.Items.Add(templist(n))
        Next
    

4 个答案:

答案 0 :(得分:2)

如果您只列出所有可能的数字(在您的情况下为0到51),那么将会更容易,然后从列表中删除该数字,以便无法再次选择它。尝试这样的事情:

Dim allNumbers As New List (Of Integer)
Dim randomNumbers As New List (Of Integer)
Dim rand as New Random

' Fill the list of all numbers
For i As Integer = 0 To 51 Step 1
    allNumbers.Add(i)
Next i

' Grab a random entry from the list of all numbers
For i As Integer = 0 To 51 Step 1
    Dim selectedIndex as Integer = rand.Next(0, (allNumbers.Count - 1) )
    Dim selectedNumber as Integer = allNumbers(selectedIndex)
    randomNumbers.Add(selectedNumber)
    allNumbers.Remove(selectedNumber)
    ' Might as well just add the number to ListBox1 here, too
    ListBox1.Items.Add(selectedNumber)
Next i

如果您的目标是将数字输入ListBox1,那么您甚至不需要“randomNumbers”列表。

编辑:

如果你必须有一个数组,请尝试这样的事情:

Function RandomArray(min As Integer, max As Integer) As Integer()

    If min >= max Then
        Throw New Exception("Min. must be less than Max.)")
    End If

    Dim count As Integer = (max - min)
    Dim randomNumbers(count) As Integer
    Dim rand As New Random()

    ' Since an array of integers sets every number to zero, and zero is possibly within our min/max range (0-51 here),
    ' we have to initialize every number in the array to something that is outside our min/max range.
    If min <= 0 AndAlso max >= 0 Then
        For i As Integer = 0 To count
            randomNumbers(i) = (min - 1)    ' Could also be max + 1
        Next i
    End If

    Dim counter As Integer = 0
    ' Loop until the array has count # of elements (so counter will be equal to count + 1, since it is incremented AFTER we place a number in the array)
    Do Until counter = count + 1
        Dim someNumber As Integer = rand.Next(min, max + 1)
        ' Only add the number if it is not already in the array
        If Not randomNumbers.Contains(someNumber) Then
            randomNumbers(counter) = someNumber
            counter += 1
        End If
    Loop

    Return randomNumbers
End Function

这对你的任务来说已经足够了,但我的计算机科学家讨厌这个算法。

这就是为什么这个算法不太理想。如果零在您的数字范围内,则必须至少循环2N次(如果从0到51,则需要104次以上)。这是最好的情况;随着数字范围的扩大,这种算法的时间复杂度实际上变得更糟。例如,如果您尝试从0到100,000运行它,它将非常快速地填充前几千个数字,但随着它的继续,找到一个尚未在列表中的数字将花费更长时间。当你到达最后几个数字时,你可能会在找到最后几个数字之前随机生成几万亿个不同的数字。如果你假设平均复杂度为100000! (100,000阶乘),然后循环将执行近十到五十万次幂。

数组更难以“随机播放”,因为它是固定大小的,因此您无法使用列表或集合来添加和删除项目。但是,你可以做的是按顺序用数字填充数组,然后通过随机数量的迭代来随机交换两个数字的位置。

答案 1 :(得分:0)

Do While counter <= 51
            p = rand.Next(0, 52)

            While Array.IndexOf(list, p) = -1
                p = rand.Next(0, 52)
            End While

            counter += 1
        Loop

答案 2 :(得分:0)

大约5年内没有写过VB,但试试这个:

Function GetRandomUniqueNumbersList(ByVal fromNumber As Integer, ByVal toNumber As Integer) As List(Of Integer)
    If (toNumber <= fromNumber) Then
        Throw New ArgumentException("toNumber must be greater than fromNumber", toNumber)
    End If
    Dim random As New Random
    Dim randomNumbers As New HashSet(Of Integer)()
    Do
        randomNumbers.Add(random.Next(fromNumber, toNumber))
    Loop While (randomNumbers.Count < toNumber - fromNumber)
    Return randomNumbers.ToList()
End Function

好的,那很痛苦。如果我犯了任何错误,请有人纠正。应该非常快,因为它使用的是HashSet。

答案 3 :(得分:0)

对stackoverflow论坛的第一反应 - 温柔。 我正在寻找一种方法来做到这一点,但无法在网上找到合适的例子。 我自己也去了,最终还是开始工作了:

Sub addUnique(ByRef tempList, ByVal n, ByRef s)
    Dim rand = CInt(Rnd() * 15) + 1
    For j = 0 To n
        If tempList(j) = rand Then
            s = True
        End If
    Next
    If s = False Then
        tempList(n) = rand
    Else
        s = False
        addUnique(tempList, n, s)
    End If
End Sub

然后使用:

调用sub
Dim values(15) As Byte
Dim valueSeen As Boolean = False
For i = 0 To 15
    addUnique(values, i, valueSeen)
Next

这将随机将数字1到16添加到数组中。每次添加一个值时,都会检查数组中的先前值,如果它们中的任何一个与随机生成的值相同,则s设置为true。如果未找到值(s = false),则添加随机生成的值。如果在&#39; For&#39;结束时s仍然为真,则再次递归调用sub。环。可能需要&#39; Randomize()&#39;在某处。

如果布局有点不稳定,请道歉。