在 vb.net 中打乱字符串数组 [英] Shuffling an array of strings in vb.net

查看:30
本文介绍了在 vb.net 中打乱字符串数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在 vb.net 中开发一个网页,该网页将为用户生成许多选择题.我需要打乱已经放在数组中的四个答案.让我们假设我必须遵循数组:

I am developing a webpage in vb.net that will generate a number of multiple choice questions to the user. I need to shuffle the four answers which are already put in an array. Lets assume that I have to following array:

array = {"Correct", "Wrong1", "Wrong2", "Wrong3"}

我尝试使用以下方法:

Public Shared Function Shuffle(ByVal items() As String) As Array
        Dim max_index As Integer = items.Length - 1
        Dim rnd As New Random(DateTime.Now.Millisecond)
        For i As Integer = 0 To max_index
            ' Pick an item for position i.
            Randomize()
            Dim j As Integer = rnd.Next(i, max_index)
            ' Swap them.
            Dim temp As String = items(i)
            items(i) = items(j)
            items(j) = temp
        Next i
        Return items
    End Function

该功能运行良好,但我的问题是,如果我有四个问题,每个问题的答案将被随机排列,但正确答案将在一个位置,例如:

The function is working really fine, but my problem is that if I have four questions, the answers will be shuffled for each question but the correct answer will be in one position like:

    array = {"Wrong1", "Correct", "Wrong2", "Wrong3"}
    array = {"Wrong2", "Correct", "Wrong3", "Wrong1"}
    array = {"Wrong3", "Correct", "Wrong1", "Wrong2"}
    array = {"Wrong1", "Correct", "Wrong3", "Wrong2"}

我需要的是将其位置从一个问题更改为另一个问题的正确答案.感谢您的帮助.

What I need is the correct answer to change its location from one question to another. Your help is appreciated.

推荐答案

您的 Shuffle 方法和 Random 的使用存在几个问题.

There are several issues with your your Shuffle method and use of Random.

  1. Randomize 用于旧的、遗留的 VB Rnd 函数.它对闪亮的新 NET Random 类没有影响.
  2. 很少需要提供自定义种子;事实上,这可能对您不利.
  3. 创建一个 Random 供整个应用程序使用,而不是每次您随机播放(或单击某些内容)时使用.并且永远不要在循环中创建它们 - 这几乎可以保证重复的数字.

  1. Randomize is for use with the old, legacy VB Rnd function. It has no impact on the shiny new NET Random class.
  2. There is rarely a need to provide a custom seed; in fact this can work against you.
  3. Create one Random for the entire app to use rather than each time you shuffle (or click something). And never create them in a loop - this almost guarantees repeated numbers.

Random.Next(min, max) 的 max 参数是独占,所以你的范围实际上比它应该的小 1 个元素.

The max argument to Random.Next(min, max) is exclusive, so your range is actually 1 element smaller than it should be.

  • 通常 Fisher-Yates Shuffle 的 NET 版本是就地洗牌 (Sub) 使其非常高效(而不是返回新集合)
  • 在列表或数组中向后循环很重要.1
  • Generally the NET version of the Fisher-Yates Shuffle is an in place shuffle (Sub) making it very efficient (rather than returning a new collection)
  • It is important to loops backwards thru the list or array.1

标准的费舍尔-耶茨洗牌:

' form/class level var
Private rnd As New Random()

Public Sub Shuffle(items As String())
    Dim j As Int32
    Dim temp As String

    For n As Int32 = items.Length - 1 To 0 Step -1
        j = rnd.Next(0, n + 1)
        ' Swap them.
        temp = items(n)
        items(n) = items(j)
        items(j) = temp
    Next n
End Sub

来自相同起始数组的 4 次 shuffle 的输出:

Output from 4 shuffles of the same starting array:

Shuffle #1    Wrong3   Correct  Wrong2   Wrong1   
Shuffle #2    Correct  Wrong2   Wrong1    Wrong3   
Shuffle #3    Wrong2   Correct  Wrong3    Wrong1   
Shuffle #4    Correct  Wrong1   Wrong2    Wrong3   
Shuffle #5    Correct  Wrong1   Wrong3    Wrong2   

变化

您可以传递它而不是全局 Random 生成器(用作扩展方法):

Variations

Rather than a global Random generator, you can pass it (useful as an extension method):

Public Sub Shuffle(items As String(), RNG As Random)

改组多种类型的通用方法:

Generic method for shuffling many types:

' Generic shuffle for basic type arrays
Public Sub Shuffle(Of T)(items As T(), rng As Random)
    Dim temp As T
    Dim j As Int32

    For i As Int32 = items.Count - 1 To 0 Step -1
        ' Pick an item for position i.
        j = rng.Next(i + 1)
        ' Swap 
        temp = items(i)
        items(i) = items(j)
        items(j) = temp
    Next i
End Sub

示例:

Shuffle(intArray, myRnd)
Shuffle(strArray, myRnd)
Shuffle(colors, myRnd)
Shuffle(myButtons, myRnd)

简单的重新排序

最后,对于可能只对它们重新排序一次的简单版本,使用扩展方法的简单且通常足够好的版本:

Finally, for something simple where you might only reorder them once, a simple and usually-good-enough version using an extension method:

Dim ShuffledItems = myItems.OrderBy(Function() rnd.Next).ToArray()

这具有较少的代码并且很容易实现,但是效率很多.

This has less code and is easy to dash off, but is much less efficient.

1 要向后循环的原因是将每个数组元素限制为一个交换.在最后一步中将X"移至 items(j) 后,将不再考虑该位置,因为 rnd.Next(0, n + 1) 只会选择直到最后一个元素/循环索引.许多实现都弄错了.

1 The reason that you want to loop backwards is to limit each array element to one swap. Once "X" is moved to items(j) in the last step, that position is removed from consideration because rnd.Next(0, n + 1) will only pick up to the last element/loop index. Many implementations get this wrong.

这篇关于在 vb.net 中打乱字符串数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆