Contents
段階的に作る
マクロを作る時、張りきって一気に作り切ってしまう必要はありません。
やりたい事が頭の中でまとまっていれば、部分ごとに作っていけば良いのです。
まとまった時間もとれませんしね。
そこで、ここでは数当てゲームを作ってみましょう。一気に紹介するような事はせずに段階的に見せていきます。
まあ、まだできていないんですけどね。(時間がとれないんですよ)
でも大丈夫です。冒頭で書いたように部分的に進めていきます。やりたい事はまとまっていますから。
今回のマクロ(数当てゲーム)
御存じの方も多いと思いますが、簡単に説明します。
4桁の数字を当てるゲームです。
4桁の数字を答えると、正解と同じ桁にある数(Hit)と、桁は異なるけど正解に含まれる数(Blow)をヒントに正解を探っていくゲームです。
例えば、正解が1234だとします。で、1436と答えると、Hit=2,Blow=1というヒントが得られます。Hitは1,3、Blowは4のことですね。
これで、正解は1436のうちの3つの数を含み、且つそのうちの2つは桁も同じということが分かる訳です。
これをくり返し4桁の正解をずばり当てるんです。
使い方を簡単に整理する
まずは、これから何を作らないといけないのかについて整理してみます。
- Startが選択されると、ゲーム開始。
この時には、解答欄、Hit欄、Blow欄をクリアし、これから当てようとする正解を用意する。 - 解答が入力された場合、正解と照らし合わせ、Hit, Blowを求め、表示する。
この際、正解した場合はメッセージを表示しておしまい。
但し、入力できるのは数値4桁のみで、最初の行から順番に入力する事とする。 - 10回解答しても正解が出ない場合は、ゲームオーバー。
簡単に書けばこんなところでしょうか?
ゲーム開始処理を作る
まずは、マクロを作ります。(ここで、注意!。このページの図のようにファイル名とシート名が同じになっている場合は、違うものにして下さい。同じになっているとExcelがマクロを見つけられないようです(~_~;) )
Startボタンを選択して、コンテキストメニューで「マクロ登録」を選びます。表示されるダイアログで、マクロ名に「GameStart」と入力して「新規作成」ボタンを押します。
VBEが起動されて、新しいモジュールには以下のようにマクロが作られるでしょう。
これで、StartボタンとマクロGameStartが関連づけられましたので、Startボタンをクリックすると、GameStartが実行されるようになります。(といっても、まだ何も書いていないので何も起こりませんが)
Option Explicit
Sub GameStart()
End Sub
では、マクロを書きましょう。でも、いきなり書かずに、まずはコメントを書いてみましょう。
いきなりマクロを書いてもいいのですが、そのまえにもう一度手順を確認してみましょうか。
Option Explicit
Sub GameStart()
' 解答欄、Hit欄、Blow欄をクリア
' 正解を用意
End Sub
単純ですね! では、本当にマクロを書きましょう。
Option Explicit
Const LEVEL = 4 '正解の桁数
Sub GameStart()
' 解答欄、Hit欄、Blow欄をクリア
Range("B5:D14").ClearContents
' 正解を用意
MakeAnswer
End Sub
Sub MakeAnswer()
Dim i As Integer
Dim index As Integer
Dim ans As String
Dim useNums As String
useNums = "0123456789"
ans = ""
Randomize
For i = 1 To LEVEL
index = Int((Len(useNums)) * Rnd) + 1
ans = ans & Mid(useNums, index, 1) '一文字抜き出し
' Debug.Print "usenums=" & useNums
' Debug.Print "index =" & index
' Debug.Print "ans=" & ans
'使った文字を除く
If (index > 1) Then '最初の文字以外
useNums = Left(useNums, index – 1) & Mid(useNums, index + 1)
Else
useNums = Mid(useNums, index + 1)
End If
Next i
With Range("正解")
.FormulaR1C1 = ans
.NumberFormat = ";;;"
End With
End Sub
クリアについては、すぐにわかると思います。セルの範囲をクリアしています。
ここで注意するのは、クリアするのは値だけと言う事です。書式はクリアしないようにしています。
次の解答作成MakeAnswerですが、人によってはプロシージャにせずにそのまま書いてしまうかもしれません。でも、それは余りお勧めできません。よ く言われるスパゲッティプログラムの元になるからです。一つのプロシージャで何でもやってしまおうとするために、処理が複雑にこんがらがるようになってわ かりにくくなるんですね。
実は、先にコメントを書いたのも、処理が複雑になるようならプロシージャとして分けましょうという考えが隠れていたのです。(隠すなって ;)
さて、解答をつくるプロシージャですが、いくつか考慮する事があります。
- 毎回違う値になるようになります。
- 全桁はユニークな数字とする。他の桁と同じ数は使わない。
一つ目は、通常乱数を使います。Rnd関数がそれです。0以上1未満の数を返す関数です。
これを使えば、ユニークな数を求める事ができるんですね。但し、このままだと毎回同じサイクルでユニークな数が得られます。これじゃクイズにならないですよね。
同じサイクルではないようにするには、先にRandomizeステートメントを呼ぶようにします。
二つ目は、いくつか方法がありそうです。例えば、ひと桁づつユニークな値を求めて、すでに使われている数なら再度数を求めるとか。。。
ただ、これだと使われている数がずっと出てきたらどうなるの?という心配がありますね。
そこで、ここでは数字を文字列として持っておいて、乱数で求めた位置にある数字を使うという方法でいきます。使った数字は文字列から削除し、二度と使えないようにするのです。
最後に、正解欄のセルに解答をセットします。ただ、このままでは解答が見えてしまってクイズにならないので、見えないようにします。これは、書式に;;;をセットするだけで構いません。
Range("正解")というように書いていますが、これはあらかじめB2セルに正解と言う名前をつけておいてこれを使っています。こういう書き方をすると非常に分かりやすくなりますね。
また、途中にDebug.Printと書いている行がありますが、これはデバッグ文と言う奴です。
マクロが思うように動いているかを確認するために書いたものですね。これをコメントにしないと、その引き数の内容が、イミディエイトペインに表示されま す。Windowsではウォッチペインと言うもっと便利なデバッグ機能があるのですが、Mac版にはないので、イミディエイトペインでやるしかないので辛 い所ですね。
2000.1.20