今度は自分だけでなく相手(コンピュータ)もカードを出せるようにします。
そのためには自分の番なのかどうかがわかるようにする必要があります。クリックしたとき自分の番ではない場合、なにもおきません。
クリックされたときの処理は前回とほとんど変わりません。最初にisMyTurnがfalseのときはなにもできないようにしたのと、カードを出したあと相手に手番を渡すようにしています。
コンピュータの処理が早いので、1人分が終わったら1秒間なにもしないで待つようにしています。
それから自分の番であってもカードが出せない場合もありますが、前回はそのときはどうすることもできませんでした。そこで順番がまわってきたときにカードが出せるかどうかを調べて、出せるカードがないときはパスするようにしました。
IsMyTurnプロパティは自分の番なのかどうかを知るためのものです。自分の番のときはステータスバーに「あなたの番です」と表示させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public partial class Form1 : Form { bool isMyTurn = false; bool IsMyTurn { get { return isMyTurn; } set { isMyTurn = value; if(isMyTurn == true) toolStripStatusLabel1.Text = "あなたの番です"; else toolStripStatusLabel1.Text = "しばらくお待ちください"; } } } |
それからこのままではステータスバーに文字を表示させる部分の背景が緑色になってしまうので、コンストラクタで初期化しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 |
public partial class Form1 : Form { public Form1() { // ここから上 変わらず // ステータスバーの表示を初期化する toolStripStatusLabel1.BackColor = Color.White; toolStripStatusLabel1.Text = ""; } } |
まずゲームがはじまったときの処理です。
順番が回ってきたらカードが出せるか調べて出せない場合は自動的にパスします。そうでない場合はカードをクリックしたら出すことができます。
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 GameStart() { // カードを配って7があれば出す HandoutCards(); Takeout7(); // まずは自分の手番でゲームスタート IsMyTurn = true; //isGaming = true; // だがほんとうにカードは出せるのか? if(!CanPlayerTakeoutCard(0)) { IsMyTurn = false; MessageBox.Show("出せるカードがないのでパスします", "報告", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); OnRivalsTurn(); } } } |
CanPlayerTakeoutCardメソッドはそれぞれのプレイヤーがカードを出せるか調べるメソッドです。引数が0のときは自分自身を対象としています。
1 2 3 4 5 6 7 8 9 10 11 |
public partial class Form1 : Form { bool CanPlayerTakeoutCard(int player) { List<Card> cards = GetCanTakeout(); if(playersCards[player].Intersect(cards).Count() != 0) return true; else return false; } } |
出すことができるカードをクリックするとカードを出します。相手の手番のときにクリックしてもなにもおきません。そしてカードを出すと相手に手番を回します。
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 |
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; 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(!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; } } if(!IsMyTurn) { OnRivalsTurn(); } } } |
相手役3人分をコンピュータにやらせます。処理が早すぎるので1人分が終わったら1秒間なにもしないで待つようにしています。
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 { async void OnRivalsTurn() { await System.Threading.Tasks.Task.Delay(1000); RivalTurn(1); await System.Threading.Tasks.Task.Delay(1000); RivalTurn(2); await System.Threading.Tasks.Task.Delay(1000); RivalTurn(3); if(!CanPlayerTakeoutCard(0)) { IsMyTurn = false; MessageBox.Show("出せるカードがないのでパスします", "報告", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); OnRivalsTurn(); } else IsMyTurn = true; } } |
RivalTurnメソッドは各相手にカードを出させるためのメソッドです。カードが出せるかどうか調べて出せるなら出させます。また再描画はフォーム全体に対してだと処理が遅くなるので出されたカードの部分だけにしています。
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 RivalTurn(int rivalID) { var rivalCards = playersCards[rivalID]; List<Card> canCards = rivalCards.Intersect(GetCanTakeout()).ToList(); if(canCards.Count != 0) { int next = random.Next(0, canCards.Count); Card nextCard = canCards[next]; rivalCards.Remove(nextCard); nextCard.isExists = true; Rectangle rectInvalidate = new Rectangle(nextCard.Point, Card.Size); Invalidate(rectInvalidate); } else { MessageBox.Show(rivalID + " はパスしました"); } } } |
これだとカードがすべてなくなっても「パスしました」と表示され続けることになります。アガったのであればアガリの扱いをします。
1 2 3 4 5 |
public partial class Form1 : Form { int ranking = 1; bool isAgari = false; } |
これらのフィールド変数を使うのであれば、ゲーム開始時に初期化が必要です。
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 partial class Form1 : Form { void GameStart() { 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(); // まずは自分の手番でゲームスタート IsMyTurn = true; // だがほんとうにカードは出せるのか? if(!CanPlayerTakeoutCard(0)) { IsMyTurn = false; MessageBox.Show("出せるカードがないのでパスします", "報告", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); OnRivalsTurn(); } } } |
あとは相手のターンのときに
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 |
public partial class Form1 : Form { async void OnRivalsTurn() { // ライバルに手番が回ったときあがっているかもしれない if(playersCards[0].Count == 0 && !isAgari) { ShowRanking("あなた"); isAgari = true; } // あがっているなら飛ばす if(playersCards[1].Count != 0) { await System.Threading.Tasks.Task.Delay(1000); RivalTurn(1); if(playersCards[1].Count == 0) ShowRanking("1"); } if(playersCards[2].Count != 0) { await System.Threading.Tasks.Task.Delay(1000); RivalTurn(2); if(playersCards[2].Count == 0) ShowRanking("2"); } if(playersCards[3].Count != 0) { await System.Threading.Tasks.Task.Delay(1000); RivalTurn(3); if(playersCards[3].Count == 0) ShowRanking("3"); } // 自分があがっているなら飛ばす if(isAgari) { // アガれていないプレイヤーがいるならライバルだけでゲームは続行される // 全員アガっているなら終了 if(playersCards[1].Count != 0 || playersCards[2].Count != 0 || playersCards[3].Count != 0) OnRivalsTurn(); return; } // 順番が回ってきたけど出せるカードがない場合は強制パス if(!CanPlayerTakeoutCard(0)) { IsMyTurn = false; MessageBox.Show("出せるカードがないのでパスします", "報告", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); OnRivalsTurn(); } else IsMyTurn = true; } } |
それからShowRankingメソッドがないとコメントで指摘がありました。申し訳ありません。ShowRankingメソッドを示します。これはメッセージボックスをつかって順位を表示させているだけです。
1 2 3 4 5 6 7 8 9 |
public partial class Form1 : Form { void ShowRanking(string name) { string str = String.Format("{0}等は {1} です。", ranking, name); ranking++; MessageBox.Show(str); } } |
失礼いたします。
OnRivalsTurnメソッド内のShowRanking()メソッドが存在しない為、エラーが発生致します
すみません。記事を修正したので確認お願いします。
あとできれば捨てハンでいいのでハンドルネームでお願いします。
adminさん、記事の修正ありがとうございます。
ハンドルネームに関しては承知いたしました。
最近C#の勉強を兼ねて、いつも、拝見させていただいてます。