💬

【Web App】拡張3目並べ

2024/10/06に公開

はじめに

友人とn次元の3目並べについて話題になったので、通常の3目並べを拡張し、2次元のn目並べと3次元のn目並べを実装してみました。
単純に遊びたい方は以下にアクセスしてください(デサインは最低限しかいじってないので目をつぶってもらえると助かります)。動作に不具合などがあれば教えて下さい。

https://tictactoe-app.reflex.run/tictactoe

コード

プロジェクト全体のコードは以下となっています。

https://github.com/maki8maki/WebTicTacToe

3目並べの実装の中身はこちらとなっています。上記のコードでサブモジュールとして参照されています。

https://github.com/maki8maki/TicTacToe/

実装

実装はPythonで行っています。

勝敗の判定

2次元・3次元ともに大半の実装は同じです。
先攻と後攻がそれぞれビンゴ(他に適切な名前が思いつきませんでした...)の候補となるリストを持ち、数字を選択するに連れて候補を削除したり、移動させたりしています。言葉だけでは説明が難しいので、具体例を上げます。以降では2次元でサイズ3の盤面を考え、インデックスは以下の通りです。

|0|1|2|
|3|4|5|
|6|7|8|

初期の候補リストは以下の通りです。縦・横・斜めの計8個が含まれています。

candidates =
    [
        [],
        [],
        [],
        [[0, 1, 2], [0, 3, 6], [3, 4, 5], [1, 4, 7],
         [6, 7, 8], [2, 5, 8], [0, 4, 8], [2, 4, 6]]
    ]

candidates[i] は残りi個選択するとビンゴになる候補となっています。例えば、上の状態で1を選択すると、1を含む候補が移動し、候補リストは以下のように変化します。

candidates =
    [
        [],
        [],
        [[0, 1, 2], [1, 4, 7]],
        [[0, 3, 6], [3, 4, 5], [6, 7, 8],
         [2, 5, 8], [0, 4, 8], [2, 4, 6]]
    ]

さらに、相手が6を選択したとすると6を含む候補が削除され、以下のようになります。

candidates =
    [
        [],
        [],
        [[0, 1, 2], [1, 4, 7]],
        [[3, 4, 5], [2, 5, 8], [0, 4, 8]]
    ]

勝負がつくか、引き分けになるまでこの作業が繰り返されます。この方法では初期の候補リストさえ与えられれば、任意のサイズや次元に対応できます。

コンピュータの選択

ランダム選択と戦略的な選択の2種類を実装しました。前者は未選択の数字からランダムに1つ選ぶだけです。後者は以下のように実装しています。

https://github.com/maki8maki/TicTacToe/blob/main/selector.py#L95-L120

コメントでも書いていますが、自分がリーチしているもの→相手が半分以上埋めている候補の残り(相手の勝利の阻止)→自分が埋めている数が多い候補の残り、の順に見ていき数字を選択します。もし複数の数字がある場合は優先度が大きい順に1つを選びます(self._select_by_priority関数)。優先度は初期候補に現れる回数としています。例えば、2は縦・横で優先度が2、4は縦・横・斜め・斜めで優先度が4になります。

Webページ

WebページはReflexというライブラリを用いて実装しています。Reflexを使うとPythonのみでWebページの作成ができます。

以下のように3次元のものは立体的に盤面を配置しました。これはPythonやReflexではなく、CSSの機能である、skewX(横方向の傾斜)とscaleY(縦方向のスケーリング)を使っています。

3D TictacToe

それ以外については基本的な機能のみを利用しています。盤面をクリックしたときには数字の選択、マス上にマウスが来たときには色の変化、リスト式の選択やクリックによる難易度・手番の変更などをイベント機能を用いて実装しています。

(おまけ)Reflexについて

Reflexはメジャーバージョンが出ておらず、日本語記事も公式のチュートリアルを踏襲しているものばかりで数が多くないです。公式ドキュメントについては機能が網羅的に書かれているので、どのような機能があるか、各機能はどのようなカスタマイズができるかわかりやすく見ることができます。また、(おそらく)ドキュメントとGitHubのIssuesの内容を学習させたAIも利用できます。自分も大いに活用しました。

自分が今回のWebページの作成にあたり参考にしていたのは公式ドキュメントとReflexで初回されているギャラリーです。ギャラリーには様々な例があるので、自身が作成したいページに近いものを見ながらコーディングしていくのが良いと思います。

PythonのみでWebページが作成はできますが、見た目に拘っていきたい場合にはHTMLやCSSなどの知識もあったほうが良いです。

終わりに

3目並べについてはそこまで苦労することなく実装できました。一方でReflexについては初めて使うので、色々と試行錯誤しながらの面が多かったです。しかし、PythonのみでWebページを作れるというのは非常に魅力的でした。

3次元の3目並べを今回作成しましたが、実際に遊んでみると先攻が有利すぎて現状のルールではゲームとして成り立たない気がします。強化学習を使ってコンピュータに選択させてみようとも考えていたのですが、ゲームバランスの微妙さと上記で述べた選択方法が性能的に十分であることから断念しました。

今後は別のゲームも実装してみようと思います。

参考

GitHubで編集を提案

Discussion