GoogleColabでインタラクティブな処理をする

2022-04-18

Google Colaboratoryでボードゲームの対戦といった、リアルタイムではないインタラクティブな処理をさせる方法を調べた。

あらまし

書籍「AlphaZero 人工知能プログラミング実践入門」の「人間とAIの対戦」では ローカル環境でPythonのGUIライブラリTkinterを使用して動かすよう書かれている。 しかし他にAnacondaやTensorFlowなどの環境を構築しないといけないので面倒。 なので対戦もColab上で動かしたい。

当初は print での盤面表示と1行入力でいいかと思ってたんだけど、プロポーショナルフォントなので幅がずれるのとキーボード入力が手間だったので、 グラフィックス表示やボタン入力ができないかと調べてみた。

グラフィックス表示

Google ColaboratoryでPILで何か描画して表示する - Qiita を参考に、PILの Image を使用してみた。 ImageDraw でプリミティブの描画(line, rectangle, ellipse など)ができる:

from PIL import Image, ImageDraw
im = Image.new('RGB', (512, 512))
draw = ImageDraw.Draw(im)
draw.rectangle((0, 0, 512, 512), fill=(0, 0, 255))
draw.ellipse((64, 64, 192, 192), fill=(255, 0, 0), outline=(0, 0, 0))
draw.line((500, 12, 12, 500), fill=(0, 255, 0), width=3)

from IPython.display import display
display(im)

UI表示

Coalb上でボタンなどのUIを表示するには ipywidgets モジュール(Jupyter Widgets)が使える。

ボードゲームの盤面のようなグリッド状の要素は GridBox が使える。 子要素に Button を指定して、クリックを判定できるようにする:

from ipywidgets import Button, Layout, GridBox

def create_button(i):
button = Button(description=str(i), layout=Layout(width='50px', height='50px'))
button.on_click(lambda _: print(i))
return button

GridBox(
children=[create_button(i) for i in range(9)],
layout=Layout(
grid_template_columns='repeat(3, 50px)',
grid_template_rows='repeat(3, 50px)',
grid_gap='4px'))
  • button.on_click(...) でクリック判定

UI表示後の処理

人間の入力を促すためにUIを表示したら、Colabのセルは実行から抜けることになる。 ボタンがクリックされたら処理を続けるようにするため、 on_click に指定したコールバック内で続きの処理を行えるようにしておく。

セルの出力クリア

三目並べ程度なら各手番の盤面の状態を出力したままにして続けて表示でもいいんだけど、かさばるし過去のUIが操作されると気持ち悪いのでクリアしてやる:

from IPython.display import clear_output
clear_output()

ソース

動かし方