⇒ 動作確認はこちらからどうぞ。
Turnメソッドのなかで城の状態に応じて処理をおこないます。このときIndexクラスが大きくならないように別のクラスを作成して、処理はそのなかでおこないます。
ここでは以下のクラスを作成します。
どこからも攻め込まれていないプレイヤーの城
PlayerCastleIfNormalクラス
攻め込まれようとしているプレイヤーの城
PlayerCastleIfAttackingクラス
包囲されているプレイヤーの城
PlayerCastleIfSiegingクラス
そしてこれらのクラスは前回作成したCastleBaseクラスを継承してつくります。
まずTurnメソッドを示します。1、2、3、5の場合はユーザーがコマンドを入力することになるのでループを抜けます。クラスの内部でメッセージを表示するメソッドを実行しています。するとすべてのメッセージを表示しおわったときにコマンドボタンをクリックできるようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
public partial class Index { // どのような型かは後述 EnemyCastleIfPlayerSieging EnemyCastleIfPlayerSieging = null; PlayerCastleIfAttacking PlayerCastleIfAttacking = null; PlayerCastleIfSieging PlayerCastleIfSieging = null; public void Turn() { CurentCastleStatus = null; // 「決定」ボタンなどをクリックできないように非表示にする // 次のメッセージを表示させるためのボタンをクリック可能にする HideCommand(); // まだそのターンでなにもしていない城のリストを取得する List<CastleStatus> Statuses = CastleStatusList.Where(x => !x.Done).ToList(); foreach (var status in Statuses) { if (status.CastleOwner == PlayerName) { if (status.AttackingCorps == null && status.SiegingCorps == null) { // 1.どこからも攻め込まれていないプレイヤーの城 new PlayerCastleIfNormal(this, status); return; } if (status.AttackingCorps != null && status.SiegingCorps == null) { // 2.攻め込まれようとしているプレイヤーの城 PlayerCastleIfAttacking = new PlayerCastleIfAttacking(this, status); return; } if (status.AttackingCorps == null && status.SiegingCorps != null) { // 3.包囲されているプレイヤーの城 PlayerCastleIfSieging = new PlayerCastleIfSieging(this, status); return; } } if (status.CastleOwner != PlayerName) { Corps attacking = status.AttackingCorps; Corps sieging = status.SiegingCorps; if (attacking != null && attacking.BaseCastleOwner == PlayerName && sieging == null) { // 4.プレイヤーに攻め込まれようとしている敵の城(後のページで) new EnemyCastleIfPlayerAttacking(this, status); continue; } if (attacking == null && sieging != null && sieging.BaseCastleOwner == PlayerName) { // 5.プレイヤーに包囲されている敵の城(後のページで) EnemyCastleIfPlayerSieging = new EnemyCastleIfPlayerSieging(this, status); return; } if (attacking != null && attacking.BaseCastleOwner != PlayerName && sieging == null) { // 6.別の敵に攻め込まれようとしている敵の城(後のページで) new EnemyCastleIfOtherEnemyAttacking(this, status); continue; } if (attacking == null && sieging != null && sieging.BaseCastleOwner != PlayerName) { // 7.別の敵に包囲されている敵の城(後のページで) new EnemyCastleIfOtherEnemySieging(this, status); continue; } if (attacking == null && sieging == null) { // 8.どこからも攻め込まれていない敵の城(後のページで) new EnemyCastleIfNormal(this, status); } } } ShowSituation(); } } |
では各クラスをみてみましょう。
Contents
どこからも攻め込まれていないプレイヤーの城 PlayerCastleIfNormalクラス
objはIndexクラスのインスタンスです。obj.~とやればIndexクラスのメソッドを実行することができます。このクラスは最後にIndex.ShowSituationメソッドを呼び出しています。Index.ShowSituationメソッドが呼び出されると[次へ]ボタンしかクリックできなくなり、リストに格納されたすべてのメッセージをクリックすると後述するIndex.PlayerActionメソッドが呼び出され、ボタンをクリックできるようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public class PlayerCastleIfNormal : CastleBase { public PlayerCastleIfNormal(Index obj, CastleStatus status) : base(obj, status) { obj.CurentCastleStatus = status; string str = "順番がきました。ここは " + status.CastleName + " です。"; // 到着した兵がいるなら合流させる if (status.SupportCorps != null) { int count = status.SupportCorps.SoldierCount; string fromCastle = status.SupportCorps.BaseCastleName; string fromOwner = status.SupportCorps.BaseCastleOwner; status.SoldierCount += count; status.MilitaryFood += obj.CurentCastleStatus.SupportCorps.MilitaryFood; status.SupportCorps = null; str += String.Format("{0}の{1}軍が{2}人合流しました。", fromCastle, fromOwner, count * 1000); } obj.AddSituation(str); obj.ShowSituation(); } } |
攻め込まれようとしているプレイヤーの城 PlayerCastleIfAttackingクラス
次に攻め込まれようとしているプレイヤーの城 PlayerCastleIfAttackingクラスを示します。
まず到着した援軍がいるなら城のなかにいれます。敵への対応はそれからになります。
もし防御側の兵がいない場合はなにもできずにそのまま占領となります。また攻撃側が出撃元の城を奪われたり包囲されていて帰ることができない場合は強行突入をしかけてします。それ以外のときは「ここは○○城。城に○軍○人が迫っています」と表示され、ユーザーにどのように対応するかを問うてきます。
コンストラクタのなかでは上記で示したような全体の流れが書かれています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
public class PlayerCastleIfAttacking : CastleBase { public PlayerCastleIfAttacking(Index obj, CastleStatus status) : base(obj, status) { // 到着した兵がいるなら合流させる SoldiersJoin(); // 防御側の兵がいない場合は占領される if (RunOccupyIfNoDefenseSoldiers()) return; // 攻撃側が帰れる城を持たない場合は強行突入をしかけてくる if (!atCanReturn) { if (RunForcedRush()) return; } else { string str1 = String.Format("ここは{0}です。", castleName); string str2 = String.Format("城に{0}軍 {1}人が迫っています。", atOwner, atCount * 1000); obj.AddSituation(str1 + str2); obj.CurentCastleStatus = status; obj.ShowSituation(); } } } |
PlayerCastleIfAttacking.SoldiersJoinメソッドは到着した兵がいるなら合流する処理をするためのメソッドです。兵と兵糧を城のなかにいれます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class PlayerCastleIfAttacking : CastleBase { void SoldiersJoin() { if (spCount != 0) { _status.SoldierCount += spCount; _status.MilitaryFood += _status.SupportCorps.MilitaryFood; _status.SupportCorps = null; string str = String.Format("{0}に{1}の{2}軍が{3}人合流しました。", _status.CastleName, spCastle, spOwner, spCount * 1000); _obj.AddSituation(str); } } } |
PlayerCastleIfAttacking.RunOccupyIfNoDefenseSoldiersメソッドは城のなかに兵がいるかどうかを調べていない場合は占領の処理をするメソッドです。占領された城は敵のものになるのでターンは回ってきません。また城を奪われたときはゲームオーバーになったかもしれないのでその確認もしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public class PlayerCastleIfAttacking : CastleBase { bool RunOccupyIfNoDefenseSoldiers() { if (OccupyIfNoDefenseSoldiers()) { string str = string.Format("{0}を守る兵はいないため {1}軍に城を奪われてしまいました・・・", castleName, atOwner); _obj.AddSituation(str); // 城を奪われたときはゲームオーバーになったかもしれないので確認をしている CastleOccupied(oldOwner); CheckGameOverIfRuin(); // 占領された場合はターンは回ってこない _status.Done = true; _obj.ShowSituation(); return true; } return false; } } |
攻め込んできた敵がもとの城に戻れない場合は強行突入をしかけてきます。PlayerCastleIfAttacking.RunForcedRushメソッドはそのときの処理をおこないます。
ここで城を取られたならターンは回ってこないのは上記と同じです。もし攻撃を跳ね返したら自分のターンになりますが、ここで撃退した敵の軍団は最後のひとつかもしれません。そのため敵の滅亡の判定と全部の敵が滅亡した(=ゲームクリア)の判定もしています。
CheckGameClearIfEnemyRuinメソッドは引数でわたした武将が滅亡したかを調べ、滅亡した場合はその旨表示します。このメソッドがtrueを返すのはゲームクリアしたときだけです。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
public class PlayerCastleIfAttacking : CastleBase { bool RunForcedRush() { _obj.AddSituation(string.Format("大変です! 出撃拠点を敵に奪われた{0}軍が{1}に強行突入をしてきました!", atOwner, castleName)); // 包囲前の突入なので status.SiegingCorpsへの代入が必要 _status.SiegingCorps = _status.AttackingCorps; _status.AttackingCorps = null; if (ForcedRush()) { _obj.AddSituation(string.Format("{0}軍に{1}を奪われました・・・", atOwner, castleName)); _status.Done = true; // 城を取られたならターンは回ってこない CastleOccupied(oldOwner); CheckGameOverIfRuin(); return true; } else { _obj.AddSituation(string.Format("{0}軍の強行突入をはねかえし{1}を守りきりました!!", atOwner, castleName)); if (CheckGameClearIfEnemyRuin(atOwner)) return false; // 強行突入を跳ね返したのであれば自分のターンにする _obj.AddSituation("順番がきました。ここは " + castleName + " です。"); _obj.CurentCastleStatus = _status; _obj.ShowSituation(); return false; } } } |
包囲されているプレイヤーの城 PlayerCastleIfSiegingクラス
次にターンが回ってきた城が敵に包囲されているプレイヤーの城である場合のPlayerCastleIfSiegingクラスを示します。
まず援軍が到着したのであれば敵の包囲軍と戦闘になります。城を守る兵がいない場合は占領されます。そして兵糧攻めをされているので兵糧を減らします。兵糧は兵数によりますが、包囲軍よりも包囲されている城側のほうが2倍早く減ります。
もし包囲軍が兵糧攻めをしても城を落とせる見込みがないと判断したときは強行突入をしてきます。
到着した援軍によって敵の包囲軍を退散させた場合、包囲軍が強行突入してきて返り討ちにできた場合は自分の城にターンが回ってきます。それ以外の場合でも、城を守る兵がいないため占領された場合を除いて自分の城にターンが回ってきます。
コンストラクタを示します。ここでは上記の流れどおりになっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
public class PlayerCastleIfSieging : CastleBase { public PlayerCastleIfSieging(Index obj, CastleStatus status) : base(obj, status) { // 到着した兵がいるなら包囲している敵と戦闘になる if (_status.SupportCorps != null) { if (RunCombatForSupport()) return; } // 防御側の兵がいない場合は占領される if (RunOccupyIfNoDefenseSoldiers()) return; // 兵糧攻めをされているので兵糧を減らす ResultSiege rs = RunSiege(); if (rs != ResultSiege.Sieging) return; // 城側が2ヵ月以上の兵糧をもつ場合は強行突入してくるかもしれない // 包囲軍に戻るべき城がないなら強行突入してくる if (status.MilitaryFood >= status.SoldierCount * 2 * 2 || status.SiegingCorps.BaseCastle == null) { RunForcedRush(); return; } string str = string.Format("ここは{0}です。現在、{1}軍 {2}人に包囲されています。非常に危険な状態です。", status.CastleName, sgOwner, sgCount * 1000); obj.AddSituation(str); // 自分のターンに obj.CurentCastleStatus = status; obj.ShowSituation(); } } |
PlayerCastleIfSieging.RunCombatForSupportメソッドは援軍が到着した場合の包囲軍との戦闘にかんする処理をおこなっています。戦いにやぶれた側がどうなるかは、以前CastleBase.CombatForSupportで示したとおりです。包囲軍を撃退したら敵が滅亡したりゲームクリアになる場合があるので上記のクラス同様の判定をしています。
CastleBase.CombatForSupportで自動的に退却の処理がおこなわれますが、プレイしている人にわかるように、どの城に逃げ帰ったか、逃げ帰る城がないため全滅したかなどをメッセージで表示しています。
包囲軍を撃退することができたら生き残った兵と兵糧がCastleBase.CombatForSupportによって自動的に自分の城に入るのですが、それもわかるようにメッセージを表示させています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
public class PlayerCastleIfSieging : CastleBase { bool RunCombatForSupport() { _obj.AddSituation(String.Format( "{0}軍に包囲されている{1}にわが軍の援軍が到着しました。包囲軍と交戦します。", sgOwner, _status.CastleName)); int ret = CombatForSupport(); if (ret > 0) { _obj.AddSituation(String.Format("{0}軍の包囲を蹴散らして{1}に{2}人合流しました。", sgOwner, castleName, ret * 1000)); if (sgCanReturn) _obj.AddSituation(String.Format("{0}軍は{1}に撤退したようです。", sgOwner, sgCastle)); else { _obj.AddSituation(String.Format("{0}軍は撤退できる城がなかったため全滅したようです♪", sgOwner)); if(CheckGameClearIfEnemyRuin(sgOwner)) return true; } // 包囲軍を撃退したら自分のターンに _obj.AddSituation(string.Format("順番がきました。ここは{0}です。", _status.CastleName)); _obj.CurentCastleStatus = _status; _obj.ShowSituation(); return true; } else return false; } } |
PlayerCastleIfSieging.RunOccupyIfNoDefenseSoldiersメソッドは城を守る兵がいるかしらべていない場合は占領の処理をおこないます。上記のクラス同様、城をうばわれてゲームオーバーになる場合もあるのでその判定もおこなっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public class PlayerCastleIfSieging : CastleBase { bool RunOccupyIfNoDefenseSoldiers() { if (OccupyIfNoDefenseSoldiers()) { string str = string.Format("{0}を守る兵はいないため {1}軍に城を奪われてしまいました・・・", _status.CastleName, sgOwner); _obj.AddSituation(str); CastleOccupied(_obj.PlayerName); CheckGameOverIfRuin(); // 城を奪われたら自分のターンにはならない _status.Done = true; _obj.ShowSituation(); return true; } return false; } } |
PlayerCastleIfSieging.RunSiegeメソッドでは兵糧攻めによって兵糧が減る処理、落城判定をおこないます。
基本的に兵糧攻めでは落城させることができない場合、敵は強行突入をするので包囲軍の兵糧がなくなることはありませんが、その場合は包囲軍は撤退し、自分のターンになるようにしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
public class PlayerCastleIfSieging : CastleBase { ResultSiege RunSiege() { ResultSiege rs = Siege(); if (rs == ResultSiege.Occupied) { // 兵糧が尽きたら落城。城を奪われたら自分のターンにはならない _obj.AddSituation(string.Format("{0}の兵糧がなくなりました。{0}は{1}軍に城を奪われました。", _status.CastleName, sgOwner)); CastleOccupied(_obj.PlayerName); CheckGameOverIfRuin(); _status.Done = true; _obj.ShowSituation(); } else if (rs == ResultSiege.Protected) { string str1 = String.Format("{0}軍の兵糧がなくなりました!", sgOwner); if (sgCanReturn) { string str2 = String.Format("{0}に撤退します。", sgCastle); _obj.AddSituation(str1 + str2); } else { string str2 = String.Format("撤退できる城がないのでこの場で全滅です。"); _obj.AddSituation(str1 + str2); CheckGameClearIfEnemyRuin(sgOwner); } // 包囲軍を撃退したら自分のターンに _obj.AddSituation(string.Format("順番がきました。ここは{0}です。", _status.CastleName)); _obj.CurentCastleStatus = _status; _obj.ShowSituation(); } return rs; } } |
PlayerCastleIfSieging.RunForcedRushメソッドは敵が強行突入してきたときの処理をおこないます。包囲軍が戻るべき城を失った場合は必ず強行突入をしてきます。城を奪われたときのゲームオーバー判定、撃退したときのゲームクリア判定もしていますが、これまでとほとんど同じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
public class PlayerCastleIfSieging : CastleBase { public bool RunForcedRush() { if (sgCanReturn) _obj.AddSituation(string.Format("{0}軍が強行突入してきました!!!", sgOwner)); else _obj.AddSituation(string.Format("戻るべき城を失った{0}軍が強行突入してきました!!!", sgOwner)); if (ForcedRush()) { // 城を奪われたら自分のターンにはならない _status.Done = true; // 城を奪われたときの処理 CastleOccupied(_obj.PlayerName); CheckGameOverIfRuin(); _obj.ShowSituation(); return true; } else { // 包囲軍を撃退した _obj.AddSituation(string.Format("{0}軍の強行突入をはねかえし{1}を守りきりました!!", sgOwner, castleName)); if (CheckGameClearIfEnemyRuin(sgOwner)) return false; // 強行突入を跳ね返したうえでゲームが続行されている場合は自分のターンにする _obj.AddSituation("順番がきました。ここは " + castleName + " です。"); _obj.CurentCastleStatus = _status; _obj.ShowSituation(); return false; } } } |