6つの番号が全て違う番号で出る乱数にするには?

解決


VB  2006-08-05 18:42:29  No: 132666

ボタンを押すと、Label1〜6に6つの番号が出るようにしたいのです。
それぞれ異なった番号で、一度に重複番号が出ないようにしたいのです。
ロト6みたいに、1〜43の番号を6つランダムに出したいというわけです。こうゆう時はどうすればいいんでしょうか?

    Private Sub Button1_Click(略) Handles Button1.Click

        Dim L1, L2, L3, L4, L5, L6 As Integer
        Randomize()
        L1 = Int(Rnd(1) * 43 + 1)
        L2 = Int(Rnd(1) * 43 + 1)
        L3 = Int(Rnd(1) * 43 + 1)
        L4 = Int(Rnd(1) * 43 + 1)
        L5 = Int(Rnd(1) * 43 + 1)
        L6 = Int(Rnd(1) * 43 + 1)
        La1.Text = L1
        La2.Text = L2
        La3.Text = L3
        La4.Text = L4
        La5.Text = L5
        La6.Text = L6

    End Sub

このような感じだと同じ番号が出てしまいます。


VB  2006-08-05 18:46:37  No: 132667

あと、小さい番号順に並べたいんです。

「26 14 16 4 43 2」とあったら「2 4 14 16 26 43」と。


ガッ  2006-08-05 18:54:17  No: 132668

・重複番号が出ないようにしたい
  案1  トランプのシャッフルの要領で考えてください
  案2  同じ値が出たらまた乱数を発生させるようにする
どちらの案も「出た値を保存しておく」ことはかわりません

・小さい番号順に並べたい
  案1  ソート法を調べてください


VB  2006-08-05 19:46:06  No: 132669

過去ログを検索してみてやってみましたが
今の所はこんな感じで大丈夫だと思います。

im L1, L2, L3, L4, L5, L6 As Integer
        Randomize()

        Do Until L1 <> L2 And L1 <> L3 And L1 <> L4 And L1 <> L5 And L1 <> L6 _
        And L2 <> L3 And L2 <> L4 And L2 <> L5 And L2 <> L6 _
        And L3 <> L4 And L3 <> L5 And L3 <> L6 _
        And L4 <> L5 And L4 <> L6 _
        And L5 <> L6

            L1 = Int(Rnd(1) * 43 + 1)
            L2 = Int(Rnd(1) * 43 + 1)
            L3 = Int(Rnd(1) * 43 + 1)
            L4 = Int(Rnd(1) * 43 + 1)
            L5 = Int(Rnd(1) * 43 + 1)
            L6 = Int(Rnd(1) * 43 + 1)
            Te1.Text = L1
            Te2.Text = L2
            Te3.Text = L3
            Te4.Text = L4
            Te5.Text = L5
            Te6.Text = L6
        Loop


ガッ  2006-08-05 23:55:54  No: 132670

※考えてみたら「出た値を保存しておく」は素直に納得できない部分かもしれませんね。

> 今の所はこんな感じで大丈夫だと思います。
多少冗長ですが、まぁいいのではないかと。


Sinya  2006-08-06 01:32:44  No: 132671

ちょっと話がずれますが
Dim L1, L2, L3, L4, L5, L6 As Integer
は、
L6 は、integerですが
後は、Variantです。

Sub test()

    Dim L1, L2, L3, L4, L5, L6 As Integer

    L1 = "タタタ"  '<----モンダイナシ Variant
    L6 = 123
    L6 = "アアア" '<---- エラー

End Sub


  2006-08-06 01:46:25  No: 132672

こんにちは良です。
VB.NET2003
でやってみたのですが
こんなのはどうでしょう?
もっとコードを簡単にできそうなんですが。

 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim L(5) As Integer
        Dim shtCnt As Short

        Randomize()

        Do Until L(0) <> L(1) And L(0) <> L(2) And L(0) <> L(3) And L(0) <> L(4) And L(0) <> L(5) _
        And L(1) <> L(2) And L(1) <> L(3) And L(1) <> L(4) And L(1) <> L(5) _
        And L(2) <> L(3) And L(2) <> L(4) And L(2) <> L(5) _
        And L(3) <> L(4) And L(3) <> L(5) _
        And L(4) <> L(5)
            For shtCnt = 1 To 6
                L(shtCnt - 1) = CInt(Rnd(1) * 43 + 1)
            Next

        Loop
        Array.Sort(L)
        Me.TextBox1.Text = L(0)
        Me.TextBox2.Text = L(1)
        Me.TextBox3.Text = L(2)
        Me.TextBox4.Text = L(3)
        Me.TextBox5.Text = L(4)
        Me.TextBox6.Text = L(5)

    End Sub


  2006-08-06 01:51:01  No: 132673

あ!インデントがめちゃくちゃだ。適当にインデントをつけてください。


  2006-08-06 01:59:59  No: 132674

やっぱりインデントそんなにめちゃくちゃではないかも。
VB.NET2003
はオートインデントなので・・


ガッ  2006-08-06 03:52:57  No: 132675

Sinyaさん
> Dim L1, L2, L3, L4, L5, L6 As Integer
> は、
> L6 は、integerですが
> 後は、Variantです。
そうですか?
見た目.NETっぽいので、違うかもしれませんよ?

良さん
> もっとコードを簡単にできそうなんですが。
っ[ せっかく配列を使っているのならば… ]
という感じですか

/*
今回は次のような段階を踏むプログラムを作ればいいのではないかと思います
1  1〜43までの整数値の中で重複しない乱数を6個発生させる
    =シャッフル
2  6個の乱数を昇順で取り出せるようにインデックスを改変させる
    =ソート

なので、次のようにしてみました。
(VB6)

Private Sub Form_Load()
    Dim v           As Variant
    Dim p()         As Integer
    
    Randomize
    
    p = GetRandoms(1, 49, 6)
    For Each v In p
        Debug.Print v;
    Next
    Debug.Print
    
    Call Sort(p)
    For Each v In p
        Debug.Print v;
    Next
    Debug.Print
    
End Sub

Function GetRandoms(ByVal min As Integer, ByVal max As Integer, ByVal cnt As Integer) As Integer()
    'min〜maxの範囲に在る整数を、ランダムのcnt個拾った配列を返す
    
    Const sflcnt    As Integer = 10240
    Dim i           As Integer
    Dim tmp         As Integer
    Dim p1          As Integer
    Dim p2          As Integer
    Dim dom()       As Integer
    Dim ret()       As Integer
    
    '引数チェック
    If max < min Then
        '乱数の値域が不正
        'どうするかは VB さんの思うとおり
        Err.Raise "乱数の範囲が不正です"
    ElseIf max - min + 1 < cnt Then
        '乱数の値域よりも、取りうる数が多いので必ず重複が起こる
        'どうするかは VB さんの思うとおり
        Err.Raise vbObjectError, , "乱数の範囲以上の大きさの戻り値が必要です"
    End If
    
    '配列を作る
    ReDim dom(min To max)
    ReDim ret(1 To cnt)
    
    'domを作り、シャッフルする
    For i = min To max
        dom(i) = i
    Next
    For i = 1 To sflcnt
        p1 = Int((max - min + 1) * Rnd + min)
        p2 = Int((max - min + 1) * Rnd + min)
        tmp = dom(p1)
        dom(p1) = dom(p2)
        dom(p2) = tmp
    Next
    
    'retに、シャッフルした配列の先頭cnt個を入れる
    For i = 1 To cnt
        ret(i) = dom(LBound(dom) + (i - 1))
    Next
    
    '戻り値を設定して戻る
    GetRandoms = ret
    
End Function

Sub Sort(ByRef data() As Integer)
    'ソートする(comb-sort)
    '参考:http://www2.moug.net/bbs/exvba/20060430000011.htm
    Dim dataL        As Integer
    Dim dataU        As Integer
    Dim i            As Integer
    Dim gap          As Integer
    Dim tmp          As Integer
    Dim flg          As Boolean
    
    dataL = LBound(data)
    dataU = UBound(data)
    gap = dataU - dataL
    
    flg = True
    Do While gap > 1 Or flg
        gap = Int(gap / 1.3)
        Select Case gap
            Case 9, 10
                gap = 11
            Case Is < 1
                gap = 1
        End Select
        
        flg = False
        For i = dataL To dataU - gap
            If data(i) > data(i + gap) Then
                tmp = data(i)
                data(i) = data(i + gap)
                data(i + gap) = tmp
                flg = True
            End If
        Next
    Loop
   
End Sub
*/

以上駄文失礼//


通ってみた  2006-08-06 06:36:12  No: 132676

VB6.0ですが、こんな感じ?

Dim r(43) As Long
Dim Shuffle1 As Long
Dim Shuffle2 As Long
Dim hozon As Long
Dim i As Long

For i = 1 To 43
    r(i) = i
Next

For i = 1 To 100
    Shuffle1 = Rnd(1) * 43 + 1
    Shuffle2 = Rnd(1) * 43 + 1

    hozon = r(Shuffle1)
    r(Shuffle1) = r(Shuffle2)
    r(Shuffle2) = hozon
Next

あとはr(1)〜r(6)の6コを抜き出せばランダムになっています
別にr(1)からにこだわる必要もないですが

ソートに関しては、ListBox辺りに丸投げするとか  (爆)


通ってみた  2006-08-06 06:37:47  No: 132677

よく見たらガッさんの内容とほぼ同じでしたね・・・orz


sinya  2006-08-07 07:46:09  No: 132678

ガッさん
>そうですか?
>見た目.NETっぽいので、違うかもしれませんよ?

Private Sub Button1_Click(略) Handles Button1.Click

そうみたいですね
失礼しました。

ところで、ArrayListを使ったらどうですかね。
ソートも簡単ですし。


  2006-08-08 02:50:51  No: 132679

ここにもいいソートのサンプルプログラムありましたよ。
VB6.0ではソートするメソッドってないんですね・・・

<VB6.0>
http://www.geocities.co.jp/SilkRoad/4511/vb/sort.htm


MenPin  2006-08-14 11:15:44  No: 132680

シャッフルする方法ではなくて、純粋に箱から選んだ数字が無くなっていく方法で作ってみました。ソートはバブルソートにしましたが、クイックソートとかの方が速いかもしれません。(そんなに変わらないと思いますが・・・

Public Class LotoX

    Private NumMax As Integer           'いくつの数字までから選び出すか
    Private NumSelect As Integer        '選び出す個数
    Private Result(0) As Integer         '結果の数字を格納する配列

    'プロパティーの設定
    '設定のみできる
    Public WriteOnly Property prpNumMax() As Integer
        Set(ByVal Value As Integer)
            NumMax = Value
        End Set
    End Property
    Public WriteOnly Property prpNumSelect() As Integer
        Set(ByVal Value As Integer)
            NumSelect = Value
        End Set
    End Property
    '参照のみできる
    Public ReadOnly Property prpResult() As Integer()
        Get
            Return Result
        End Get
    End Property

    '計算を実行する
    Public Sub Execute()

        '最大数や選び出す数が適切でない場合エラーとして0を返す
        If NumSelect > NumMax Or NumSelect < 1 Or NumMax < 1 Then
            Result(0) = 0
            Exit Sub
        End If

        '数を選び出し結果を配列に格納する
        Call SelectNum()

        '結果を昇順に並べ替える
        Call SortResult()

    End Sub

    '数を選び出し結果を配列に格納する
    Private Sub SelectNum()

        Dim Box() As Integer        '選び出す為の数字を入れておく箱
        Dim NumBoxIndex As Integer  '何番目の箱から取り出すか
        Dim NumBoxRest As Integer   '箱の中にあと何個数字が入っているか
        Dim I, J As Integer

        '箱に数字を入れる
        ReDim Box(NumMax - 1)
        For I = 0 To NumMax - 1
            Box(I) = I + 1
        Next

        '結果の配列を用意する
        ReDim Result(NumSelect - 1)
        '乱数の初期化
        Randomize()

        '数を選び出す
        For I = 0 To NumSelect - 1
            '箱の残り数を求める
            NumBoxRest = NumMax - I
            '何番目の箱から選ぶか決める
            NumBoxIndex = Int(Rnd() * NumBoxRest)
            '選んだ番号の箱から数字を結果に取り出す
            Result(I) = Box(NumBoxIndex)
            '箱から選んだ数字を削除する
            For J = NumBoxIndex To NumBoxRest - 2
                Box(J) = Box(J + 1)
            Next
            ReDim Preserve Box(NumBoxRest - 2)
        Next

    End Sub

    '結果を昇順に並べ替える
    Private Sub SortResult()

        Dim Buff As Integer
        Dim I, J As Integer

        I = NumSelect - 2
        Do While I >= 0
            For J = 0 To I
                If Result(J) > Result(J + 1) Then
                    Buff = Result(J)
                    Result(J) = Result(J + 1)
                    Result(J + 1) = Buff
                End If
            Next
            I -= 1
        Loop

    End Sub

End Class


MenPin  2006-08-14 11:28:03  No: 132681

ついでにイベントプロシージャも載せときますね

    Private Sub btnExecute_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExecute.Click

        Dim insLotoX As New LotoX()
        Dim NumMax As Integer
        Dim NumSelect As Integer
        Dim Buff As String
        Dim I As Integer

        '数値が入力されているか調べる
        If (Not IsNumeric(txtNumMax.Text)) Or (Not IsNumeric(txtNumSelect.Text)) Then
            txtResult.Text = "数値を入力してください"
            Exit Sub
        End If

        '少数が入力されていたら整数に変換する
        NumMax = CInt(txtNumMax.Text)
        NumSelect = CInt(txtNumSelect.Text)
        txtNumMax.Text = CStr(NumMax)
        txtNumSelect.Text = CStr(NumSelect)

        '数値を設定して実行する
        insLotoX.prpNumMax = NumMax
        insLotoX.prpNumSelect = NumSelect
        insLotoX.Execute()

        'エラーの場合
        If insLotoX.prpResult(0) = 0 Then
            txtResult.Text = "数値が正しくありません"
            Exit Sub
        End If

        '結果の出力
        Buff = ""
        For I = 0 To NumSelect - 1
            Buff = Buff & insLotoX.prpResult(I) & " "
        Next
        txtResult.Text = Buff

    End Sub


VB  2006-10-29 22:37:38  No: 132682

解決です。


VB  2006-10-29 22:37:38  No: 132683

解決です。


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




  


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