更有效的循环

时间:2014-07-18 13:43:55

标签: vb.net

我在Visual Basic中制作了一个玩家匹配程序。该程序应该选择随机注册的玩家并配对。我目前正在研究奇数玩家的一部分。

我所拥有的解决方案正在发挥作用,但可能并不那么有效。我有更好的方法来编写这段代码吗?

代码应该选择随机玩家,并确保不再选择它们。如你所见,为了使代码工作,我必须让它循环数千次。如果我没有一些玩家不会出现在列表框中。有更好的解决方案???

如果它令人困惑" spiller"是"播放器"

的挪威语
For i As Integer = 0 To 100000
            Dim spiller1 As Integer
            Dim spiller2 As Integer

            Do
                spiller1 = CInt(Math.Floor(Rnd() * spillerListe.Count))
                spiller2 = CInt(Math.Floor(Rnd() * spillerListe.Count))

            Loop Until CBool(spiller1 <> spiller2)

            If brukteSpillere(spiller1) = False And brukteSpillere(spiller2) = False Then
                brukteSpillere(spiller1) = True
                brukteSpillere(spiller2) = True
                lstSpillere.Items.Add(spillerListe(spiller1).ToString + " VS. " + spillerListe(spiller2).ToString())
            End If
        Next i

4 个答案:

答案 0 :(得分:4)

这是一团糟......拥有一个包含所有可用索引的List(Of Integer)。

Loop while availableIndex.Count > 1
   Pick a random index from availableIndex and remove it from that list
   Pick a random index from availableIndex and remove it from that list

   Add these two index to the list of pairs
End Loop

这样您就不需要检查随机值是否相同或者是否已经选择它们。

现在,如果您不想创建列表。然后威胁随机数不作为索引,而是作为要检查的项目数。

Delta = RandomNumber
x = 0

For i As Integer = 0 To itemList.Count-1
  If Not itemList(i).IsChoosen Then
    x += 1

    If x = Delta Then
       ' i is now your item to pick
       itemList(i).IsChoosen = True
       Exit For
    End If
  End If
Next

答案 1 :(得分:2)

解决此问题有两种有效方法:

  1. 按随机数对播放器列表进行排序,然后将1与2,3匹配为4,依此类推。

    Dim r As New Random
    Dim randomListe = spillerListe.OrderBy(Function() r.Next).ToList
    
  2. 从您的范围生成两个随机数,将这些玩家匹配到一个单独的列表中,从原始列表中删除玩家。一般来自较小范围的两个随机数(原始减去2),匹配等等。

  3. 编辑:看了MSDN后,List的RemoveAt性能为O(n),所以效率不高,最好使用字典which is O(1) at removing items,所以而不是spillerListe有一些spillerDicte,您可以在表格中添加条目(key = index,value = item)。

答案 2 :(得分:0)

如果您将玩家的名字保留在列表中,并且在挑选玩家后将其从列表中删除,该怎么办?可能这不是最好的高性能解决方案,但很明显你想做什么

Dim lstSpillere = new List(Of String)() ' Just for the example below
Dim spillerListe = new List(Of String)() from {"Marc", "John", "Steve", "George", "David", "Jeremy", "Andrew" }

Dim rnd = new Random()
While spillerListe.Count > 1
    Dim firstPlayer = spillerListe(rnd.Next(0, spillerListe.Count))
    spillerListe.Remove(firstPlayer)
    Dim secondPlayer = spillerListe(rnd.Next(0, spillerListe.Count))
    spillerListe.Remove(secondPlayer)
    lstSpillere.Add(firstPlayer + " VS. " + secondPlayer)
    ' for debug purpose....
    Console.WriteLine(firstPlayer & " VS. " & secondPlayer)
End While

if spillerListe.Count > 0 Then
   Console.WriteLine("Excluded from play list is:" & spillerListe(0))
End if

这里的重要关键是生成应该在循环外部的Random实例,以避免在循环执行所需的短时间内生成相同的数字。

答案 3 :(得分:0)

试试这个:

Module Module1
Dim rnd As New Random

Sub Main()

    Dim RegisteredPlayers As New List(Of Player)
    ' Fill List (example 100 players)
    For index As Integer = 1 To 100
        RegisteredPlayers.Add(New Player(String.Format("Player{0}", index)))
    Next
    'Sort Players using a random number
    Dim SortedPlayersArray = RandomSortItems(RegisteredPlayers.ToArray())

    'Pair players by selecting 2 consequative ones from randomly sorted array
    Dim Matches As New List(Of Match)
    For index As Integer = 1 To SortedPlayersArray.Length Step 2
        Dim m As Match = New Match(SortedPlayersArray(index - 1), SortedPlayersArray(index))
        Matches.Add(m)
        Debug.WriteLine(m.ToString())
    Next
    ' Match Player48 vs. Player79
    ' Match Player3 vs. Player53
    ' Match Player18 vs. Player43
    ' Match Player85 vs. Player1
    ' Match Player47 vs. Player56
    ' Match Player23 vs. Player66
    ' etc..

End Sub

Public Function RandomSortItems(Of T)(ByVal items As T()) As T()
    Dim sorted As T() = New T(items.Length-1) {}
    Array.Copy(items, sorted, sorted.Length)
    Dim keys As Double() = New Double(items.Length-1) {}
    For i As Integer = 1 To items.Length
        keys(i - 1) = rnd.NextDouble()
    Next
    Array.Sort(keys, sorted)
    Return sorted
End Function
End Module1

Public Class Player
    Dim m_name As String
    Public Sub New(ByVal player_name As String)
        m_name = player_name
    End Sub
    Public ReadOnly Property Name() As String
        Get
            Return m_name
        End Get
    End Property

    Public Overrides Function ToString() As String
        Return m_name
    End Function
End Class

Public Class Match
    Dim m_player_1 As Player, m_player_2 As Player

    Public Sub New(ByVal player_1 As Player, ByVal player_2 As Player)
        m_player_1 = player_1
        m_player_2 = player_2
    End Sub

    Public ReadOnly Property Player1() As Player
        Get
            Return m_player_1
        End Get
    End Property
    Public ReadOnly Property Player2() As Player
        Get
            Return m_player_2
        End Get
    End Property
    Public Overrides Function ToString() As String
        Return String.Format("Match {0} vs. {1}", Player1, Player2)
    End Function
End Class

编辑1:

备用随机分拣机(应该更快)

Public Function RandomSortItems(Of T)(ByVal items As T()) As T()
    Dim slist As New SortedList(Of Double, T)
    For i As Integer  = 1 to items.Length
        slist.Add(rnd.NextDouble(), items(i-1) )
    Next i
    return slist.Values.ToArray()
End Function