この記事で扱っていること
- LabVIEWでビンゴゲームを作る方法
を紹介しています。
注意:すべてのエラーを確認しているわけではないので、記事の内容を実装する際には自己責任でお願いします。また、エラー配線は適当な部分があるので適宜修正してください。
この記事が出ているのは年の瀬なので、クリスマスや忘年会などのイベントで、ビンゴを行う機会がある方もいるかなと思います。
と、いうわけで、LabVIEWでビンゴゲームを作る方法の例について紹介します。
「ビンゴ大会の幹事頼まれたけれどビンゴの番号を出す機械用意するの忘れていた!」そんなときにはLabVIEWでさくっと作ってみてはいかがでしょうか?
(半分お遊びの記事ですが、プログラムはちゃんとビンゴゲームとして動きます)
なお、この記事で紹介しているプログラムは、もっと見やすい形で書けるようなアーキテクチャでも書けると思います。が、あえて単純なステートマシンだけで実装するように考えてみました。
なので、ステートマシンの知識を持っている方であれば書けるような内容となっています。
どんな結果になるか
ゲームの状態は2Dピクチャ上に表示しています。
操作はシンプルに、「開始およびリセットを行うためのボタン」、「次の出目を選ぶボタン」、「プログラムを終了するためのボタン」の3つだけとしています。
プログラムを開始するとタイトル画面が表示されるので、次の出目の番号を選ぶためにボタンを押すと、抽選が始まります(下の図では静止画ですが、抽選時に番号が最初素早く、だんだんゆっくり変化し、最終的に出目が決まります)。
これまでに出た出目はピクチャ上に表示されるので、実際のビンゴ大会でもこれで安心ですね。
プログラムの構造
初心者の方にとっつきやすいプログラムとするため、今回は単純なステートマシンとしています。
が、画面表示を頻繁に切り替えるための工夫を行っています。
まずは各ステートをそれぞれ紹介します。
initステートでは、このプログラムで使う様々なパラメタを初期化しています。
普通のステートマシンと異なるところがあるとすれば、ある特定のステート(update picture)の次のステートを指定するための列挙体があるという点かなと思います。(下の図の、下から2つめの列挙体)
そのupdate pictureのケースを次に紹介します。
このステートは、2Dピクチャに新しい情報(今回のプログラムではテキスト情報だけですが)を表示するための機能を持っています。
このステートは、他の様々なステートの後に実行されることになります。
例えば、ステートAが他の複数の別のステートであるステートBやステートCの後に実行される場合、ステートBやステートCからはステートAを実行すればいいのですが、その後、ステートBとしてはステートDへ、ステートCとしてはステートEへ移ってほしい場合、「ステートAの次」をあらかじめステートBやCから指定しておく必要があります。
本来このような「特定の順番」が決まっているようなプログラムであれば、キューを使用したプログラムが楽です。あるいは列挙体の配列を使用したプログラムも考えらえます。
ただこれらはそれなりにLabVIEWの経験がないと難しいので今回は採用しないことにしました(興味がある方は腕試しに挑戦してみてください)。
代わりの機能として「state after update picture」を用意しています。
2Dピクチャへの描画は「ポイントにテキスト描画」関数を使用します。
なお、このステートの中には待機関数があり、その待機関数へ与える値は配列から指標配列で指定した指標番号の値としています。
こうすることで、このupdate pictureステートが続く時間、言いかえれば、他のステートに移るまでの時間を他のステートからコントロールすることができます。
下の図に配列の例を出しています。この配列と同じにすると、良い感じにビンゴの番号の抽選感が出ると思います。
今の段階で、update pictureにあるサブVIである「bingo_result_update.vi」の中身について紹介しておきます。
このサブVIでは、これまで出目として表示されてきた番号の履歴(hit numbersの配列)の情報を元に、それらの番号をキレイに整列して表示させる機能を持っています。
これまでの出目として表示する番号の間隔は横方向にはx座標に40を足す、ピクチャ表示器上の端にきたら(今回は1行に15個の番号を表示すると想定)、y方向に30ずらして次の行のまた左端から表示するようにしています。
なお、1桁の番号の表示は、さらにx軸方向の表示位置をずらして、整列したときに「右寄り」に並ぶように調整を加えています(2つめのケースストラクチャ)。
各ケースストラクチャの中身は以下の図を参考にしてみてください。
なお、「ポイントにテキスト描画」関数に対するフォントの情報は適宜調整してください(サイズとか)。
上で紹介していた例では、明示されていない限りフォントサイズは「24」としています。
では、他のステートの紹介に移ります。次はeventステートです。
今回のプログラムは3つしかボタンがないためイベントも3つだけです。
基本的にどれかのイベントが起こり別のステートに移ってもまたこのeventケースに戻ってくるので、3つのボタンの無効プロパティに全てEnableを入れています。
ただし、番号が全て出そろった状態では、それ以上「次の番号」がないので、その時には「次の番号を選ぶ」の無効プロパティがEnableにならないようにします。
start bingoステートでは、ビンゴの抽選の準備をします。
まだ出ていない出目の番号の配列を1D配列シャッフルの関数で入れ替えておきます。
また、timer counterについても初期化しておき、ボタンが押せないように無効プロパティの設定もしておきます。
select numberステートでは、表示する番号を選択します。
ここで選ばれた番号を表示するので、このステートの後にはupdate pictureを指定するのですが、このselect numberステートが24回行われた際に選ばれた数を、いわゆる「出目」としています。
それまでの23回分は、画面に表示こそすれど、出目としてではなく、抽選時のドキドキ感を演出するためのいわばダミーの番号の選択、としています。
なので、24回目かそれ以外かで画面に表示する文字が異なるのでケースストラクチャで場合分けをしています。
update resultステートは、出目が確定してから、何か必要な処理を行う際に使用します。
これについては、機能の拡張性を持たせるために用意しているステートで、今回は何もしません。
が、記事後半で紹介するプログラムで使用します。
あとはfinishステートでWhileループを止めます。
途中でうっかりゲームを開始または終了してしまった場合への対処
上で紹介したプログラム、実際にちゃんと動くのですが、もしゲームの途中で、意図せず「開始/リセット」のボタンあるいはプログラム終了のボタンを押してしまうと、それまでの出目がリセットされ始めからやり直し、になります。
ビンゴゲームでこの状況になってしまうのはかなり不便ですね。
この問題を回避する方法として、もし万が一リセットや終了をしても、前の最後の状態から再開できるようにプログラムに機能を追加していきます。
具体的には、出目の情報をファイル出力するようにしています。
そのため、「出目をファイルに保存する機能」と、「続きから再開する機能」を用意します。
前者はファイル保存のプログラムを既存のステートに何か所か追加し、後者は一つステートを丸々追加します。(タイプ定義した列挙体であればこういった機能の追加もやりやすいですしね)
以下では、上で紹介したプログラムと違っているステートのみ紹介します。
まずはinitステートです。「ファイルがあるかどうか」を確認するサブVIを用意し、その結果次第で、「続きから再開するかどうか」を判定させるようにしています。
check_record.viのサブVIの中身は以下の通りです。
出目の履歴を保存したファイルがそもそも存在するかどうかを確認し、あった場合にはその中身を調べ、記録されている出目の数が全番号よりも少ない場合にはダイアログを出すようにしています。
ファイルの保存先は別にどこでもいいですしファイル名もなんでもいいのですが、以降で紹介する「ファイル保存」のプログラムも全て同じファイルパスを指定する必要があることに注意してください。
event、start bingo、select numberについては変化点はありません。
update resultステートについて、ここで出目の保存を行っています。
update resultステートが実行されるたびにファイルを開いて閉じてとしていますが、これは突然プログラムがフリーズするなど意図したタイミングでプログラムを終了できない場合でもファイルにはしっかり履歴を残しておくためにこうしています。
ファイル位置を設定の関数は、これを使用して「end」を指定しないと履歴データがちゃんと全部書き加えられなくなるので入れています。
fnishステートでは、もし全てのビンゴの出目がで揃ったら、ファイルを削除するようにしています。
全てで揃ったら「続きから再開」する必要はないですしね。
新たに用意したrestoreステートでは、ファイルの中身を読みだして、remain numbersとhit numbersの配列の情報を更新して「前回の続き」の状態としています。
見た目は一見複雑そうに見えるかもしれませんがやっていることは単純で、このステートの後は、通常の出目が決定した時のupdate result同様、update pictureとその後にeventステートに移るように指定します。
本記事では、ビンゴゲームを作る方法を紹介しました。
LabVIEWは本来ハードウェア操作やテストを行う場面が得意なプログラミング言語ですが、やろうと思えばこのようなゲームも作れるので、皆さんもぜひ挑戦してみてください。
ここまで読んでいただきありがとうございました。
コメント