ここでやろうとしていることはコンピュータが出すカードを決めるアルゴリズムの研究です。人間であるプレーヤーが出したカードであれば実際に計算をして素数なのか、適切な合成数出しなのかを比較的簡単に調べることができますが、コンピュータのターンである場合は適切なカードをアルゴリズムで探し出さなければなりません。

前回のコンピュータが出せるカードを調べる C#で素数大富豪をつくる(2)ではおおざっぱな方法で出すことができる合成数を調べました。しかし前回示したコードでは本当に出すことができるカードなのか正確にはわかりません。

ある合成数を手持ちの素数で割り続けて1になるかどうかでは「合成数出しが可能であるかもしれないカード」ということはできても、本当に出せるカードであると断定はできません。

たとえばすべてのカードが、3, 5, 5, 5, 6, 6, 6, 6, 7, 10, 10, 11, 11のとき、3, 10, 7, 5を使って合成数31075をつくることができ、しかも素因数分解可能 5 5 11 113に素因数分解することができます。ところが31075をつくることによって残るカードは5, 5, 6, 6, 6, 6, 10, 11, 11であり、素因数113をつくることができません。そこで手持ちのカードで素因数分解できても合成数を作ったり他の素因数をつくるためにカードが足りなくなっていないか検証が必要なのです。

2段階戦術でコンピュータが出せる合成数を求める

そこで手持ちのカードの数すべてと出さなければならない枚数をわたして本当に出せるカードを取得するメソッドをつくります。戻り値はResultCardsオブジェクトのリストです。

ResultCardsクラス

以下はResultCardsクラスです。

それから素数とカードの番号の関係がわかるように以下のクラスも作成します。

GetCardsCanPutメソッド

それでは手持ちのカードから出すことができるカードを返すGetCardsCanPutメソッドを示します。

試運転

実際に処理を行なってみましょう。

一番最初に取得された合成数を表示させています。以下は実行結果の一例です。

たしかに合成数として場に出すカードと素因数場に出されるカードはすべて配布されたカードのなかにあり、11×7583の計算結果は83,413であり、11と7583はそれぞれ素数です。GetCardsCanPutメソッドは正しく動作しているといえます。