【问题标题】:Non-repeating random number generator?非重复随机数生成器?
【发布时间】:2011-11-24 10:49:15
【问题描述】:

我使用 Visual Basic for Applications (Excel) 创建了一个问答游戏,它通过一个案例陈述来选择问题,其中案例是数字。我让程序随机选择一个从 1 到最大问题数量的数字。使用这种方法,游戏会重复问题。

有没有办法制作随机生成数字(每次结果不同)并且不会重复一个数字多次的东西?在它完成了执行特定代码所需的所有数字之后。 (我将输入结束游戏的代码并显示他们正确和错误的问题数量)

我想到了几种不同的方法来做到这一点,但是我什至无法开始思考语法可能是什么。

【问题讨论】:

  • 我一定是遗漏了一些东西,我认为你想防止同一个问题出现两次?

标签: vba random generator


【解决方案1】:

听起来您需要一个 Array Shuffler!

查看以下链接 - http://www.cpearson.com/excel/ShuffleArray.aspx

Function ShuffleArray(InArray() As Variant) As Variant()
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' ShuffleArray
' This function returns the values of InArray in random order. The original
' InArray is not modified.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Dim N As Long
    Dim Temp As Variant
    Dim J As Long
    Dim Arr() As Variant


    Randomize
    L = UBound(InArray) - LBound(InArray) + 1
    ReDim Arr(LBound(InArray) To UBound(InArray))
    For N = LBound(InArray) To UBound(InArray)
        Arr(N) = InArray(N)
    Next N
    For N = LBound(InArray) To UBound(InArray)
        J = CLng(((UBound(InArray) - N) * Rnd) + N)
        Temp = InArray(N)
        InArray(N) = InArray(J)
        InArray(J) = Temp
    Next N
    ShuffleArray = Arr
End Function

Sub ShuffleArrayInPlace(InArray() As Variant)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' ShuffleArrayInPlace
' This shuffles InArray to random order, randomized in place.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Dim N As Long
    Dim Temp As Variant
    Dim J As Long

    Randomize
    For N = LBound(InArray) To UBound(InArray)
        J = CLng(((UBound(InArray) - N) * Rnd) + N)
        If N <> J Then
            Temp = InArray(N)
            InArray(N) = InArray(J)
            InArray(J) = Temp
        End If
    Next N
End Sub

【讨论】:

  • +1。随机化并在开始时完成所有工作,这样您就可以循环遍历随机列表是明智的。保存每个问题后的工作。
【解决方案2】:

这里还有一个例子。它生成一个唯一的随机长数组。 在此示例中,我使用 1 到 100。它通过使用集合对象来实现。然后,您可以对 qArray 中的每个数组元素进行正常循环,而无需多次随机化。

Sub test()
Dim qArray() As Long
ReDim qArray(1 To 100)

qArray() = RandomQuestionArray
'loop through your questions

End Sub

Function RandomQuestionArray()  
Dim i As Long, n As Long
Dim numArray(1 To 100) As Long
Dim numCollection As New Collection

With numCollection
    For i = 1 To 100
        .Add i
    Next
    For i = 1 To 100
        n = Rnd * (.Count - 1) + 1
        numArray(i) = numCollection(n)
        .Remove n
    Next
End With

RandomQuestionArray = numArray()

End Function

【讨论】:

  • 我喜欢你的方法,它更干净
【解决方案3】:

我看到你有答案,我正在处理这个问题,但失去了我的互联网连接。无论如何,这是另一种方法。

'// Builds a question bank (make it a hidden sheet)
Sub ResetQuestions()
    Const lTotalQuestions As Long = 300 '// Total number of questions.

    With Range("A1")
        .Value = 1
        .AutoFill Destination:=Range("A1").Resize(lTotalQuestions), Type:=xlFillSeries
    End With

End Sub
'// Gets a random question number and removes it from the bank
Function GetQuestionNumber()
    Dim lCount As Long   

    lCount = Cells(Rows.Count, 1).End(xlUp).Row      

    GetQuestionNumber = Cells(Int(lCount * Rnd + 1), 1).Value

    Cells(lRandom, 1).Delete
End Function

Sub Test()

    Msgbox (GetQuestionNumber)

End Sub

【讨论】:

    【解决方案4】:

    无论这里有什么价值,都是我对这个问题的抨击。这个使用布尔函数而不是数值数组。它非常简单但非常快。我并不是说它的优点是完美的,它是一个有效的解决长期数字的方法,因为你只检查你已经选择和保存的数字,不需要一个潜在的大数组来保存这些值你已经拒绝了,所以它不会因为数组的大小而导致内存问题。

    Sub UniqueRandomGenerator()
    Dim N As Long, MaxNum As Long, MinNum As Long, Rand As Long, i As Long
    
    MinNum = 1        'Put the input of minimum number here
    MaxNum = 100      'Put the input of maximum number here
    N = MaxNum - MinNum + 1
    
    ReDim Unique(1 To N, 1 To 1)
    
    For i = 1 To N
    Randomize         'I put this inside the loop to make sure of generating "good" random numbers
        Do
            Rand = Int(MinNum + N * Rnd)
            If IsUnique(Rand, Unique) Then Unique(i, 1) = Rand:  Exit Do
        Loop
    Next
    Sheet1.[A1].Resize(N) = Unique
    End Sub
    
    Function IsUnique(Num As Long, Data As Variant) As Boolean
    Dim iFind As Long
    
    On Error GoTo Unique
    iFind = Application.WorksheetFunction.Match(Num, Data, 0)
    
    If iFind > 0 Then IsUnique = False: Exit Function
    
    Unique:
        IsUnique = True
    End Function
    

    【讨论】:

      猜你喜欢
      • 2013-04-06
      • 1970-01-01
      • 1970-01-01
      • 2014-06-10
      • 1970-01-01
      • 2011-07-19
      相关资源
      最近更新 更多