前回作成した753ゲームはコンピュータ側の着手はランダムに選択していただけなので弱すぎました。今回はこれを改善します。

753ゲーム必勝法

実は753ゲームには必勝法が存在します。

参考:七五三(線引きゲーム)の必勝法 – LnL.jp

これによるとつながっている未選択部分の個数を2進法に変換し、その排他的論理和の合計(以下「排他的論理和の合計」と書く)が0になるように選択すれば勝つことができるようです。もし自分の番になったときに「排他的論理和の合計」が0の場合は勝つことはできません。相手が正しく着手すれば必ず負けることになります。

では自分が着手したあと「排他的論理和の合計」が0になるようにするにはどうすればいいでしょうか?

まず「排他的論理和の合計」の1番左側の1になっている桁を確認します。そしてその桁と同じ桁のビットが立っているグループを探します。そこから選択します。もし該当する箇所が複数ある場合はそのなかのひとつを選びます。

どこから選択するかが決まったら何個を選択するのかを考えます。これはそれ以外のグループのビット毎の排他的論理和の合計を計算します。その数だけ残すように選択をすればよいのです。

例:

最初は7と5と3なので(7 ^ 5 ^ 3)を計算します。計算結果は1です。1番左側の1になっている桁は右から1桁目なので、7と5と3のなかから2進法に変換すると右から1桁目が1であるものを探します。実は7と5と3はいずれも条件に合致しています。そこでここでは7から選択することにします。

では7からいくつ選択すればいいのでしょうか? 5と3の排他的論理和は6なので6個残るように選択します。つまり選択するのは1個だということです。

プレイヤーがミスしたらコンピュータ側を勝たせる

では前回のコードにそのようなアルゴリズムを組み込んでみましょう。

コンピュータ側が勝つ着手をするtoWin関数を示します。上記のアルゴリズムで着手しています。

random関数はコンピュータ側に勝つ手段がない場合にランダムな着手をさせるためのものです。

応用編

753だとパターン化するとすぐにどうすればいいかわかってしまうのでランダムに出題されるようなパズル形式にしてもよいと思います。たとえばこんなのはどうでしょうか?