satoの雑技術ノート

エクセルVBAで1~25までの数字をランダムに発生させる処理を考えてみました

25マスの手書きビンゴをもう浴びるほどやり狂いたい!

きっかけはもうこの一点だけ、でした。25ビンゴは、縦5マス、横5マスに1から25までの数字を適当に書いた紙をそれぞれ用意し、数字を交互に言い合いながらビンゴ(縦列・横列・ナナメ列)を完成させるゲームです。

25ビンゴイメージ

小学生になった長男とこのゲームをたまにやるんですけど、いちいちエンピツで紙にマス書いて、ランダムに数字を書いて、なんてしていると非常に面倒ですし「せっかく熱くなってきたゲームがいちいち中断されて冷や冷やしてしまう感」がどうしてもあるので、どうせならエクセルで一気に作れないだろうか、と思いついた次第です。
スポンサーリンク

エクセルVBAで1~25までの数字をランダムに発生させる処理を考えてみた

25ビンゴのルールに関しては人や地域によって様々みたいなので、あくまでも個人的なアレですけど、代表的なものをふたつ紹介します。

25ビンゴルール

細かいアレはあるかもしれませんが、大きく分けると25ビンゴには2つの方式があります。

ビンゴルール1

自分が言った数字にバツ、相手が言った数字にマルをつけて、マルで1列ビンゴをつくる。
詳しい説明はコチラにあります

ゲームの特徴
相手が言った数字でビンゴを作るので、ビンゴ特有のドキドキ感が演出されます。さらに、自分がバツをつける位置も考えなくてはならないので、より戦略的、知的な戦いになります。

ビンゴルール2

自分が言った数字と相手が言った数字、両方マルをつけて、マルで数列(2列~5列くらい)ビンゴをつくる。

ゲームの特徴
自分が言う数字でもビンゴが作れるので特に何も考えずにビンゴが楽しめます。あまり深くまで考えられない子供向き、といった感じです。

完成イメージ A4版

完成イメージは以下のような感じです。
完成イメージ(25ビンゴシート)

実際のエクセル上にはボタンが配置されてあり、そのボタンをポチポチ押すたびにマスの数字がランダムで入れ替わるという仕様になってます。マクロのセキュリティでマクロを有効にしてお使いください。

ひとり1枚で15回の対戦が楽しめるので、もう嫌になるほど対戦が楽しめます。完成したシートを使ってみたいという方は以下のリンクからダウンロードできますので使ってみてください。

25ビンゴシート ダウンロード(ファイル名 25_bingo.xls)

(Excel 2003,2007,2010,2013 で動作を確認)

1~25の数字をランダムに発生させるマクロについて

ネットでちょっと調べてみると、別シート上で関数を使って乱数を発生させて、それに順位をつけて、みたいなやり方が一例として紹介されていました。

場合によりけり、かもしれませんが、個人的には別シートを使うやり方はどうもスマートではない気がします。VBAで書けば小難しい処理部分はすべて裏に隠し、ボタンひとつで表現できるので今回はこちらの方法でやることにします。

マクロに必要と思われる処理は主に以下の2点です。

  1. 1~25までのランダムな数字を自動で発生させる
  2. 1~25までの数字で同じ数字が出てはいけない

ランダムな数字の自動生成は単純ですが、問題は2の同じ数字が出ない、という点です。ここに悩まされましたが、ネットで調べながらあれこれ試行錯誤してみた結果、ブーリアン型を使ったフラグを使って実装する方法でうまくいきました。1から25までのフラグ用の配列を用意し、一度使われた数字かどうかをTrueとFalseで判断します。

以下は実際に作成した1から25までの数字をランダムに発生させるマクロです。

[vb]
Sub random25()
Const MIN =1
Const MAX =25
Dim num As Integer
Dim a_num(MIN To MAX) As Integer
Dim flag(MIN To MAX) As Boolean
Dim cnt As Integer

‘乱数の初期化
Randomize

For cnt = MIN To MAX
Do
num = Int(MAX * Rnd + 1)
Loop While flag(num)

a_num(cnt) = num
flag(num) = True
Next cnt
End Sub
[/vb]

マクロの解説的なもの

  1. まず最終的に25コの数字が必要になることからFor文を使用して25回繰り返しを宣言します。
  2. 次に変数numにランダムに発生させた1~25までの数字を格納し、flagの確認をしています。Do~Loop Whileはflag(num)がFalseを引くまで(まだ出ていない数字が出るまで)延々と処理を繰り返します。(ブーリアン型の宣言時の初期値はFalseです)
  3. ループを抜けると、その時の数字numを1~25までの配列であるa_num()へと格納し、numに対応するflag(num)をTrueに変えます。これで次の回のループ(2の処理)でこの数字が呼ばれても無視されることになります。
  4. For文が全て終わった時には、a_num(1)からa_num(25)には重複しないランダムな1~25までの数字が格納されていることになります。あとは25個の数字を順番にマス目に配置していくような処理を別で書いて連携させれば完成です。
モバイルバージョンを終了