|
|
VBAではじめるAutoCADカスタマイズ |
|
|
第10回 Tic-Tac-Toeゲームを作る(その2) |
|
|
■ はじめに
前回は人間の指し手を処理するTurnMaruプロシージャの作成までを解説しました。今回は引き続き後半部分のコンピュータの指し手を処理するTurnBatsuプロシージャから解説をはじめます。図面上に作図されたマス目と1対1に対応し、コンピュータの指し手の決定や勝敗の判定に利用する2次元配列の扱い方がポイントになります。なお、今回作成するゲームのVBAプロジェクトファイルはこちらからダウンロードすることができます。
■ プログラムの作成(後編)
◆ TurnBatsuプロシージャ
TurnBatsuはコンピュータの指し手を処理するプロシージャです。人間の指し手と違ってどのマス目に×を置くのかを決定する処理が含まれています。
ところで三目並べには以下のような定石があり、両者が最善を尽くすと引き分けになることが知られています。TurnBatsuプロシージャでもこの定石にしたがってどのマス目に×を置くかを決定することにしましょう。
1. 3つ並べることができればそうする。
2. 相手が3つ並べるのを妨げる。
3. 可能なら中央のマス目へ置く。
4. 可能なら隅のマス目へ置く。
6行目〜21行目
最初のForループではGameBoardの配列要素のうち空いているマス目(FREE)を総当りで探し、仮に×(BATSU)を置いてみて、勝敗を判定するCheckWinner関数の戻り値が×の勝ち(BATSU_WIN)ならDrawBatsuプロシージャを呼び出して終了し、それ以外ならマス目の値をもと(FREE)に戻します。
23行目〜38行目
空いているどのマス目に×を置いても勝てなければ、最初のForループと同様、仮に○(MARU)を置いてみて、○が勝つ(MARU_WIN)マス目があった場合はDrawBatsuプロシージャを呼び出して終了します。
40行目〜55行目
どのマス目に○×を置いても勝ちとならない場合は、中央もしくは四隅のマス目のうち空いているマス目に×を置いてプロシージャを終了します。
BoardArray配列の中央と四隅のマス目 |
|
57行目〜64行目
1〜4のどの定石を試してもうまくいかない場合は、空いたマス目を左下隅から総当りで探して最初に見つかったマス目に×を置きます。
実際にはもっと適切かつ効率よく×を置くマス目を決定する方法もあると思うのですが、今回はプログラムのわかりやすさを優先してこのような方法としています。
◆
DrawMaruプロシージャ
DrawMaruはTurnMaruプロシージャから呼び出され、引数で指定されたゲーム盤のマス目位置に○を作図するプロシージャです。
6行目
○が置かれたマス目位置に対応するGameBoardの配列要素に定数MARU(= 1)を書き込みます。
ゲーム盤上の○×とBoardArray配列の対応 |
|
8行目〜10行目
○が置かれたマス目の中心にAddCircleメソッドで円(Circleオブジェクト)を作図し、色を赤(acRed)に変更します。
12行目〜13行目
最後に作図した○を選択セットに格納し、ApplicationオブジェクトのUpdateメソッドを実行して図面の更新を行います。
◆ DrawBatsuプロシージャ
DrawBatsuはTurnBatsuプロシージャから呼び出され、引数で指定されたゲーム盤のマス目位置に×を作図するプロシージャです。
7行目
×が置かれたマス目位置に対応するGameBoardの配列要素に定数BATSU(= -1)を書き込みます。
9行目〜16行目
×が置かれたマス目の中心にAddLineメソッドとMirrorメソッドを組み合わせて×を作図し、色を青(acBlue)に変更します。
18行目〜19行目
最後に作図した×を選択セットに格納し、ApplicationオブジェクトのUpdateメソッドを実行して図面の更新を行います。
◆ CheckExitプロシージャ(関数)
CheckExitは引数として現在のゲームのターン数を受け取り、CheckWinner関数を呼び出してゲームの終了判定と勝敗の結果を表示するプロシージャ(関数)です。
3行目〜19行目
CheckWinner関数が返す勝敗の判定結果(MARU_WINまたはBATSU_WINまたはDRAW)に応じて適切なメッセージを表示し、すでに勝敗が決まっている場合はTrueを返してプロシージャを終了します。
10行目〜18行目
ただし、引き分け(DRAW)でかつ現在のゲームのターン数が4未満の場合はまだ勝敗が決まっていないので、呼び出し元のプロシージャにFalseを返します。
◆ CheckWinnerプロシージャ(関数)
CheckWinnerは勝敗の判定を行うプロシージャ(関数)で、○の勝ちの場合はMARU_WIN(= 1)を、×の勝ちの場合はBATSU_WIN(= -1)を、引き分け(勝敗が決まっていない場合を含む)の場合はDRAW(= 0)を返します。
6行目〜13行目
三目並べでは勝ちとなる組み合わせが縦横斜めの8通りしかありません。ですから、あらかじめ勝ちとなるすべてのGameBoard配列要素の組み合わせについてその値を合計したものを要素数8の一次元配列sujiに書き込んでおきます。
15行目〜25行目
勝ちとなる配列要素の組み合わせの値の合計は、すべてが○の場合は定数MARUの値が1なので3となり、×の場合は-3になります。ここではForループで一次元配列sujiのすべての値をチェックすることにより、勝敗の判定を行います。
○が勝ちの場合は値の合計が3になる。 |
|
■ プログラムの実行と保存
すべてのプログラムコードが入力できたら早速実行してみましょう。VBエディタを閉じ、AutoCADの[ツール]メニューの[マクロ - マクロ]をクリックして[マクロダイアログ]を開きます。[マクロダイアログ]のマクロ名[Global1!Module1.Main]を選択して[実行]ボタンをクリックするとゲームがスタートします。
うまくプログラムが動作したら作成したプロジェクトを保存しておきます。VBAプロジェクトを保存しておけば、いつでもAutoCADにロードしてゲームを行うことができるようになります。
AutoCADのAutoCADの[ツール]メニューの[マクロ - VBA管理]を選択して[VBA管理]ダイアログを開きます。[VBA管理]ダイアログのプロジェクト「TicTacToe」を選択して[名前を付けて保存]ボタンをクリックし、プロジェクトを「TicTacToe.dvb」という名前で保存します。
■ 最後に
前回と今回の2回に分けて初めて本格的なプログラムに挑戦してみました。単純なゲームでしたが楽しみながらプログラミングできたでしょうか? ゲームの作成自体が目的ではないので、コンピュータの思考方法は少し簡略化していますが、人間とコンピュータのどちらを先攻にするか選べるようにしたり、より強くなるように改造してみるのも面白いと思います。このようにAutoCAD VBAはアイディア次第でいろいろなことに応用できます。 |
|
|
|