C#でつくる素数大富豪、完成品はこんな感じです。

これまでコンピュータの次の一手を考えることだけを考えてきましたが、今回は自分(=プレイヤー)と対戦できるものをつくります。実験的なアプリなのでカードを表示させてカードゲームっぽく見せることはしません。数字が表示されるだけです。

まずコンピュータとプレイヤーの2人で対戦します。そこで両者が持っているカードを格納しているリストを示します。トランプを使うのでスート(スペードとかダイヤとか)があるのですが、いまは考えないことにします。

それから親が出せるカードの枚数を決めるとともに、次のプレイヤーは前のプレイヤーよりも大きな数を出さなければなりません。そこで出すことができる枚数とそれよりも大きな数を出さなければならない数をフィールド変数で管理します。もし-1であれば自分が親であり、好きな枚数で好きな数を出すことができます。

プレイヤーの動作に関する処理

ゲームが開始されたらコンピュータとプレイヤーにカードが配られ、ゲームが開始されます。その処理を示します。最初はプレイヤーが親で始まります。

出すカードを選ぶ

出したいカードをボタンをクリックすることで選択します。存在しないカードは選択できないのでその場合は灰色表示します。これは後述するEnableNumberButtonメソッドでおこないます。そのときキャンセルされることもあるのでプレイヤーのカードを別のリストにコピーしておきます。

プレイヤーがカードを出すためには数字が書かれたボタンを押します。どのボタンが押されたらその番号をもつカードが出されるかがわかるようにしておかなければなりません。その役割をしているのがGetNumberFromButtonメソッドです。

数字が書かれたボタンをクリックしたときの処理を示します。ボタンがクリックされるときは素数としてカードを出すときにクリックされるときと、合成数出しで素因数を指定する場合があります。これはCheckBoxで区別しています。

またカードが出されたら、そのカードはなくなってしまうのでボタンをクリックすることができなくなるかもしれません。そこでEnableNumberButtonメソッドを呼び出して、ボタンをクリックできるできないをセットしなおしています。

ボタンをクリックすることでプレイヤーが持っているカードを出すことができるのですが、もしプレイヤーがそのカードを持っていないのであればそのボタンはクリックできないようにしなければなりません。GetNumberFromButtonメソッドはそのためのメソッドです。

合成数出しをする場合、素因数を複数指定することになります。かけ算の記号である×をクリックすると素因数として確定され、これをPrimefactors内に格納します。

出されたカードの正当性のチェック

プレイヤーによって出すカードが確定し、決定ボタンがクリックされたときの処理を示します。

ここでは最初に本当に出せるカードなのかを調べます。場に出せるカードはそのとき親でなければ制約があります。もし条件を満たしていないのであればカードを出せない旨を表示します。

条件を満たしていれば、素数として出された場合は本当に素数なのか、合成数として出された場合は素因数の計算はあっているのかを調べます。もし合っているのであればカードを出したことにして、PlayerCardsDealtのなかから取り除きます。この処理はCheckPlayerCards1メソッド、またはCheckPlayerCards2メソッドのなかでおこなわれます。

この処理によってプレイヤーのカードがすべてなくなっていればプレイヤーの勝利です。そうでなければコンピュータに手番が移ります。そしてコンピュータの勝利が確定しないのであれば再びプレイヤーの手番となります。

CheckPlayerCards1メソッドとCheckPlayerCards2メソッドはプレイヤーによって出されたカードが正当なものであるかどうかをチェックするためのものです。素数として出された場合はCheckPlayerCards1メソッドで、合成数として出された場合はCheckPlayerCards2メソッドでチェックがおこなわれます。

キャンセルやパスに関する処理

カードが出されたときやゲーム開始のとき、いったん選択されたカードがキャンセルされたときはPlayerPutCards1やPlayerPutCards2などに格納されているデータをすべてクリアしなければなりません。InputDataClearメソッドはそのためのものです。

うっかりミスで出せないカードを選択してしまう場合もあるかもしれないので、この場合は選択したカードをすべてクリアできる手段を用意しました。

プレイヤーがカードを一枚山札から取るための処理です。1ターンにつきカードを取れるのは1回だけです。そのためこれを実行するとボタンが灰色表示になります。

出せるカードがない場合、戦略的にパスをしたい場合に対応するためのパスの処理です。

コンピュータが手番のときの処理

コンピュータが手番のときの処理を示します。

コンピュータの手番のときに出せるカードを決めるための処理を示します。SearchNumberメソッドの引数が増えています。カードはなんでも出せるわけでなく、前のプレイヤーと同じ枚数のカードを出すとともにそれよりも大きな数でなければならないからです。

これはコンピュータがカードを出したとき(出せなかったとき)にその結果を表示するためのメソッドです。コンピュータの手持ちのカードがすべてなくなっていればゲームは終了です。

実際に対戦してみたら散々な結果になりました。