前回までにババ抜きの大枠完成させました。

コンピュータにカードを引かせてみる C#でババ抜きをつくる

ただ不満な点も残っています。

大枠はできたが不満な点も

相手のカードをクリックしたらすぐにつぎの順番がまわってきます。

また実際に人とババ抜きをするのであれば相手はカードを何枚もっているのか、相手がカードを引いた時カードはそろったのかといった情報も知ることができます。相手がカードをひいて自分に順番が回ってくるまでに一定の時間がかかります。

そこでもっと実際のババ抜きらしいアプリケーションを作成することにします。

相手が持っているカードの数を表示させる

まずは相手がどれだけのカードを持っているのかを表示させましょう。

そこでデザイナで以下のようなユーザーコントロールをつくります。

ユーザーコントロールのサイズは(500, 30)、ラベルを3枚(高さは23ピクセル)貼り付けています。ユーザーコントロールのなまえはUserControlPlayerInfoにしました。

またForm1の下部にpanel3を追加しました。この部分にプレイヤーの数だけユーザーコントロールが追加されます。

CreatePlayerメソッドを以下のように変更します。

実行結果はこうなります。

プレイヤーからこれに対応するユーザーコントロール UserControlPlayerInfoを取得できるように、Playerクラスに以下のプロパティを加えます。

先述のShowPlayerInfoメソッドを以下のように変更すれば、これでプレイヤーの名前と残り枚数、その他の情報を表示させることができます。

またゲームが開始される以前であればなにも表示させる必要はないのでPlayerInfoにはなにも表示されていない状態にしたほうがよいでしょう。

それから表示させるものはプレイヤーの名前、カードの残数、その他情報なので、以下のメソッドも追加しておきます。

GameStartメソッドに以下を追加するとプレイヤーに関するデータが表示されます。

すると実行結果はこんな感じになります。

次にゲームの進行によってカード残数がどのように変更するかを表示させます。

全プレイヤーのカード残数が一気にかわる問題点を改善

これで一応、カードの残数は表示されます。しかし全プレイヤーのカード残数が一気にかわります。できればひとりがカードをひくごとに結果がかわるようにしたいものです。そのほうがゲームの進行が自然にみえます。そこでこのように変更します。

カードを引くたび1秒間停止します。しかしこれだけではうまくいきません。RivalsTurn1の呼び出し元にも変更を加える必要があります。

asyncをつけました。それから

とすることで1秒ごとに結果を表示してくれるようになります。

非同期処理をすると「有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール‘XXXX’がアクセスされました」という例外が発生することがあります。そこでその対策が必要です。

処理中に新しいゲームを開始しようとするとどうなる?

isRivalsTurnというフィールド変数を使用していますが、これはこの処理が行なわれているあいだに[ゲームスタート]をクリックすると、処理が停止されることなく新しくカードが配られてしまうという問題がおきるからです。