重複させない乱数を作りたいのですが…

解決


ichi  2007-01-06 01:19:17  No: 134765

こちらの掲示板ログで調べて、以下のようなプログラムを作りました。
乱数を発生させて、重複を防ぐために配列に入れて、後から確認させるようにしました。

    Sub Randomcount()

        Dim i As Integer
        Dim FLAG As Boolean = False

        Randomize()

        '乱数の発生
        Dim RAN As New Random
        TOIC = RAN.Next(99)
        Rnd(0) = TOIC

        If MONDAI = 1 Then
            Rnd(MONDAI) = TOIC

        ElseIf MONDAI = 2 Then
            If Rnd(1) = Rnd(0) Then
                TOIC = RAN.Next(99)
                Rnd(0) = TOIC
            Else
                Rnd(MONDAI) = TOIC
            End If

        Else
            Do
                For i = 1 To MONDAI - 1
                    If Rnd(0) = Rnd(i) Then
                        TOIC = RAN.Next(99)
                        FLAG = False
                        Exit For
                    Else
                        FLAG = True
                    End If
                Next
            Loop While FLAG = False
            Rnd(MONDAI) = Rnd(0)
        End If
        TOIC = Rnd(MONDAI)

    End Sub

これだと途中で無限ループになってしまったり、うまく重複チェックができていなかったりします。
どこが悪いのかを指摘していただけると嬉しいです。
よろしくお願い致します。


魔界の仮面弁士  2007-01-06 03:21:59  No: 134766

表記からして、VB6 や VB.NET 2003 では無さそうですね。
VB2005 か、VB.NET 2002 かな? 次回は開発環境も明記してくださいね。

とりあえず現行バージョン(2005)と仮定して回答します。

> Randomize()
> '乱数の発生
> Dim RAN As New Random

Randomize は、「Rnd関数」に影響を与えるものです。
Random クラスを使うときは不要ですよ。

> どこが悪いのかを指摘していただけると嬉しいです。

重複しないデータを作りたいときは、
  『トランプをシャッフルするときの手法』
を用いるか、
  『トランプから、数枚のカードを取り出す』
ときの手法を用います。

たとえば、こんな感じ。

Module Module1

    Sub Main()
        Dim numbers() As Integer = GetRandomNumbers(100)

        For n As Integer = LBound(numbers) To UBound(numbers)
            Console.WriteLine(String.Format("{0,3:G}番目={1,8:#,0}", n + 1, numbers(n)))
        Next
    End Sub

    Public Function GetRandomNumbers(ByVal Count As Short) As Integer()
        '取得したい値の最小値と最大値
        Dim MinValue As Integer = 0
        Dim MaxValue As Integer = 76543
        If (MaxValue - MinValue) < Count Then
            MinValue = MinValue + Count
        End If

        '連続した値を用意しておき…
        Dim numbers As New List(Of Integer)()
        For value As Integer = MinValue To MaxValue
            numbers.Add(value)
        Next

        'そこから、ランダムにCount個のデータを取り出す
        Dim r As New Random()
        Dim results As New List(Of Integer)()
        For n As Integer = 1 To Count
            Dim index As Integer = r.Next(0, numbers.Count - 1)

            '番号を取得し、それを一覧から取り除く
            Dim newValue As Integer = numbers(index)
            numbers.RemoveAt(index)

            results.Add(newValue)
        Next

        '取り出したデータを戻り値として返す
        Return results.ToArray()
    End Function

End Module


ichi  2007-01-06 10:04:55  No: 134767

魔界の仮面弁士さん、ありがとうございます!
わざわざ判りやすいプログラムまで書いてくださって、お手数お掛けしました。
開発環境は、VB.NET2005です。すみません(汗

> Randomize は、「Rnd関数」に影響を与えるものです。
> Random クラスを使うときは不要ですよ。

これは私は知りませんでした…ためになりました!
本当にありがとうございます!

これからもう一度プログラムを組み立てなおして見ます!


ichi  2007-01-06 10:54:00  No: 134768

すみません、このモジュールの処理を呼び出すにはどうすればいいでしょうか?
本で調べてみたのですが、あまりよく判らなくて…。
Subのような方法ではないのですよね?


特攻隊長まるるう  2007-01-09 23:39:38  No: 134769

> すみません、このモジュールの処理を呼び出すにはどうすればいいでしょうか?
…どこから呼び出すのですか?
魔界の仮面弁士 さんのサンプルコードは Sub Main 起動のものになっています。
Sub Main から GetRandomNumbers を呼び出せていますので、そのままです。
質問の意味が分かるような説明をお願いします。


ichi  2007-01-15 09:06:37  No: 134770

>特攻隊長まるるう様
すいません、勘違いしていました。
あとから調べてちゃんとモジュールの意味もわかりました。
お手数をお掛けしてすいませんでした(汗)


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加