エンジニアリングデイズ - Engineering Days - 

その時々興味があるものを作ります。

python tkinterで三目並べ(OXゲーム)をつくってみた。[Op.1]

三目並べ(OXゲーム)を作る

きっかけ

ということで、第一弾は三目並べです。何かしらGUIソフトを作りたいなぁとネットサーフィンしていると、pythonの入門書[1]を見つけました。ちょうどGUI作成ができるtkinterについて書かれていて、pythonも少しは知っていたので、これを参考にしようと思いました。

作るもの

テキストにはCUIベースで動作する三目並べのサンプルがあったので、これをGUIに作りかえます。テキストでは課題として扱われている内容です。特にGUI構成の指示とはないので自由に作りたいと思います。

完成イメージ

こんな感じのものを作ろうと思います。

f:id:kiymiy04:20220116224248j:plain

図:GUIのイメージ

 

動作イメージ

・START:ゲーム開始

・RESET:ゲーム中断。STARTボタン押下後、同じ位置に表示

・REPLAY:ゲーム終了後に棋譜の再生

・対CPU機能(PLAYモードの選択)

 

表示の仕様

・先手の番か後手の番かの表示

・現在何手目かの表示

・盤面にマウスポインタを持ってくると、OまたはXを薄く表示。左クリックで確定させると濃く表示

 

とりあえずは今書いたような感じで作ります。細部は作りながら調整します。

 

~~~ ~~~

完成品

というわけで、ざっと作りました。

ネット情報を参考におよそイメージ通りにできました。一点詰まったところがあったのでそこについて少しメモしておきます。

 

詰まったところ:tkinterでの図形描画のタイミング

描画用の関数を作って試していたがうまくいかない。調べるとどうやら関数から抜けてmainloop内に戻らないとtkinter Canvas.create実行がされないような感じ。そのため、描画用関数内でtime.sleepを実行しても、関数を抜けた後にしか、描画が実行されず意図した動作にならなかった。

これを解決するには、tkinterに用意されているafter関数を用いる。after関数を使用することで待機時間中は一旦mainloopに戻る(と思われる?)ため、描画がその待機時間中に実行される。

*この場合でも自作の関数内にfor等のループ関数を書いた場合には上手くいかなかったので注意する。(for, whileループ内からtkinterのafter関数を使ってもmainloopに戻れない?)→ eventを発生させた場合に関数処理が長くならないように関数渡しする必要がある。

 

動作確認

とりあえず動作するものができました。下の動画のようになりました。


www.youtube.com

 

一応ですがCUIコンソールも並べて表示しています。CUI動作はほとんど[1]のサンプルのままです。ちなみに非表示対応はしていません(まだ調べていないのでわからない+このプログラムに関しては追加する予定なし)。あと動画ではわかりにくいですが、O,Xの手は左クリック時に確定しています(タッチパネルなので実際には1タップです)。既に置かれているマスを押した場合は、GUI的には何もしないようにしていますが、CUI上でテキスト出力されており、意図した動作になっています。

 

あとは、棋譜を再生する機能REPLAYが実装できていないので、これを追加します。この内容については次回の記事で。

 

[1] Kyoto University Research Information Repository: プログラミング演習 Python 2019