今回はプレイヤーが出したカードが正しいものかどうかの判定とコンピュータがカードを出す処理を実装します。

最初に適切なカードが出されたかどうかを判定する処理を実装する前に、カードから素数または合成数を求める処理を示します。

GetNumberメソッドにはListとint[]を引数にするものもありますが、これは前回と同じものです。また素数であるかどうかを判定するIsPrimeNumberメソッドも前回のものと同じです。

決定ボタンが押されたあとの処理

決定ボタンが押されたら出されたカードは素数なのか、または素因数がすべて出されている合成数なのか判定がおこなわれます。ルール上、枚数が間違っていた場合はカードを出すこと自体認められませんが、その条件をクリアしていればカードの正当性が判定され、間違っていた場合はペナルティーを受けることになります。

ペナルティーは間違って出したカードが返されるとともに、出そうとした枚数と同じ数だけ山札からカードを取らなければなりません。いまの段階で全部完璧にはできないので、いまはカードが返されるだけにしています。またグロタンカットやラマヌジャン革命、ジョーカーの存在もいまはカットしています。これはあとで考えます。

途中、await Task.Delay(500)と書かれている部分がありますが、これは出されたカードが正しくなかった場合、すぐにカードをプレイヤーに返されるように見せるためです。これがないとコンピュータがカードを出す処理を終えるまでカードが返されないように見えてしまうのです。

場に出されたカードは自分以外の全員(といっても相手はコンピュータひとりですが……)がパスをしたときに流されますが、相手が素因数場に出したカードは手番が代わると同時に流れます。そのようなルールになっているようです。

自分の手番が終わったらコンピュータの手番になります。ちょっと注意しなければならないこととして、カードを出した直後(パスをした場合も同様)からコンピュータの手番が終了するまでのあいだ、プレイヤーによって他のボタンが押されると困った問題がおきます。そこでボタンを一時的に使用不可にする処理が必要です。これはパスのボタンがクリックされたときも必要です。

これはボタンをまとめて使用可にしたり使用不可にするメソッドです。

以下が決定ボタンが押されたときにおこなわれる処理です。

出されたカードは間違っていないか?

プレイヤーによって出されたカードの正当性をチェックする処理を示します。素数かどうかをみて素数でなければプレイヤーに返されます。素数であれば両者が場に出したカードを一時的に貯めておくCardsPutByAllに格納し、CardsPutByPlayer1内のオブジェクトはクリアしてしまいます。

合成数出しの場合の処理を示します。

コンピュータの手番における処理

コンピュータの手番の処理はCompPutCardsメソッドで行ないます。SearchNumberメソッドで出せるカードを探してカードを出します。

出せるカードを探す

SearchNumberメソッドはコンピュータと対戦できるようにする C#で素数大富豪をつくる(5)のものとほとんど同じです。このメソッドのなかで呼び出されているGetCardsCanPutメソッドはこれと完全に同じです。

カードを探すときはスートは関係ないので手持ちのカードのなかから番号部分だけを取り出してリストをつくり、出せるカードを探しています。

それからResultCardsクラスですが、フィールド変数の名前を変えています。ResultCards.Card1とResultCards.Card2ではカードそのもののような名前なので、番号だけであることがわかりやすいようにResultCards.CardNumbers1、ResultCards.CardNumbers2へと変更しています。

コンピュータが出すべきカードが見つかったら場に出します。このときCardsPutByComp1になにかが入っていれば前のターンで出したカードなのでCardsPutByAllへ移動させます。出せるカードが見つからなかった場合はコンピュータはカードを1枚山札からとってパスをします。

カードを出したときプレイに必要なボタンを一時的に操作不能にしましたが、ボタン操作不能時に勝負がついてしまう場合があります。この場合はゲームスタートのボタンがクリックされたときに他のボタンをクリックできるようにしておかなければならないし、ゲーム終了のときにはゲームスタートのボタンをクリックできるようにしておかなければなりません。

ButtonGameStart_Clickメソッドの最後でEableButtons(true)を実行しておけばよいでしょう。