前回の続きです。
Contents
コンピュータにカードを引かせてみる
順番はユーザーが一番最初にカードを引きます。そしてそのあと他のプレイヤーがカードを引いていきます。
1が0のカードを引く
2が1のカードを引く
3が2のカードを引く
4が3のカードを引く
5が4のカードを引く
0が5のカードを引く
これなら自分はインデックス(添字)が一番大きいプレイヤーからカードを引き、それ以外のライバルたちは自分よりインデックス(添字)が1小さいプレイヤーからカードを引けばよいということになります。
ところがあがった人はゲームから抜けていくので、単純にPlayersの添字だけをみてはうまく動いてくれません。
自分があがっているときとそうでないときで処理をわけました。自分があがったらライバル同士で終わるまで戦わせます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public partial class Form1 : Form { void RivalsTurn() { IsMyTurn = false; RivalsTurn1(); // 自分があがったあとはライバル同士で終わるまで戦わせる if(Players[0].IsFinished) { while(RivalsTurn2() >= 2) ; } // ライバルのターンが終わったら自分のターンへ IsMyTurn = true; // パネルを更新する panel1.Invalidate(); panel2.Invalidate(); } } |
これは自分があがる前におけるライバルの動作をメソッドにしたものです。
すでにあがっているプレイヤーもいるかもしれないので、まずはまだあがっていないプレイヤーを集めます。そしてPlayersのインデックスが大きい側が小さい側のカードを引きます。ユーザーのインデックスは0なのでとくにややこしいことはありません。
ババ抜きではカードを1枚だけ持っているときにカードを引き、ペアができてあがることができるだけでなく、ペアができてカードを捨てた結果、残り1枚になり、次のプレイヤーに引かせてあがることができる場合もあります。
どちらにでも対応できるようにカードを引いたり引かせたプレイヤーのカード数を確認して、あがりの処理をおこなっています。
あがりの処理として、IsFinishedプロパティを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 35 36 37 38 39 40 |
public partial class Form1 : Form { int RivalsTurn1() { // インデックスが大きい側が小さい側からカードを引く // まだあがっていないプレイヤーを集める List<Player> players1 = Players.Where(x => !x.IsFinished).ToList(); int playersCount = players1.Count; // ユーザーがあがっていないのであれば「1」から for(int i = 1; i < playersCount; i++) { if(players1[i].Cards.Count != 0) { int rand = random.Next(0, players1[i - 1].Cards.Count); players1[i].PullCard(players1[i - 1], rand); // カードを引いたり引かせることであがってしまうかもしれない if(players1[i].Cards.Count == 0) { players1[i].IsFinished = true; PlayerFinished(players1[i]); } if(players1[i-1].Cards.Count == 0) { players1[i - 1].IsFinished = true; PlayerFinished(players1[i - 1]); } } } return Players.Count(x => !x.IsFinished); } void PlayerFinished(Player player) { // 後述 } } |
次に自分があがってしまったあとの処理です。この場合、基本的にインデックスが大きい側が小さい側からカードを引くことになるのですが、一番インデックスが最小のものは最大のものからカードを引くことになります。
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 |
public partial class Form1 : Form { int RivalsTurn2() { // まだあがっていない人を集める List<Player> players1 = Players.Where(x => !x.IsFinished).ToList(); int playersCount = players1.Count; // ユーザーはあがっているので「0」から for(int i = 0; i < playersCount; i++) { if(players1[i].Cards.Count != 0) { int from; // 誰からカードをもらうか from = i - 1; if(from < 0) from = playersCount - 1; int rand = random.Next(0, players1[from].Cards.Count); players1[i].PullCard(players1[from], rand); // カードを引いたり引かせることであがってしまうかもしれない if(players1[i].Cards.Count == 0) { players1[i].IsFinished = true; PlayerFinished(players1[i]); } if(players1[from].Cards.Count == 0) { players1[from].IsFinished = true; PlayerFinished(players1[from]); } } } return Players.Count(x => !x.IsFinished); } } |
順位を表示する
カードの持ち数がゼロになったらあがりなので順位を表示します。また最下位はカードの持ち数がゼロにできないので最下位のひとつ上の順位が確定した段階でビリが確定することになります。
PlayerFinishedメソッドはRivalsTurnメソッドのループ文のなかで呼ばれるので二重に呼ばれてしまうことがあります。そこであがったプレイヤーを格納するリストを作成して二重に格納できないようにしています。これで順位が二重に表示されることはありません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public partial class Form1 : Form { List<Player> finishedPlayers = new List<Player>(); int rank = 1; void PlayerFinished(Player player) { if(!finishedPlayers.Any(x => x == player)) { finishedPlayers.Add(player); string str = String.Format("{0}位は{1}です", rank++, player.Name); MessageBox.Show(str); if(Players.Count-1 == finishedPlayers.Count) { string name = Players.Except(finishedPlayers).ToList()[0].Name; string str1 = String.Format("{0}が最下位です", name); MessageBox.Show(str1); } } } } |
それからPlayerFinishedメソッドで使用したフィールド変数はゲーム開始時に初期化するようにしましょう。
1 2 3 4 5 6 7 8 9 10 11 12 |
public partial class Form1 : Form { void GameStart() { rank = 1; finishedPlayers.Clear(); // これより下は変わらず // 省略 } } |