ズンドコ節で遊ぶ
ズンドコ節で遊ぶ
ノンプロ研のSlackのチャンネルに「今週のお題」というやつがある。毎週一つ、ちょっとした「お題」(〈数字をローマ数字に変換する関数を作れ〉とかそういうやつ)がランダムに出される。
今回、
「ズン」と「ドコ」をランダムで出力し、「ズンズンズンズンドコ」という並びが完成したら「キ・ヨ・シ!」と出力するプログラムを書け
という「お題」が出された。
GASやPythonで回答している人はいたものの、VBAで回答した人はいなかったので、ちょっとやってみた。
「ズン」と「ドコ」をランダムで出力する
これは、単純にRnd
関数を使えばよいと考えた。
Rnd
関数は「0~1未満の数」をランダムに生成するらしいので、
Int(2 * Rnd)
で0
か1
かをランダムに取得することができる。
リスト1
Private Function genLyric() As String Dim ret As String ret = "ズン" Randomize Dim tmp As Long tmp = Int(2 * Rnd) If tmp = 1 Then ret = "ドコ" genLyric = ret End Function
このgenLyric
メソッドを呼べば、「ズン」か「ドコ」か、いづれかの文字列を取得することができる。
ズンドコ節を歌うクラスを作る
リスト1を用いれば、「ズン」か「ドコ」かのどちらかを歌わせることができる。
後は、歌い続ける中で「ズンズンズンズンドコ」の並びが完成したら「キ・ヨ・シ!」と歌わせるようにすればよい。
これは、要素数5
のQueueではないか!
ならば、クラスの内部に要素数5
のQueueを持たせて、歌うたびにそれをチェックすればよいではないか!
リスト2 クラスモジュール Zundoko
'### オブジェクト名は Zundoko ###' Option Explicit 'Field Variables' '……(1)' Private zundoko1 As String Private zundoko2 As String Private zundoko3 As String Private zundoko4 As String Private zundoko5 As String Private hasDone_ As Boolean 'Properties' '……(2)' Public Property Get HasDone() As Boolean HasDone = hasDone_ End Property Public Property Get Lyrics() As String Dim ret As String ret = zundoko1 ret = ret & zundoko2 ret = ret & zundoko3 ret = ret & zundoko4 ret = ret & zundoko5 Lyrics = ret End Property 'Constructor' Private Sub Class_Initialize() '……(3)' hasDone_ = False Dim n As Long n = 0 Do Until n = 5 Call Me.sing n = n + 1 Loop End Sub 'Methods' Public Sub sing() '……(4)' Dim tmp As String '……(5)' tmp = genLyric zundoko1 = zundoko2 '……(6)' zundoko2 = zundoko3 zundoko3 = zundoko4 zundoko4 = zundoko5 zundoko5 = tmp Debug.Print tmp '……(7)' If Me.Lyrics = "ズンズンズンズンドコ" Then '……(8)' hasDone_ = True Debug.Print "キ・ヨ・シ!" End If End Sub Public Sub resetZundoko() '……(9)' hasDone_ = False End Sub 'Internal Methods' 'リリック(笑)生成用メソッド' Private Function genLyric() As String Dim ret As String ret = "ズン" Randomize Dim tmp As Long tmp = Int(2 * Rnd) If tmp = 1 Then ret = "ドコ" genLyric = ret End Function
相変わらずのタテ長。
(1)の
Private zundoko1 As String Private zundoko2 As String Private zundoko3 As String Private zundoko4 As String Private zundoko5 As String Private hasDone_ As Boolean
はフィールド変数。
上の五つは直近五つのリリック(笑)を蓄えておく場所。
最後の一つ(hasDone_
)は、ズンドコ節が完成したかどうかを表すフラグ。「ズン、ズン、ズン、ズンドコ キ・ヨ・シ!」が完成したらTrue
になる。
(2)の
Public Property Get HasDone() As Boolean HasDone = hasDone_ End Property Public Property Get Lyrics() As String Dim ret As String ret = zundoko1 ret = ret & zundoko2 ret = ret & zundoko3 ret = ret & zundoko4 ret = ret & zundoko5 Lyrics = ret End Property
はプロパティ。プロパティは二つ。
HasDone
はズンドコ節が完成したかどうかをこのクラスの利用者に知らせるもの。
もう一つのLyrics
プロパティは、直近五つのリリック(笑)をつなぎ合わせた文字列を返す。
(3)の
Private Sub Class_Initialize() hasDone_ = False Dim n As Long n = 0 Do Until n = 5 Call Me.sing n = n + 1 Loop End Sub
はコンストラクタ。
hasDone_
を明示的にFalse
にする他、この段階で五つのリリック(笑)を満たしておく。
リリック(笑)を取得するためのsing
メソッドについては後述。
(4)の
Public Sub sing() Dim tmp As String '……(5)' tmp = genLyric zundoko1 = zundoko2 '……(6)' zundoko2 = zundoko3 zundoko3 = zundoko4 zundoko4 = zundoko5 zundoko5 = tmp Debug.Print tmp '……(7)' If Me.Lyrics = "ズンズンズンズンドコ" Then '……(8)' hasDone_ = True Debug.Print "キ・ヨ・シ!" End If End Sub
がリリック(笑)を取得して歌うsing
メソッド。
まず(5)の
Dim tmp As String tmp = genLyric
で変数tmp
を用意。
リスト1のgenLyric
で「ズン」か「ドコ」かを取得して変数tmp
に突っ込む。
次に(6)の
zundoko1 = zundoko2 zundoko2 = zundoko3 zundoko3 = zundoko4 zundoko4 = zundoko5 zundoko5 = tmp
で、変数zundoko2
~同5
に入っている文字列をそれぞれzundoko1
~同4
にずらして入れる。
最後にzundoko5
に先ほど取得したtmp
を突っ込む。
これで、あたかも要素数五つのQueueに新たに一つの要素を追加(して先頭の要素を消去)したかのような動作になる。
ここで(7)の
Debug.Print tmp
で新たに取得したリリック(笑)をイミディエイトに出力。
そうして今度は(8)の
If Me.Lyrics = "ズンズンズンズンドコ" Then hasDone_ = True Debug.Print "キ・ヨ・シ!" End If
で直近五つのリリック(笑)を調べる。
直近五つのリリック(笑)、すなわちLyrics
プロパティの値がズンズンズンズンドコ
になっていたら条件成立なので、
hasDone_ = True Debug.Print "キ・ヨ・シ!"
を実行。
hasDone_
をTrue
にし、イミディエイトに「キ・ヨ・シ!」を出力する。
「ズン」とか「ドコ」は1行づつイミディエイトに表示されるので、条件が成立した場合は、イミディエイトに
ズン ズン ズン ズン ドコ キ・ヨ・シ!
と表示されることになる。
最後の「ズン」と「ドコ」はⅠ行で表示した方が雰囲気は出るんですけどね……。
最後、(9)の
Public Sub resetZundoko() '……(9)' hasDone_ = False End Sub
は、HasDone
プロパティをFalse
にするためのもの。ただそれだけ。
使ってみる
次のコードで実験。
リスト3
Private Sub testZundoko() Dim zd As Zundoko Set zd = New Zundoko Dim n As Long n = 1 Do Until zd.HasDone Call zd.sing n = n + 1 If n > 100 Then Debug.Print "タイムオーバー! 残念!" Exit Sub End If DoEvents Loop Debug.Print n & " 回で達成!" End Sub
見ての通り、条件が成立するまでsing
メソッドを実行し続ける。
最後に何回目で「ズンズンズンズンドコキ・ヨ・シ!」が完成したかを表示するようにした。なお、「ズンズンズンズンドコ」が完成しない限り、延々sing
メソッドを実行し続けるので、100回で一旦やめるようにした。
実行すると、
こんな感じ。
おわりに
頭の体操です。
もっとスマートなやり方がありそうですね。