派遣事務員の迷走

派遣事務員コロ子。会社の犬。顔出しNG。常に迷走している。

マンゴー杯!

こんにちは。
派犬事務員のコロ子です。

マンゴー杯 結果報告

前回、あみだくじや抽選のコードを「自分ならこう書く!」を募集したところ、素晴らしいアイディアの応募がありました!どうもありがとうございます!!
みんな演出が凝っていて高度な技が満載!

エントリーNo.1

セラエノ (id:celaeno42)さん
celaeno42.hatenablog.com

エントリーNo.2

id:Infomentさん
infoment.hatenablog.com

さらに進化版。あみだくじの格子部分もマクロで作る↓
infoment.hatenablog.com

infoment.hatenablog.com

すごい!!!
あみだくじの完成形。必見↓

infoment.hatenablog.com

あみだくじファイナル↓
infoment.hatenablog.com


エントリーNo.3

Kou (id:ExcelLover)さん
www.excellovers.com

エントリーNo.4

コロ子
ちょっとみんな凄すぎて実力の差がありすぎる・・・。
こうなったらコロ子が絶対当たるマクロを作ろう。

【コロ子が絶対当たる抽選】
マンゴーの数を入力して「抽選」ボタンを押すと、「当たり」「はずれ」が表示される。コロ子は絶対「当たり」が出る。
f:id:SNegishi:20190804231401p:plain


【考え方】
①「当たり・はずれの要素」「乱数を入れる要素」を加者数-1(コロ子を抜かす)の要素数の2次元配列を用意する。
②「当たり・はずれの要素」の先頭から、マンゴーの数-1個の当たり、後ははずれを入れる。
③「乱数を入れる要素」に整数1~参加者数を重複しないでランダムに入れる。

例:マンゴーの数3個、コロ子以外の参加者7人の場合の配列のイメージ

f:id:SNegishi:20190804215251p:plain
配列のイメージ

④「乱数を入れる要素」で昇順にソートする。

⑤結果セルに「乱数を入れる要素」を順に入れていく。
このとき参加者が「コロ子」だったら当たりを入れスキップし、次のセルへ。

【コード】
抽選ボタン

Sub Absolutely_win()

Dim i As Long, j As Long
Dim StartCell As Long
Dim Cellcount As Long
Dim Arr() As Variant

Application.ScreenUpdating = False

StartCell = 5
Cellcount = Cells(Rows.Count, 1).End(xlUp).Row - StartCell

ReDim Arr(1 To Cellcount, 1)

For i = 1 To Cellcount

    If i < Range("B2").Value Then
        Arr(i, 0) = "当たり"
    Else
        Arr(i, 0) = "はずれ"
    End If

    Dim Flg() As Boolean
    ReDim Flg(1 To Cellcount)
    Dim Num As Long
    
    '整数1~参加者数を重複しないでランダムに発生させる
    Randomize
    Do
        Num = Int((Cellcount - 1 + 1) * Rnd + 1)
    Loop Until Flg(Num) = False
    Arr(i, 1) = Num
    Flg(Num) = True
    
Next i

'ソート
Call ArrSort(Arr)

'セルに配列を入れる(コロ子の時は当たりを入れる)
For i = 1 To Cellcount

    Cells(StartCell, 2).Value = Arr(i, 0)
    
    If Cells(StartCell, 1).Value = "コロ子" Then  
        Cells(StartCell, 2).Value = "当たり"
        i = i - 1
    End If

    StartCell = StartCell + 1
    
Next i

Application.ScreenUpdating = True

End Sub

※範囲を指定して乱数を発生させる
乱数=Int((最大値 - 最小値 +1 ) * Rnd + 最小値)


配列をソートする

Sub ArrSort(Arr As Variant)

Dim bufL As Long
Dim bufS As String
Dim i As Double
Dim j As Double

For i = UBound(Arr, 1) To LBound(Arr, 1) Step -1

    For j = LBound(Arr, 1) To i - 1
    
        If Arr(j, 1) > Arr(j + 1, 1) Then
        
                bufS = Arr(j, 0)
                bufL = Arr(j, 1)
                
                Arr(j, 0) = Arr(j + 1, 0)
                Arr(j, 1) = Arr(j + 1, 1)
                
                Arr(j + 1, 0) = bufS
                Arr(j + 1, 1) = bufL
                                
        End If
        
    Next j
    
Next i

やったー!コロ子マンゴー当たったー!!
セコイ!!
こーゆー不正はダメですよ!



【今回のポイント】
整数1~参加者数を重複しないでランダムに発生させる

For i = 1 To Cellcount
・
・
・
    Dim Flg() As Boolean
    ReDim Flg(1 To Cellcount)
    Dim Num As Long

    Randomize
    Do
        Num = Int((Cellcount - 1 + 1) * Rnd + 1)
    Loop Until Flg(Num) = False

    Arr(i, 1) = Num
    Flg(Num) = True

Next i

Boolean型の初期値はFalse

範囲を指定して乱数を発生させてみたら、意外と多く重複していた。
重複しないように作ろうとしたところ、なかなか上手かず、ネットで調べたら
Boolean型の配列を使うというのがあった。
最初Do~Loopのところだけを見て?って思ったけど、その下の
Arr(i, 1) = Num
Flg(Num) = True
を見て納得!Boolean型の初期値はFalse。Numを配列に格納したらFlgの要素数Num番目をTrueにすれば、ループでフラグの要素数Num番目がTrueだったら重複しているので、重複しなくなるまで乱数を発生させる。
こんなフラグの使い方あるんだ!

参考サイト
www.moug.net