オセロ盤を作ってみました。
できたのがこちら、

すごいシンプルな感じで作りました。
今回はオセロ盤を作るのみで、石の反転やマスがクリックされたときの処理は次回以降に書きます。
このオセロ盤を作るステップは
1. メインウィンドウをつくる
2. Canvasをメインウィンドウに貼る
3. Canvas上に線を引きマスをつくる。
4. オセロ盤の設定。
5. Labelを作る。
です。
1. メインウィンドウを作る
はじめに、メインウィンドウを作ります。
メインウィンドウの作り方は以前書いた記事で一応説明しています。
pytry3g.hatenablog.com
前回と違うのは、Tkクラスを継承してAppクラスを定義しているところのみです。
下のプログラムをベースにset_widgetsメソッドでwidgetを作ってメインウィンドウに配置していきます。
import tkinter as tk
class App(tk.Tk):
def __init__(self):
super(App, self).__init__()
self.title("オセロ")
self.geometry("{}x{}+{}+{}".format(550, 550, 300, 100))
self.resizable(0, 0)
self.iconbitmap("othello.ico")
self.configure(bg="white")
self.set_widgets()
def set_widgets(self):
pass
def run(self):
self.mainloop()
if __name__ == "__main__":
app = App()
app.run()
Canvasの使い方ですが、今回やることは下の記事の説明で十分間に合うと思います。
pytry3g.hatenablog.com
はじめに、Canvasを使ってオセロ盤を作ります。
def set_widgets(self):
self.board = tk.Canvas(self, bg="lime green", width=350, height=350)
self.board.pack(pady=(30, 0))

次に縦線と横線を引いてマスを作ります。
線をひく必要はなかった。
for x in range(15, 336, 40):
self.board.create_line(x, 15, x, 335)
for y in range(15, 336, 40):
self.board.create_line(15, y, 335, y)
線を引かずに長方形を作ってマスを配置していきます。このマスの上に白と黒の石を配置するようになります。
例えば、長方形を作るには下のような感じ作ります。
def set_widgets(self):
self.board = tk.Canvas(self, bg="lime green", width=350, height=350)
self.board.pack(pady=(30, 0))
self.board.create_rectangle((20, 20, 60, 50), fill="red")
(20, 20, 60, 50)で長方形の大きさを指定し、fillで背景の色を赤色にしています。

オセロ盤は8x8の64個のマスが必要となるので 下の画像になるように長方形を作っていきます。次のオセロ盤の設定のところで実際に64個の長方形を作っています。

4. オセロ盤の設定
続いて、オセロ盤の設定をします。
ここでしていることは、
盤面の情報をもつリストを用意する。
8x8の盤面をつくるために、64個の長方形を配置する。
盤面の初期設定をする。
self.board2info = [-1] * 10 + [[0, -1][i in [0, 9]] for i in range(10)] * 8 + [-1] * 10
self.numstr = '12345678'
self.alpstr = "abcdefgh"
self.tag2pos = {}
self.z2tag = {}
for i, y in zip(self.numstr, range(15, 336, 40)):
for j, x in zip(self.alpstr, range(15, 336, 40)):
pos = x, y, x+40, y+40
tag = i + j
self.tag2pos[tag] = pos
self.board.create_rectangle(*pos, fill="lime green", tags=tag)
self.z2tag[self.z_coordinate(tag)] = tag
for p, i in zip([1, 2], "45"):
for q, j in zip([2, 1], "de"):
color = ["black", "white"][p-q]
tag = i + j
self.board2info[self.z_coordinate(tag)] = [1, 2][p-q]
self.board.create_oval(*self.tag2pos[tag], fill=color, tags=tag)
self.get_board_info()
board2infoにはオセロ盤の情報を入れています。オセロ盤は8x8の8路盤ですが、
どこに石が置けるのか、どの石が反転できるのかを判定しやすくするために盤の外を加え10x10にして、さらに1次元の座標で表しています。
-1は盤外、0は空点、1は黒、2は白を表します。
numstrとalpstrはtagに使います。tagを使う理由は2つあります。1つは、座標の位置を理解しやすくするため。もう1つは、Canvas上に長方形をつくるときに、すべての長方形にtagを設定するためです。
長方形にtagを設定することにより、オセロ盤がクリックされたとき、どの長方形がクリックされたのかを判別することができ、かつ、その長方形のtagを取得することができるようになります。
tag2posはtagからそのtagが設定されている長方形の座標を入れています。これは、石をひっくり返すときや空点に新しく石を置くときに使います。
z2tagは1次元の座標をtagに変換します。
z_coordinateはtagから1次元の座標を手に入れるために使います。
def z_coordinate(self, tag):
x = self.alpstr.index(tag[1])+1
y = self.numstr.index(tag[0])+1
return y*10 + x
tagは以下のような感じで上から順に1から8まで、左から順にaからhまでの数字とアルファベットを組み合わせて設定します。例えば一番左上は1a、一番左下は8aとなります。

get_board_infoはオセロ盤の情報を表示する。
def get_board_info(self):
board_format = " {:2d} " * 10
print("", *[board_format.format(*self.board2info[i:i+10]) \
for i in range(0, 100, 10)], sep='\n')
初期設定のところで、create_ovalを使い、マスの上に白と黒の石を配置しています。
初期設定をした後、オセロ盤の情報を表示すると、
こんな感じで表示されます。

5. Labelを作る
最後にLabelの設定をします。ラベルにはテキスト(手番)を表示するようにします。
手番が変わると、表示するテキストも変わるようにします。
やり方は以下の記事で書いてある通りです。
pytry3g.hatenablog.com
今回はキャンバスを作ってその上にラベルを配置しています。
self.turn = 1
self.info = tk.Canvas(self, bg="white", width=300, height=100)
self.info.pack(pady=(30, 0))
self.var = tk.StringVar()
self.update_label()
self.label = tk.Label(self.info, bg="white",
font=("Helvetica", 15), textvariable=self.var)
self.label.pack()
def update_label(self):
self.var.set("{}のターン".format(["AI", "あなた"][self.turn]))
と、ここまでオセロ盤の作り方をざっくり説明してみました。
今後このプログラムを空いているマスに石を置いたり、石を反転させれるようにするつもりです。
To be continued...
続き ↓↓↓
pytry3g.hatenablog.com