前回は「信長の野望」もどきでもなんでもなかったので、今回は最低でも「もどき」といえるものを作ることにします。

まずユーザーコントロールを作成します。クラス名は城を表示するためのものなのでCastleにします。

これをフォーム上に配置します。

それから表示させたい城の名称と城主の名前、兵力を管理するために以下のようなクラスを作成します。

次にこれに城の名称と城主の名前、兵力を表示させるために以下のような処理をおこないます。

まず自作メソッド CreateCastleList()でCreateオブジェクトのリストを作成するとともに、0 ~ 9 の通し番号をつけます。次に自作 InitCastleStatusList()で城のステータスを表すCastleStatusのリストを生成し、ここに城の名称と城主の名前、兵力をセットします。最後に自作メソッド UpdateCastlesStatusで反映させます。

コンストラクタの実行はこんな感じになります。

Createオブジェクトのリストを作成するとともに、0 ~ 9 の通し番号をつけるCreateCastleListメソッドを示します。

城のステータスを表すCastleStatusのリストを生成し、ここに城の名称と城主の名前、兵力をセットするInitCastleStatusListメソッドを示します。城の名称と城主はネタ元に合わせています。

CastleStatusのリストを実際に表示されている城に反映させるUpdateCastlesStatusメソッドを示します。

スタートボタンがクリックされたらゲームスタートです。前回のゲームデータが表示されているかもしれないのでInitCastleStatusListメソッドを実行します。そしてランダムに順番を決めます。そのためにCastleStatusListの順番を入れ替えるGetShuffledCastlesメソッドを呼び出します。Turnメソッドについてはこのあと解説します。

Turnメソッドですが、そのターンでなにもしていない城のリストを取得したあと、foreach文で処理を回すわけですが、そのなかで城主が「織田」かどうかを調べます。この場合はプレイヤーのターンです。複数の城がある場合、どれがどれなのかわからなくならないようにPlayerCastleStatusにCastleStatusを保存します。

それ以外は敵のターンなのでEnemyTurnメソッドで処理をします。このときゲームオーバーになる場合があるので、処理を継続する必要があるのかを戻り値で判断できるようにしています。

表示させるメッセージはSituationsのなかに追加していき、ShowSituationメソッドで表示させます。表示させるメッセージが存在する場合はつぎのメッセージを見る以外の動作はできないようにします(後述)。

Situationsですが、Form1クラスのなかで以下のように宣言されています。

そしてSituationクラスは以下のようになっています。

敵のターンにかんする処理はすぐに終わりますが、その結果は1行ずつ表示させるために表示させたいメッセージとそのときの城の状態をSituationクラスに格納します。

コンストラクタ内でそのときの城の状態をコピーして記憶させています。あとはメッセージが表示されるタイミングでUpdateCastlesStatusメソッドで城の状態をフォームに反映させればよいのです。

EnemyTurnメソッドでは敵にとって自分の城と敵の城をわけてリストを作成します。そして兵が存在する場合は戦争を仕掛けます。

戦争を仕掛けるときは動員する人数を乱数で決めます。このとき0人になったら戦争はやめます。0人より多い人数を動員する場合はどの城に仕掛けるかを乱数で決めて実行します。戦争の結果は別のメソッド、Warで求めます。

戦争の結果、織田側が負けた場合で、残りの城が存在しない場合はゲームオーバーです。

戦争をした結果を求めるメソッド Warを示します。ネタ元と同じで守備側が有利にします。乱数を生成して0なら守備側の兵数を1減らし、1と2のときは攻撃側の兵数を1減らします。2倍の差がありますが、実際に城を落とすためには守備側の3倍の兵力が必要であるといわれています。

ボタンをおすとメッセージが表示されます。ShowSituationメソッドになかでメッセージをすべて表示してしまった場合はボタンを押せなくしています。

実際にメッセージを表示するためのShowSituationメソッドを示します。TurnメソッドやEnemyTurnメソッド、Warメソッドが実行されるとSituationsのなかにメッセージが格納されていきます。このなかで一番最初に格納されているものを表示させるとともにUpdateCastlesStatusメソッドを呼び出してそのときの城の状態を反映させています。

メッセージがなくなったときとはプレイヤーに順番が回ってきたとき、プレイヤーがすべての城を獲得したとき又は失ったとき、すべての城主の行動が終了したときです。

すべての城主の行動が終了かどうかはCastleStatus.Doneプロパティがすべてtrueになっているかどうかでわかります。このときは1年が経過したとして、翌年のターンにはいります。この場合はTurnメソッドを呼び出します。

プレイヤーに順番が回ってきたときは自作メソッド PlayerAction(後述)を呼び出します。すでにゲームクリアまたはゲームオーバーになったときは次へボタンがクリックできないように非表示にして、ゲーム開始ボタンをクリックできるように表示させます。

プレイヤーに順番がまわってきたときは移動先の城をコンボボックスに表示させます。そして移動させたい人数を選択して[決定]ボタンをおせば移動先が味方であるときは移動し、敵の城であるときは戦争になります。

[決定]ボタンを押した場合、移動先としてどこが選択されているかを調べます。移動先のstatus.CastleOwnerがプレイヤーと同じ場合は「移動」で移動元の城の兵力が減り、移動先が増えます。移動先のstatus.CastleOwnerが敵の場合は「戦争」でありWarメソッドが呼び出されます。

戦争に勝った場合は敵勢力は自分の城をすべてなくしているかもしれません。このときは「家は滅亡しました」と表示されます。またすべての城がすべてプレイヤーのものになっている場合は天下統一となりゲームクリアです。

ゲームクリアの場合は最後のメッセージを表示させるために、ShowSituationメソッドが実行されます。それ以外のときはほかの敵のターンになるため、Turnメソッドが呼び出されます。

待機の場合は兵力が6になります(プレイヤーだけの特権)。このようなプレイヤーだけの特権があるのはデバッグのときに結果を自由に操作できるようにするためです。

このゲームはネタ元とちがって隣の城でなくても攻撃できてしまいます。ブラウザアプリでも作りたいので、あまりこのあたりは深入りしないようにしています。