SeaGate HomePage 別館
本館 別館 ブログ
 
トップページ
第01回
第02回
第03回
第04回
第05回
第06回
第07回
第08回
第09回
第10回
第11回
第12回
第13回
第14回
おまけ
VBAではじめるAutoCADカスタマイズ VBAではじめるAutoCADカスタマイズ
第09回 Tic-Tac-Toeゲームを作る(その1)

■ はじめに

これまで学習してきたAutoCADのメソッドやプロパティ、VBAのプログラミングに関する知識をおさらいする意味で、今回と次回の2回に分けて人間とコンピュータが対戦する簡単なゲームを作成してみます。作成するゲームは皆さんお馴染みのTic-Tac-Toe(三目並べ、いわゆるマルバツゲーム)です。単純なゲームですが一通りの機能がそろった本格的なプログラムですので、ゲームを楽しみながらVBAプログラムの作成手順を再確認してみてください。

今回は、プログラムの作成方法と、前半部分のプログラムコードの解説を行います。後半部分のプログラムコードの解説と、プログラムの実行方法などについては次回解説します。なお、今回作成するゲームのVBAプロジェクトファイルはこちらからダウンロードすることができます。

Tic-Tac-Toe(三目並べ)の実行画面
Tic-Tac-Toe(三目並べ)の実行画面

■ プログラムの仕様と構成

プログラムを作成するには、ちょうど建築の基本設計でプランや仕様を決定し、それにしたがって実施設計で図面を作図していくように、まずどのような仕様のプログラムを作成するのかを決定し、次に実際にどのようなプログラムコードとして記述していくのかを考えていく必要があります。

今回作成する三目並べゲームでは、最初に新しい図面を作成してゲーム盤を作図し、そのゲーム盤上で人間とコンピュータが対戦しながらゲームを進めて行くことにします。また、ゲームの作成そのものが目的ではないので、処理を単純にするために常に人間が先攻(○)でコンピュータが後攻(×)とし、何度もリプレイできるようにします。

プログラムの構成は、メインプロシージャのループの中で人間とコンピュータが交互に○×を置き、指し手ごとに勝敗の判定を行うようにします。ゲーム盤の作図や初期化、勝敗の判定などのまとまった処理と、指し手や○×の作図などの繰り返し実行する処理は、それぞれ別の子プロシージャにまとめて順次呼び出しながら処理を進めていくことにします。

■ プログラムの作成(前編)

それでは早速プログラムの作成に取りかかりましょう。今回は「ThisDrawing」ではなく、標準モジュールにすべてのプログラムコードを記述していくことにします。VBエディタを起動して[挿入]メニューの[標準モジュール]をクリックします。次に、プロジェクトエクスプローラでプロジェクト[ACADProject(Glabal1)]を選択し、プロパティウィンドウでプロジェクトの名前を「TicTacToe」に変更してください。

VBAプロジェクトの構成

プログラムコードの記述

今回の解説ではプログラムコードをプロシージャごとに分けて掲載していますが、実際にはすべてのプロシージャをコードウィンドウに続けて入力します。また、VBAでは原則として行単位でプログラムコードを記述する必要があります。

コードウィンドウの[オブジェクト]ボックスで「(General)」を選択したときは、[プロシージャ]ボックスに宣言セクション(Declarations)とすべてのプロシージャが表示され、選択したプロシージャにジャンプすることができます。また、コードウィンドウの左下にある[プロシージャの表示][モジュール全体を表示]ボタンをクリックすると、コードウィンドウに1つのプロシージャのみを表示するか、モジュール内のプログラムコード全体を連続して表示するかを切り替えることができます。


◆ 宣言セクション

宣言セクションではモジュール内のプロシージャで共通して使用する定数と変数の宣言を行います。

> プログラムコードを別ウィンドウで表示 ※ 行番号を入力する必要はありません

6行目〜8行目
AutoCAD VBAは3次元座標を要素数3の倍精度浮動小数点型の1次元配列で表わすので、X, Y, Z各座標を示す添え字(0〜2)を定数で指定できるようにします。

10行目〜16行目
定数MARU, BATSU, FREEは後述するGameBoard配列の各要素が○か×か、あるいは何も置かれていないかを表わし、定数MARU_WIN, BATSU_WIN, DRAWは勝敗の判定結果を表わします。

18行目〜20行目
GameDocumentはAcadDocument型のオブジェクト変数で、ゲームを行う図面(Documentオブジェクト)を格納してそのDocumentオブジェクトを各プロシージャから操作するために使用します。また、GameSelSetは図面上に作図した○×を格納し、リプレイする時に一括して消去するために使用する選択セットです。

GameBoardは下図に示すような要素数3×3の整数型の2次元配列で、ゲーム盤のマス目を表わします。プレイヤーやコンピュータがゲーム盤のマス目に○×を置くと、該当する配列要素に定数MARU, BATSUを書き込んでマス目の空き状況や勝敗の判定を行うために使用します。

GameBoard配列の要素
GameBoard配列の要素

◆ Mainプロシージャ

MainはPublicキーワード付きで宣言されたグローバルレベルのプロシージャで、このプログラムのエントリーポイントです。Mainプロシージャは大きく分けて前処理とループ、後処理の3つの部分から構成されます。

> プログラムコードを別ウィンドウで表示 ※ 行番号を入力する必要はありません

5行目〜16行目
前処理の部分ではゲーム盤を作図する図面(Documentオブジェクト)と作図した○×を格納するための選択セット(SelectionSetオブジェクト)を作成し、DrawBoardプロシージャを呼び出してゲーム盤の作図などを行います。

StartUndoMarkはDocumentオブジェクトの持つメソッドで、このメソッドを呼び出してからEndUndoMarkメソッドを呼び出すまでに実行された操作をグループ化します。グループ化された操作はプログラム終了後にU[一回元に戻す]コマンドなどで取消すことができます。

18行目〜35行目
ループ部分は外側のDoループと内側のForループの2重のループになっています。外側のDoループは最初にClearBoardプロシージャを呼び出してGameBoard配列の初期化などを行った後、ゲーム終了時にプレイヤーがメッセージボックスに対して「いいえ」(vbNo)を選択するまでゲームを繰り返します。

21行目〜29行目
内側のForループは人間とコンピュータが実際に対戦する部分で、TurnMaru, TurnBatsuプロシージャを交互に呼び出して両者が○×を置くたびにCheckExit関数で勝敗の判定を行い、勝敗が決まるか引き分けの場合にはExit For文を実行してループを脱出します。また、三目並べではゲームのターン数が5を超えることはないので、Forループの繰り返し回数を0〜4の5回としています。

37行目〜38行目
最後の後処理の部分ではEndUndoMarkメソッドを呼び出して操作のグループ化を終了し、不要になった選択セット(GameSelSet)をDeleteメソッドで削除します。

◆ DrawBoardプロシージャ

DrawBoardはMainプロシージャで作成したDocumentオブジェクトのモデル空間(ModelSpaceコレクション)にゲーム盤を作図するプロシージャです。

> プログラムコードを別ウィンドウで表示 ※ 行番号を入力する必要はありません

8行目〜13行目
最初のForループではY座標を0〜3まで変化させながらAddLineメソッドで水平線を作図します。

15行目〜20行目
同様に、2番目のForループではX座標を0〜3まで変化させながら垂直線を作図し、全体として下図のようなグリッドを作図しています。

ゲーム盤の座標
ゲーム盤の座標

22行目
最後にApplicationオブジェクトのUpdateメソッドを実行して図面の更新を行います。

◆ ClearBoardプロシージャ

ClearBoardはゲーム盤のマス目を表わすGameBoard配列の初期化やゲーム盤に作図した○×の消去を行い、新しいゲームを開始するための準備を行うプロシージャです。

> プログラムコードを別ウィンドウで表示 ※ 行番号を入力する必要はありません

6行目〜10行目
2重のForループを使用してGameBoard配列のすべての要素の値を定数FREE(= 0)にリセットします。

初期化後のGameBoard配列の値
初期化後のGameBoard配列の値

12行目〜13行目
ゲーム盤に作図され、選択セット(GameSelSet)に格納された○×をEraseメソッドで消去し、ApplicationオブジェクトのUpdateメソッドを実行して図面の更新を行います。

◆ TurnMaruプロシージャ

TurnMaruは人間の指し手を処理するプロシージャです。

> プログラムコードを別ウィンドウで表示 ※ 行番号を入力する必要はありません

10行目
UtilityオブジェクトのGetPointメソッドを実行し、プレイヤーがゲーム盤上で指定した座標位置を取得します。

12行目〜14行目
GetPointメソッドで座標以外が入力されるとエラーが発生し、ErrオブジェクトのNumberプロパティが0以外の値となります。その場合はErrオブジェクトをクリアして再度座標位置の入力を求めます。

18行目〜21行目
正常に座標位置が取得できた時は、取得した座標位置がGameBoard配列のどのマス目位置に該当するかを判断し、列(X)と行(Y)の番号を一次元配列boardに書き込みます。また、該当するマス目がない時は列・行番号とも-1になります。

23行目〜36行目
該当するマス目がありかつそのマス目が空いていたら(FREE)、DrawMaruプロシージャの引数にマス目の列・行番号を指定して呼び出します。また、該当するマス目がないがマス目が空いていなかった場合には、メッセージを表示して再度座標位置の入力を求めます。

ゲーム盤の座標とBoardArray配列の関係
ゲーム盤の座標とBoardArray配列の関係

■ 最後に

今回はいきなりプログラムコードの量が増えて面食らった方もいらっしゃるのではないでしょうか?しかし、プログラムコードの量は増えても今までの連載で説明した内容が組み合わされているだけですので、少しずつ読み進めていけばきっと理解できるはずです。次回は、Tic-Tac-Toeゲームの後半部分の解説とプログラムの実行方法などについて説明します。ぜひ残り半分のプログラミングにも挑戦し、Tic-Tac-Toeゲームを完成させてみてください。
SeaGate
コレクション



inserted by FC2 system