【问题标题】:Write a method to shuffle a deck of cards in VB.NET编写一个在 VB.NET 中洗牌的方法
【发布时间】:2011-11-13 00:24:19
【问题描述】:

我有一副标准的 52 张卡片以数组表示。每张卡片都表示为一个整数。我写了下面的函数来洗牌。下面的代码看起来还可以吗?

Module Module3

Sub Main()

    ' initialize array
    Dim Cards(52) As Integer

    ' Unit Test
    ' Pass array as argument.
    Console.WriteLine(shuffle(Cards))

End Sub

Function shuffle(ByVal Cards() As Integer)

    Dim counter = 1
    Dim rand = New Random()

    For Each card In Cards

        ' Grab random number with range of 52
        Dim n = rand.Next(52)

        ' Pick a card
        Dim temp = Cards(counter)

        ' Swap picked card with random card
        Cards(counter) = Cards(n)
        Cards(n) = temp

        counter += 1

    Next

    Return (Cards)

End Function

End Module

【问题讨论】:

标签: vb.net


【解决方案1】:

不,代码没有按照你说的做。

Dim Cards(52) As Integer

这将为 53 张卡片创建一个数组,而不是 52 张。使用:

Dim Cards(51) As Integer

洗牌时,将每张牌与牌组中较早的牌(或本身)交换,而不是牌组中的任何位置。 (这就是Fisher-Yates shuffle的原理。)

不要将计数器与循环分开,而是使用计数器进行循环。

Dim rand = New Random()

For counter = 0 to Cards.Length - 1

  Dim n = rand.Next(counter + 1)

  Dim temp = Cards(counter)
  Cards(counter) = Cards(n)
  Cards(n) = temp

Next

【讨论】:

    【解决方案2】:

    查看 Jeff Atwood 关于该主题的博文。

    http://www.codinghorror.com/blog/2007/12/shuffling.html

    【讨论】:

    • 我想知道英特尔的 Bull Mountain 架构将如何影响这一切?
    【解决方案3】:

    如果这将用于某些游戏,我不会使用数组,我会使用列表,因为可以添加/删除轻松项目。

    Module Module1
    
        Dim deck As New List(Of Integer)
        Dim prng As New Random
    
        Sub Main()
            newDeck()
            showDeck()
            shuffle()
            showDeck()
            Dim s As String
            Do
                s = Console.ReadLine()
                Select Case s
                    Case "s"
                        showDeck()
                    Case "c"
                        If deck.Count = 0 Then
                            Console.WriteLine("No cards")
                        Else
                            'take top card
                            Dim foo As Integer = deck(0)
                            deck.RemoveAt(0)
                            Console.WriteLine(foo.ToString)
                        End If
                    Case "n"
                        newDeck()
                        shuffle()
                End Select
            Loop Until s.ToLower = "x"
        End Sub
    
        Sub newDeck()
            deck = Enumerable.Range(1, 52).ToList 'create deck
        End Sub
    
        Sub shuffle()
            deck = deck.OrderBy(Function(r) prng.Next).ToList
        End Sub
    
        Sub showDeck()
            Dim ctr As Integer = 0
            Console.WriteLine()
            For Each card As Integer In deck
                Console.Write("{0}", card.ToString.PadLeft(4, " "c))
                ctr += 1
                If ctr Mod 10 = 0 Then Console.WriteLine()
            Next
            Console.WriteLine()
        End Sub
    End Module
    

    一段时间以来,我一直认为这是计算机不应该完全模仿现实世界的情况。首先,这是一个程序,它显示了知道随机数生成器的种子的问题。

    'create a form with three buttons and a richtextbox
    Dim deckIdx As New List(Of Integer)
    Dim cards As New List(Of card)
    Dim prng As New Random
    
    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        newDeck()
        shuffle()
        showDeck()
    End Sub
    
    Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click
        'show next five cards
        Dim sb As New System.Text.StringBuilder
        sb.AppendLine()
        For x As Integer = 1 To 5
            Dim foo As card = getTopCard()
            If Not foo Is Nothing Then sb.AppendFormat("{0}", foo.theCard.ToString.PadLeft(4, " "c))
        Next
        RichTextBox1.AppendText(sb.ToString)
        RichTextBox1.ScrollToCaret()
    End Sub
    
    Private Sub Form1_Shown(sender As Object, e As System.EventArgs) Handles Me.Shown
        Button1.PerformClick()
    End Sub
    
    Class card
        Public theCard As Integer
        Public count As Integer
    End Class
    
    Sub newDeck()
        prng = New Random(42) '<<<<<<<<<<<<<<<<<<<<<<<< OOPS!!!
        deckIdx = Enumerable.Range(0, 51).ToList 'create deck indicies
        cards = New List(Of card)
        For Each cIDX As Integer In deckIdx
            Dim foo As New card
            foo.theCard = cIDX
            foo.count = 0
            cards.Add(foo)
        Next
    End Sub
    
    Sub shuffle()
        deckIdx = deckIdx.OrderBy(Function(r) prng.Next).ToList
    End Sub
    
    Function getTopCard() As card
        If deckIdx.Count > 0 Then
            Dim foo As New card
            foo.theCard = cards(deckIdx(0)).theCard
            foo.count = cards(deckIdx(0)).count
            deckIdx.RemoveAt(0)
            Return foo
        Else
            Return Nothing
        End If
    End Function
    
    Sub showDeck()
        Dim ctr As Integer = 0
        Dim sb As New System.Text.StringBuilder
        For Each card As Integer In deckIdx
            sb.AppendFormat("{0}", cards(card).theCard.ToString.PadLeft(4, " "c))
            ctr += 1
            If ctr Mod 10 = 0 Then sb.AppendLine()
        Next
        RichTextBox1.Text = sb.ToString
    End Sub
    

    运行程序并反复按下按钮 1 / 3 将产生相同的结果,一遍又一遍。如果我们要坚持计算机必须完全模仿现实世界的想法,那么明显的解决方法是不要重新播种 PRNG。但是,如果我们采用不同的方法会怎样。

    添加此代码

    Dim bkgShuffle As Threading.Thread
    Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
        Button2.Enabled = False
        bkgShuffle = New Threading.Thread(AddressOf shuffleBkg)
        bkgShuffle.IsBackground = True
        bkgShuffle.Start()
    End Sub
    
    Sub shuffleBkg()
        Do
            Threading.Thread.Sleep(50)
            shuffle()
        Loop
    End Sub
    

    像以前一样运行程序,按下按钮 1 和 3 以验证没有任何变化。满意后按按钮 2,然后按按钮 1 和 3。

    当你亲自打牌时,很明显牌组并没有不断地被洗牌,但如果是这样呢?它会改变什么吗?如果我在网上打牌,我是否知道或关心牌组是否不断被洗牌?

    代码只是为了说明一个观点,跳出框框思考,不应被视为成品。

    编辑: Bull Mountain 可能会影响其中的一部分。

    【讨论】:

    • 什么会终止 shuffleBkg 方法中的无限循环?
    • 应用程序结束。正如我所说,这是为了证明一个观点。
    【解决方案4】:

    现在正式称为“布里格斯”洗牌

    Module module1
    
    Dim cards(51) As String
    Dim trues(51) As Boolean
    Dim number, Truecheck As Integer
    Dim stores, loopy As String
    
    Sub main()
    
        number = 1
    
        cards(0) = "Ace of Spades"
        cards(10) = "Jack of Spades"
        cards(11) = "Queen of Spades"
        cards(12) = "King of Spades"
    
        cards(13) = "Ace of Clubs"
        cards(23) = "Jack of Clubs"
        cards(24) = "Queen of Clubs"
        cards(25) = "King of Clubs"
    
        cards(26) = "Aec of Diamonds"
        cards(36) = "Jack of Diamods"
        cards(37) = "Queen of Diamonds"
        cards(38) = "King of Diamonds"
    
        cards(39) = "Ace of Hearts"
        cards(49) = "Jack of Heats"
        cards(50) = "Queen of Hearts"
        cards(51) = "King of Hearts"
    
    
        For i = 1 To 9
            number = number + 1
            cards(i) = number.ToString + " of Spades"
        Next
    
        number = 1
    
        For i = 14 To 22
            number = number + 1
            cards(i) = number.ToString + " of Clubs"
        Next
    
        number = 1
    
        For i = 27 To 35
            number = number + 1
            cards(i) = number.ToString + " of Diamonds"
        Next
    
        number = 1
    
        For i = 40 To 48
            number = number + 1
            cards(i) = number.ToString + " of Hearts"
        Next
    
        For i = 0 To 51
            Console.WriteLine(cards(i))
        Next
    
    
        Console.WriteLine("")
        Console.WriteLine("")
    
        For i = 0 To 51
    
    linetrue:
    
            Randomize()
            stores = cards(i)
            Truecheck = Int(Rnd() * 51)
            If trues(Truecheck) = True Then GoTo linetrue
    
            trues(i) = True
            cards(i) = cards(Truecheck)
            cards(Truecheck) = stores
            Console.WriteLine(cards(i))
    
        Next
    
    
    End Sub
    
    
    End Module
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-09
      • 1970-01-01
      • 2015-01-14
      • 2016-01-02
      • 1970-01-01
      相关资源
      最近更新 更多