これまでパスは何回でもできましたが(そもそもパスの回数をカウントすらしていない)、パスできる回数には制限がある場合がほとんどであり、すでに定められた回数のパスをしているにも関わらず出せるカードがない場合は失格となります。
そしてゲームの途中でプレイヤーが脱落したら、そのプレイヤーがもっている手札は、場の該当箇所に置いた後、残りのプレイヤーはゲームを続けることになります。この場合、出せるカードを取得するときの処理が変わってきます。
まず各プレイヤーがすでに何回パスをしているか記憶しておく必要があります。これはint型の配列でよいかと思います。
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 |
public partial class Form1 : Form { int[] passCounts = new int[4]; int PASS_MAX = 3; // パスは3回まで void GameStart() { for(int i = 0; i< passCounts.Length; i++) passCounts[i] = 0; ranking = 1; isAgari = false; // ゲームスタート前の段階なのでだれもカードは持っていない。 // 全プレイヤーのカードをリセットする playersCards[0].Clear(); playersCards[1].Clear(); playersCards[2].Clear(); playersCards[3].Clear(); foreach(Card card in cards) card.isExists = false; Invalidate(); // テーブル上のカードをクリア // カードを配って7があれば出す HandoutCards(); Takeout7(); ShowPlayerInfo(0); ShowPlayerInfo(1); ShowPlayerInfo(2); ShowPlayerInfo(3); // まずは自分の手番でゲームスタート IsMyTurn = true; // だがほんとうにカードは出せるのか? if(!CanPlayerTakeoutCard(0)) { MyPass(); // 新しく作成したメソッド OnRivalsTurn(); } } } |
自分がパスしたときの処理をするメソッドとしてMyPassを作成しました。パスの回数を記憶しておき、4回パスをしたら失格にします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public partial class Form1 : Form { // 自分がパスしたときの処理をするメソッド void MyPass() { IsMyTurn = false; passCounts[0]++; if(passCounts[0] <= PASS_MAX) { string str = String.Format("出せるカードがないのでパスします。パス{0}回目", passCounts[0]); MessageBox.Show(str, "報告", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); } else { string str = String.Format("出せるカードがありません。{0}回パスをしたので失格です。", passCounts[0]); MessageBox.Show(str, "報告", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); } ShowPlayerInfo(0); } } |
RivalPassはライバルがパスをしたときの処理をするメソッドです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public partial class Form1 : Form { void RivalPass(int rivalID) { passCounts[rivalID]++; if(passCounts[rivalID] <= PASS_MAX) { string str = String.Format("{0} はパスしました(パス{1}回目)", rivalID, passCounts[rivalID]); MessageBox.Show(str, "報告", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); } else { string str = String.Format("{0} はパスしました。{1}回パスをしたので失格です", rivalID, passCounts[rivalID]); MessageBox.Show(str, "報告", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); } ShowPlayerInfo(rivalID); } } |
ライバルの手番で出せるカードがない場合、RivalPassが実行されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public partial class Form1 : Form { void RivalTurn(int rivalID) { var rivalCards = playersCards[rivalID]; List<Card> canCards = rivalCards.Intersect(GetCanTakeout()).ToList(); if(canCards.Count != 0) { // ライバルがカードを出せるときの処理 } else { // ライバルがカードを出せないときRivalPassが実行される RivalPass(rivalID); } ShowPlayerInfo(rivalID); } } |
自分がカードを出したときに相手のターンになりますが、そのときに相手があがっているときだけで失格のときもスキップする必要があります。
自分があがってしまった後や失格になったときもライバルがゲーム続行可能のときは続行します。すべてのプレイヤーがあがるか失格になったらゲーム終了です。
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 |
public partial class Form1 : Form { async void OnRivalsTurn() { // ライバルに手番が回ったときあがっているかもしれない if(playersCards[0].Count == 0 && !isAgari) { ShowRanking("あなた"); isAgari = true; } // あがっているか失格のときは飛ばす if(playersCards[1].Count != 0 && passCounts[1] <= PASS_MAX) { await System.Threading.Tasks.Task.Delay(1000); RivalTurn(1); if(playersCards[1].Count == 0) ShowRanking("1"); } if(playersCards[2].Count != 0 && passCounts[2] <= PASS_MAX) { await System.Threading.Tasks.Task.Delay(1000); RivalTurn(2); if(playersCards[2].Count == 0) ShowRanking("2"); } if(playersCards[3].Count != 0 && passCounts[3] <= PASS_MAX) { await System.Threading.Tasks.Task.Delay(1000); RivalTurn(3); if(playersCards[3].Count == 0) ShowRanking("3"); } // 自分があがっているか失格になっているなら飛ばす if(isAgari || passCounts[0] > PASS_MAX) { // アガれていない、失格にもなっていないプレイヤーがいるならライバルだけでゲームは続行される // 全員アガっているか失格になっているなら終了 if( (playersCards[1].Count != 0 && passCounts[1] <= PASS_MAX) || (playersCards[2].Count != 0 && passCounts[2] <= PASS_MAX) || (playersCards[3].Count != 0 && passCounts[3] <= PASS_MAX) ) OnRivalsTurn(); else MessageBox.Show("ゲーム終了です"); return; } // 順番が回ってきたけど出せるカードがない場合は強制パス if(!CanPlayerTakeoutCard(0)) { MyPass(); OnRivalsTurn(); } else IsMyTurn = true; } } |
カードを出したときやパスをしたときに残りのカード数やパスできる回数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public partial class Form1 : Form { void ShowPlayerInfo(int player) { int cardCount = playersCards[player].Count; string str = String.Format("カード残り{0}枚 パス残り{1}回", cardCount, PASS_MAX - passCounts[player]); if(PASS_MAX - passCounts[player] < 0) str = "失格"; if(player == 0) StatusLabelPlayerinfo0.Text = str; if(player == 1) StatusLabelPlayerinfo1.Text = str; if(player == 2) StatusLabelPlayerinfo2.Text = str; if(player == 3) StatusLabelPlayerinfo3.Text = str; } } |
これで失格の判定はできるようになりましたが、失格になったら手持ちのカードをテーブルの上に出さないといけません。そのための処理が必要なのとこの処理によって出せるカードがどれなのか判定する方法を考え直す必要があります。
失格になったときに呼び出されるメソッドはこんな感じになります。
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 |
public partial class Form1 : Form { void RivalPass(int rivalID) { passCounts[rivalID]++; if(passCounts[rivalID] <= PASS_MAX) { string str = String.Format("{0} はパスしました(パス{1}回目)", rivalID, passCounts[rivalID]); MessageBox.Show(str, "報告", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); } else { // 失格確定 string str = String.Format("{0} はパスしました。{1}回パスをしたので失格です", rivalID, passCounts[rivalID]); MessageBox.Show(str, "報告", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); // 失格になったら呼び出される OnRivalLost(rivalID); } } void OnRivalLost(int rivalID) { // 手持ちのカードをテーブルの上に出す var playerCards = playersCards[rivalID]; foreach(Card card in playerCards) card.isExists = true; Invalidate(); } } |
ただこれだとGetCanTakeoutメソッドが正しく機能しません。次回、つくりなおします。