【问题标题】:Different numbers from 1 to 10从 1 到 10 的不同数字
【发布时间】:2010-12-23 22:28:39
【问题描述】:

我想从 0-9 的范围内生成 10 个不同的数字。所需的输出可能如下所示,9 0 8 6 5 3 2 4 1 7

Dim arraynum(9) As Integer
Dim crmd As Boolean
Dim rmd as integer

For i = 0 To 9
    arraynum(i) = -1
Next i

crmd = True
Randomize Timer
For i = 0 To 9
    rmd = Int(Rnd * 10)
    For j = 0 To 9
        If arraynum(j) = rmd Then
            j = 9
            If crmd = False Then
                i = i - 1
            End If
            crmd = True
        Else
            crmd = False
        End If
    Next j
    If crmd = False Then
        arraynum(i) = rmd
        QuestionILabel.Caption = QuestionILabel.Caption + Str(arraynum(i))
    End If
Next i

【问题讨论】:

  • 拜托拜托 RTFM - (换句话说,你到目前为止尝试了什么,等等,等等,等等)。我们不只是为您做作业:(
  • 当您编辑您的问题时 - 向右看:How to Format: • 将代码缩进 4 个空格
  • 单击编辑并输入代码,选择它并按 ctrl-k(哦,是的,然后单击保存)
  • 当然可以有真随机数:xkcd.com/221
  • @phil 我大笑并 +1 甚至没有点击链接。 xkcd FTW!

标签: vb6


【解决方案1】:

没有指定性能要求,我将使用以下简短的代码:

Randomize
With CreateObject("Scripting.Dictionary")
    Do
        .Item(Int(Rnd * 10)) = ""
    Loop Until .Count = 10
    MsgBox Join(.Keys)
End With

【讨论】:

    【解决方案2】:

    这是最简单但有效的代码。也没有 API!

    Dim a(1 To 10), tmp, count, isRepeated
    count = 1
    Randomize
    While count <= 10
        isRepeated = False
        tmp = Left(Rnd * 10, 1)
        For i = 1 To 10
            If tmp = a(i) Then isRepeated = True: Exit For
        Next
        If isRepeated = False Then a(count) = tmp: count = count + 1
    Wend
    YourLine = Join(a, "")
    

    【讨论】:

    • @Deanna,对不起,有很多错误。现在我已经修复了它们。请删除你的 cmets:)
    • 这与this answer 中给出的解决方案相同,这正是 OP 试图避免的。我的反对票仍然有效。
    【解决方案3】:
    Option Explicit 'Force variable declaration
    
    Private Sub Form_Load()
        Dim Ar(1 To 100) As Integer 'The array to store it in
        Dim i, j As Integer 'Counters for loops
        Dim X As Integer 'Variable to store the random generated number
        Dim bFound As Boolean 'Boolean to check if the value has been generated before
    
        Randomize 'Just once to ensure that we get random values
    
        For i = 1 To 100
            Do 'Start the loop that generates a random number and checks if it has already been generated
                X = RandomInteger(1, 100) 'Generate a random number
                bFound = False 'Set the boolean to false, if we find the number while searching the array, we'll set it to true which means that we already have that number
                For j = 1 To i 'We only need to check up to i (since we haven't put any values in the rest of the array)
                    If Ar(j) = X Then 'If an item of the arrray is the same as the last generated number
                        bFound = True 'Set the boolean to true (it already exists)
                        DoEvents 'To not freeze until the looping is done
                        Exit For 'Since we found it there is no need to check the rest
                    End If
                Next
            Loop Until bFound = False 'If it wasn't found then we'll add it, if it was found then we go back to generating a new number and comparing it with all the items of the array
            Ar(i) = X 'Add it to the array
        Next
    
        ShowInTextBox Text1, Ar 'Just to print the data and see it
    End Sub
    
    Private Function RandomInteger(Lowerbound As Integer, Upperbound As Integer) As Integer 'The random number generator code
        RandomInteger = Int((Upperbound - Lowerbound + 1) * Rnd + Lowerbound)
    End Function
    
    Private Sub ShowInTextBox(TB As TextBox, A() As Integer) 'Just a sub to show the data in a textbox
        Dim i As Integer
    
        TB.Text = ""
    
        For i = 1 To UBound(A)
            TB.Text = TB.Text & CStr(A(i)) & vbCrLf
        Next
    
        TB.Text = Left$(TB.Text, Len(TB.Text) - 2)
    End Sub
    

    【讨论】:

    • 这与 OP 的解决方案完全相同,并被告知这是一个坏主意(由于必须检查 fintie 池)。 Shuffle 是一个更好的解决方案。
    【解决方案4】:

    选择随机值然后丢弃那些你已经使用过的值是一个的想法。由于您丢弃的数字越来越多,因此可用数字池越来越少,因此运行时间变长。

    你想要的是一个随机列表,我将使用以下代码(伪代码,因为它是家庭作业)来实现:

    dim n[10]                 // gives n[0] through n[9]
    for each i in 0..9:
        n[i] = i              // initialize them to their indexes
    nsize = 10                // starting pool size
    do 10 times:
        i = rnd(nsize)        // give a number between 0 and nsize-1
        print n[i]
        nsize = nsize - 1     // these two lines effectively remove the used number
        n[i] = n[nsize]
    

    只需从池中选择一个随机数,然后用该池中的顶部数字替换它并减小池的大小,您就可以进行洗牌,而不必担心预先进行大量交换。如果数量很大,这一点很重要,因为它不会引入不必要的启动延迟。

    例如,检查以下基准检查:

    <--------- n[x] ---------->
    for x = 0 1 2 3 4 5 6 7 8 9  nsize  rnd(nsize)  output
    ---------------------------  -----  ----------  ------
            0 1 2 3 4 5 6 7 8 9     10           4       4
            0 1 2 3 9 5 6 7 8        9           7       7
            0 1 2 3 9 5 6 8          8           2       2
            0 1 8 3 9 5 6            7           6       6
            0 1 8 3 9 5              6           0       0
            5 1 8 3 9                5           2       8
            5 1 9 3                  4           1       1
            5 3 9                    3           0       5
            9 3                      2           1       3
            9                        1           0       9
    

    您可以看到池在减少,因为您总是用未使用的替换使用过的,因此您永远不会重复。

    现在你的作业就是把它变成 VB :-)


    而且,由于这项作业现在几乎可以肯定已经过期了(大约一年前),为了完整起见,我将发布一个 VBA 解决方案来展示如何做。

    Option Explicit
    Option Base 0
    Sub Macro1()
        Randomize
        Dim list(10) As Integer
        Dim i As Integer
        Dim size As Integer
        Dim pos As Integer
        Dim result As String
    
        For i = 0 To 9
            list(i) = i
        Next
    
        size = 10
        result = ":"
        For i = 1 To 10
            pos = Int(Rnd() * size)
            result = result & list(pos) & ":"
            size = size - 1
            list(pos) = list(size)
        Next
    
        MsgBox result
    End Sub
    

    这在三个单独的运行中生成:

    :5:7:4:2:9:1:0:8:3:6:
    :3:9:6:0:7:8:5:4:2:1:
    :7:6:3:5:1:8:9:0:4:2:
    

    【讨论】:

    • 您使用 i 作为循环计数器,然后在循环内存储随机值 - 通过将随机数存储在另一个 int j; 中并将 i 替换为 j 来运行它循环内。算法+1。这个有具体的名字吗?
    • 找到了这个名字——Fisher-Yates shuffle。 en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
    • @studentnoob35783,如果你遇到错误,你没有从伪代码正确翻译它:-) 发布你的源代码,我会看看。
    • 我喜欢这个名字。 20 多年前,学习、恐惧、数纸牌,我“发明”(好的,实施)了同样的方法——这是编写纸牌游戏的唯一方法,其中记住抽出的纸牌很重要。基本上,为 0 到 X 选择一个随机数,从队列中拉出该位置的卡值,将其下方的所有内容移到一个位置。或者,如果你真的很敏锐,只需一个链表:)
    • @Corinne,伪代码中的注释指出i = rnd(nsize)"give a number between 0 and nsize-1"。因此,在给出4(0 到 9 之间的随机数)的第一次迭代中,n[4] 实际上是4。我怀疑您认为第一个元素的位置是一而不是零。这可能是这个词的常见英语用法,所以index 可能会更好。
    【解决方案5】:

    您需要对 0 到 9 的数组进行随机排列。

    我忘了怎么写基本的..类似的东西:

    dim a(10)
    for i=0 to 9 do a(i) = i
    rem do random permute over a:
    for i=0 to 9 do 
      j = rand() mod (i+1)
      tmp = a(j)
      a(i) = a(j)
      a(j) = tmp
    next i
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-11
    • 2016-04-18
    • 1970-01-01
    • 2022-11-18
    • 1970-01-01
    • 1970-01-01
    • 2020-01-04
    • 2017-08-05
    相关资源
    最近更新 更多