1

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

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

我的尝试:

    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

4 回答 4

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 阶乘),那么循环将执行几乎十到百万分之一的幂次。

数组更难“洗牌”,因为它是固定大小的,因此您不能像使用列表或集合那样真正添加和删除项目。但是,您可以做的是按顺序用您的数字填充数组,然后进行随机次数的迭代,在其中随机交换两个数字的位置。

于 2013-07-16T01:05:01.963 回答
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
于 2013-07-16T01:09:58.397 回答
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。

于 2013-07-16T01:36:19.070 回答
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

然后使用以下命令调用子:

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),则添加随机生成的值。如果在“For”循环结束时 s 仍然为真,则再次递归调用 sub。可能在某处需要'Randomize()'。

抱歉,如果布局有点摇摆不定。

于 2016-11-23T14:13:22.760 回答