前回はライバル側の動作に関するメソッドを考えました。
今回はプレイヤー側について考えます。
Contents
自分のジョーカーを表示させる
カードが配り終えたとき、手元にジョーカーがあるなら表示させる必要があります。これまではカードを4種類にわけてソートしてから表示させていましたが、ジョーカーが手元にあるのであればこれも表示させないといけません。
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 |
public partial class Form1 : Form { void ShowMyCards(Graphics g) { if(playersCards[0] == null || playersCards[0].Count == 0) return; List<Card> cards1 = new List<Card>(); cards1.AddRange(playersCards[0].Where(x => x.Mark == CardMark.spade).OrderBy(x => x.Number)); cards1.AddRange(playersCards[0].Where(x => x.Mark == CardMark.hart).OrderBy(x => x.Number)); cards1.AddRange(playersCards[0].Where(x => x.Mark == CardMark.dia).OrderBy(x => x.Number)); cards1.AddRange(playersCards[0].Where(x => x.Mark == CardMark.club).OrderBy(x => x.Number)); cards1.AddRange(playersCards[0].Where(x => x.Mark == CardMark.joker).OrderBy(x => x.Number)); // これを追加 playersCards[0] = cards1; int i = 20; foreach(var card in cards1) { Point pt = new Point(i, 450); card.CopyDrawCard(g, pt); i += 70; } } } |
パスのときの処理
出せるカードがない場合は自動的にMyPassメソッドが呼ばれていましたが、これを書き直します。
出せるカードがなくてもジョーカーなら出せる
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 partial class Form1 : Form { bool isTakingOutJoker = false; void MyPass() { var myCards = playersCards[0]; // ジョーカーしかもっていないのであれば失格 if(myCards.Count == 1 && myCards[0].Mark == CardMark.joker) { string str = String.Format("ジョーカーしかもっていないのであなたは失格です"); MessageBox.Show(str, "報告", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); // 失格の表示をさせるための処理 passCounts[0] = PASS_MAX + 1; ShowPlayerInfo(0); return; } // ジョーカーをもっているのであれば出させる if(myCards.Any(x => x.Mark == CardMark.joker)) { MessageBox.Show( "ジョーカーを使用します。出したいカードの位置をクリックしてください。", "", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); isTakingOutJoker = true; return; } // これ以降はこれまでのパス時と同じ処理 // 省略 } } |
勝手にゲームがはじまってしまう問題点を解決
カードが配り終わって1回目のターンで出せるカードがないけどジョーカーをもっている場合、「ジョーカーを使用します。出したいカードの位置をクリックしてください」というメッセージボックスが出るのですが、メッセージボックスが消えるとライバルが勝手にカードを置き始めます。
この問題は以下の方法で解決できます。OnRivalsTurnが呼ばれても自分のターンのときはなにもさせません。
1 2 3 4 5 6 7 8 9 10 11 |
public partial class Form1 : Form { async void OnRivalsTurn() { if(IsMyTurn) return; // 以下は変更なし // 省略 } } |
ジョーカーを出すための処理
ジョーカーを使うときはカードを出したい位置をクリックすることにします。これまでユーザーがクリックするときは出したいカードを指定するときでした。今回はそれとは違うのでフィールド変数 isTakingOutJokerで処理を切り分けます。
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 Form1_MouseClick(object sender, MouseEventArgs e) { if(!IsMyTurn) return; if(playersCards == null) return; var playerCards = playersCards[0]; int cardsCount = playerCards.Count; if(cardsCount == 0) return; if(!isTakingOutJoker) MouseClickForTakeCard(e); else MouseClickForTakeJoler(e); ShowPlayerInfo(0); if(!IsMyTurn) { OnRivalsTurn(); } } } |
MouseClickForTakeCardは普通にカードを出すときのメソッドです。ジョーカーをクリックするとメッセージボックスが表示されます。
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 partial class Form1 : Form { void MouseClickForTakeCard(MouseEventArgs e) { var playerCards = playersCards[0]; int cardsCount = playerCards.Count; for(int i = 0; i < cardsCount; i++) { Rectangle rect = GetMyCardRectangle(i); if(rect.Top > e.Y) return; if(rect.Bottom < e.Y) return; if(rect.Left < e.X && e.X < rect.Right) { int num = playerCards[i].Number; CardMark mark = playerCards[i].Mark; if(mark == CardMark.joker) { isTakingOutJoker = true; MessageBox.Show( "ジョーカーを使用します。出したいカードの位置をクリックしてください。", "", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); return; } if(!CanTakeout(mark, num)) { MessageBox.Show("このカードは出せません!", "", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } IsMyTurn = false; Card card = playerCards.First(x => x.Mark == mark && x.Number == num); playerCards.Remove(card); card.isExists = true; Invalidate(); break; } } } } |
MouseClickForTakeJolerメソッドはジョーカーを使用するときに呼ばれるメソッドです。どの部分がクリックされたかでどのカードを出すか判断しています。
自分が持っているカードのかわりにジョーカーは使えない
自分が持っているカードのかわりにジョーカーは使えません。出せないカードの位置やカードがおけない場所をクリックしたときにはOnMouseClickJoler_NoUseメソッドが呼ばれます。
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 |
public partial class Form1 : Form { void MouseClickForTakeJoler(MouseEventArgs e) { var myCards = playersCards[0]; var CanTakeoutCards = GetCanTakeout(); foreach(Card card in CanTakeoutCards) { Rectangle rect = new Rectangle(card.Point, Card.Size); if(rect.Top > e.Y) continue; if(rect.Bottom < e.Y) continue; if(rect.Left < e.X && e.X < rect.Right) { // 自分が持っているカードのかわりにジョーカーは使えない if(myCards.Any(x => x == card)) { OnMouseClickJoler_NoUse(); return; } // 手持ちのカードからジョーカーを取り除く Card joker = myCards.First(x => x.Mark == CardMark.joker); myCards.Remove(joker); OnUseJoker(joker, card); Invalidate(); isTakingOutJoker = false; IsMyTurn = false; break; } } // 検討はずれな場所がクリックされた if(IsMyTurn) OnMouseClickJoler_NoUse(); } } |
不正な場所がクリックされたときの処理
不正な場所がクリックされたときは「ここにはジョーカーは使えません!」「ジョーカーを使うのはやめますか?」というメッセージボックスを表示して通常モードに戻すかジョーカーを使うかをユーザーに問うようにしています。
1 2 3 4 5 6 7 8 9 10 11 |
public partial class Form1 : Form { void OnMouseClickJoler_NoUse() { MessageBox.Show("ここにはジョーカーは使えません!", "", MessageBoxButtons.OK, MessageBoxIcon.Error); DialogResult dr = MessageBox.Show("ジョーカーを使うのはやめますか?", "", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if(dr == DialogResult.Yes) isTakingOutJoker = false; } } |