特殊なカード
によるとカードのなかには特殊な役割をするものがあることがわかります。
A
次にだすはずの人をとばして、その次の人に順番が回ります。
2
カード出した次の順番の人は手札を出すことができず、積み札からカードを2枚とって手札にくわえなければなりません。ただし次の人も2を持っていたらこれを出すことができます。そして更に次の人が2を出すことができない場合は4枚とらなくてはなりません。2が出される限り、2倍2倍と増えていきます。UNOのDraw Twoのようなものと考えることができます。
8
UNOのWild カードのように台札に関係なく出せるカードです。8が出されたときは、次の人は8と同じ色のスートのカードか8を出します。
J
カードを出す順番は最初は時計回りですが、これを逆回りにすることができます。
A スキップされる処理
まずAが出された場合は、最後に出されたカードは「A」かどうかを表すフィールド変数を使って以下のようにすればなんとかなりそうです。
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 |
public partial class Form1 : Form { bool isLastCardA = false; // 最後に出されたカードは「A」か? bool RivalsTurn() { // 0 は自分なのでライバルではない List<Player> rivals = Players.Skip(1).ToList(); foreach(Player player in rivals) { bool isFinish = false; System.Threading.Thread.Sleep(500); // Aが出されていたらスキップ if(CenterCard.Number == 1 && isLastCardA) { isLastCardA = false; continue; } CenterCard = player.PutCard(CenterCard, ShuffledCards); if(CenterCard.Number == 1) isLastCardA = true; if(player.Cards.Count == 0) { isFinish = true; MessageBox.Show(player.Name + "が あがりました"); } // 出されたカードに他のプレイヤーはドボンできるか? if(DobonIfCan(player)) return false; // あがった人に誰もドボンしなかったらゲーム終了 if(isFinish) return false; } // ループが終わったらあなたのターンになるのだが・・・ // Aが出ているときはスキップされる if(CenterCard.Number == 1 && isLastCardA) { Text = "スキップされました"; System.Threading.Thread.Sleep(500); isLastCardA = false; return RivalsTurn(); } if(!AddCardIfCanNotPutCard()) return true; else return RivalsTurn(); } } |
自分がカードを出したときは・・・
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 { private void panelSouth_MouseDown(object sender, MouseEventArgs e) { Card card = GetClickedCard(e); if(CheckUnjustClick(card)) return; Players[0].Cards.Remove(card); CenterCard = card; panelSouth.Invalidate(); if(CenterCard.Number == 1) isLastCardA = true; if(CenterCard.Number == 2) drawTwoCount = 1; // ドボンされる可能性があるのでチェックする if(DobonIfCan(Players[0])) return; // カードがなくなったらあがり if(Players[0].Cards.Count == 0) { OnMyFinish(); return; } RivalsTurnAsync(); } } |
新しく作成したCheckUnjustClickメソッドはクリックが不正であるかどうかを判定するためのものです。
自分の番ではないのにクリックした、カードがない場所をクリックした、出せないカードをクリックした場合にメッセージボックスが表示されます。
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 { bool CheckUnjustClick(Card card) { if(!IsMyTurn) { MessageBox.Show("まだあなたの番ではありません"); return true; } if(card == null) { panelSouth.Invalidate(); MessageBox.Show("カードがある位置をクリックしてください"); return true; } if(CenterCard.Suit != card.Suit && CenterCard.Number != card.Number) { MessageBox.Show("このカードは出せません"); return true; } return false; } } |
それから自分のカードがなくなったときもドボンされる可能性があります。これは手持ちのカードを出し終わったときに実行されるメソッドです。
1 2 3 4 5 6 7 8 9 10 11 |
public partial class Form1 : Form { void OnMyFinish() { MessageBox.Show(Players[0].Name + "が あがりました"); // 出されたカードに他のプレイヤーはドボンできるか? if(! DobonIfCan(Players[0])) MessageBox.Show(Players[0].Name + "の勝ちです"); } } |
2 カードを2枚(またはそれ以上)とらされる
また2を出したときの処理ですが、2が出されたあと次のプレイヤーは2を持っているなら出し持っていないならカードを取らないといけません。またそのときのカードの枚数をカウントする必要があります。
まずは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 38 39 40 41 42 43 44 45 46 47 |
public class Player { public Card DrawTwo(Card card, List<Card> shuffledCards, int count) { // 積み札がなくなったらすでに出されているカードを使う。 if(shuffledCards.Count == 0) _form1.ShuffleCard(card); // 出せるカードを求める List<Card> cards1 = Cards.Where(x => x.Number == 2).ToList(); Card ret = null; if(cards1.Count == 1) { Cards.Remove(cards1[0]); ret = cards1[0]; System.Threading.Thread.Sleep(1000); PlayerPanel.Invalidate(); count++; return ret; } else if(cards1.Count > 1) { // 複数ある場合 int index = Random.Next(cards1.Count); Card card1 = cards1[index]; Cards.Remove(card1); ret = card1; System.Threading.Thread.Sleep(1000); PlayerPanel.Invalidate(); count++; return ret; } double cnt = Math.Pow(2, count); for(int i=0; i< cnt; i++) { Card addCard = shuffledCards[0]; shuffledCards.RemoveAt(0); Cards.Add(addCard); System.Threading.Thread.Sleep(200); PlayerPanel.Invalidate(); } return null; } } |
上記のメソッドをライバルのターン、ライバルのターンが終わって自分のターンに変わるときに呼べばうまくいきそうです。
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 |
public partial class Form1 : Form { int drawTwoCount = 0; // 2を出せないときは 2のdrawTwoCount乗だけカードをとらされる bool RivalsTurn() { // 0 は自分なのでライバルではない List<Player> rivals = Players.Skip(1).ToList(); foreach(Player player in rivals) { bool isFinish = false; // カードを出すときにプレイヤーごとに少し止める System.Threading.Thread.Sleep(500); // Aが出されていたらスキップ if(CenterCard.Number == 1 && isLastCardA) { isLastCardA = false; continue; } // 2が出されていたら2を出すか2のn乗枚のカードをとる if(CenterCard.Number == 2 && drawTwoCount > 0) { OnWasPut2(player); continue; } // その他のときは普通にカードを出す CenterCard = player.PutCard(CenterCard, ShuffledCards); if(CenterCard.Number == 1) isLastCardA = true; if(CenterCard.Number == 2) drawTwoCount = 1; if(player.Cards.Count == 0) { isFinish = true; MessageBox.Show(player.Name + "が あがりました"); // あがったときもドボンされる可能性がある } // 出されたカードに他のプレイヤーはドボンできるか? if(DobonIfCan(player)) return false; if(isFinish) return false; } // ループが終わったらあなたのターンになるのだが・・・ // Aが出ているときはスキップされる if(CenterCard.Number == 1 && isLastCardA) { Text = "スキップされました"; System.Threading.Thread.Sleep(500); isLastCardA = false; return RivalsTurn(); } // 2が出ているときは2を出すかカードを取らされる if(CenterCard.Number == 2 && drawTwoCount > 0) { OnWasPutTwo(Players[0]); return RivalsTurn(); } if(!AddCardIfCanNotPutCard()) return true; else return RivalsTurn(); } } |
OnWasPutTwoは2が出されていたときのプレイヤーの動作に関するメソッドです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public partial class Form1 : Form { void OnWasPutTwo(Player player) { // 2を出すか2のn乗枚のカードをとる Card card = player.DrawTwo(CenterCard, ShuffledCards, drawTwoCount); if(card == null) drawTwoCount = 0; else { CenterCard = card; panelCenter.Invalidate(); drawTwoCount++; } } } |
それから自分が2を出してライバルにカードを取らせる場合も考えられます。
自分が出したカードが2であれば、ライバルに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 |
public partial class Form1 : Form { private void panelSouth_MouseDown(object sender, MouseEventArgs e) { Card card = GetClickedCard(e); if(CheckUnjustClick(card)) return; Players[0].Cards.Remove(card); CenterCard = card; // カードがなくなったらあがり(ただしドボンの可能性あり) if(Players[0].Cards.Count == 0) { OnMyFinish(); return; } if(CenterCard.Number == 1) isLastCardA = true; if(CenterCard.Number == 2) drawTwoCount = 1; panelSouth.Invalidate(); RivalsTurnAsync(); } } |
失礼いたします。
OnMyFinishメソッド内のif文で使用されている、playerの変数が宣言がされておりません
>OnMyFinishメソッド内のif文で使用されている、playerの変数が宣言がされておりません
記事を訂正しました。