Tkinterを用いたオセロ

tkinterを用いたオセロゲーム

開発環境：VScode python 3.10.2

実行結果
仕様：下記のpythonプログラムを実行すると2つのウィンドウが表示される(図1)。図1の右のウィンドウにおきたいマス(行>row(1-8行)、列>col(1-8列))を入力し「ok」をクリック。その後、vscodeのコンソール上で任意の文字を入力すると、図3のように駒が置かれる。

図1：実行結果(1)
![スクリーンショット_20230126_173448.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3031701/664f962f-313c-2f1b-e81f-b89960995759.png)

図2:実行結果(2)
![スクリーンショット_20230126_173508.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3031701/1b50eba3-7d6c-be06-8bf4-ef990b6bf989.png)

図3：実行結果(3)
![スクリーンショット_20230126_173530.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3031701/9fdc973e-2587-30aa-8cff-ba929806c0ea.png)




```python
#othelloプログラム
#作成日：2022/12/07
#モジュールインストール
import tkinter as tk

#駒が置けるか判定する関数
def judge(bw,rowcol,board):
    #変数定義
    i=1 #ループカウンタ、走査する際に使用する
    j=1 #ループカウンタ、走査する際に使用する
    cnt=0 #カウンタ変数、何枚ひっくり返すか記憶する変数
    ok=0 #一枚でもひっくり返せたら1にする
    way=0 #どこの向きを走査するか 1:上　2:下 3:右 4:左 5:右上 6:左上 7:左下 8:右下

    if(1>rowcol[0] or 8<rowcol[0] or 1>rowcol[1] or 8<rowcol[1]):
        print('存在しないマスです。')
        return 1


    #置けるかどうかチェック
    #way 1:上　2:下 3:右 4:左 5:右上 6:右下 7:左上 8:左下
    for way in range(1,9):
        cnt=0 #変数の初期化
        if(way==1 or way==2):
            i=0
        if(way==3 or way==5 or way==6):
            i=1
        if(way==4 or way==7 or way==8):
            i=-1
        if(way==3 or way==4):
            j=0
        if(way==2 or way==6 or way==8):
            j=1
        if(way==1 or way==5 or way==7):
            j=-1

        if(bw==1): #黒色(bw==1)の場合
            if(board[rowcol[1]+i][rowcol[0]+j]==2): #特定の方向が白色
                cnt+=1
                if(way==1 or way==5 or way==7):
                    j-=1
                if(way==2 or way==6 or way==8):
                    j+=1
                if(way==3 or way==5 or way==6):
                    i+=1
                if(way==4 or way==7 or way==8):
                    i-=1
                while(board[rowcol[1]+i][rowcol[0]+j]==2): #その方向に白色がいくつあるのか
                    cnt+=1
                    if(way==1 or way==5 or way==7):
                        j-=1
                    if(way==2 or way==6 or way==8):
                        j+=1
                    if(way==3 or way==5 or way==6):
                        i+=1
                    if(way==4 or way==7 or way==8):
                        i-=1
                if(board[rowcol[1]+i][rowcol[0]+j]==bw): #黒までをひっくり返す
                    ok=1
                    while(cnt>0):
                        if(way==1):#上方向ひっくり返す
                            board[rowcol[1]][rowcol[0]-cnt]=bw
                            canvas.create_oval(5+(rowcol[1]-1)*50,5+(rowcol[0]-1-cnt)*50,45+(rowcol[1]-1)*50,45+(rowcol[0]-1-cnt)*50,fill='black')
                        if(way==2):#下方向ひっくり返す
                            board[rowcol[1]][rowcol[0]+cnt]=bw
                            canvas.create_oval(5+(rowcol[1]-1)*50,5+(rowcol[0]-1+cnt)*50,45+(rowcol[1]-1)*50,45+(rowcol[0]-1+cnt)*50,fill='black')
                        if(way==3):#右方向ひっくり返す
                            board[rowcol[1]+cnt][rowcol[0]]=bw
                            canvas.create_oval(5+(rowcol[1]-1+cnt)*50,5+(rowcol[0]-1)*50,45+(rowcol[1]-1+cnt)*50,45+(rowcol[0]-1)*50,fill='black')
                        if(way==4):#左方向ひっくり返す
                            board[rowcol[1]-cnt][rowcol[0]]=bw
                            canvas.create_oval(5+(rowcol[1]-1-cnt)*50,5+(rowcol[0]-1)*50,45+(rowcol[1]-1-cnt)*50,45+(rowcol[0]-1)*50,fill='black')
                        if(way==5):#右上方向ひっくり返す
                            board[rowcol[1]+cnt][rowcol[0]-cnt]=bw
                            canvas.create_oval(5+(rowcol[1]-1+cnt)*50,5+(rowcol[0]-1-cnt)*50,45+(rowcol[1]-1+cnt)*50,45+(rowcol[0]-1-cnt)*50,fill='black')
                        if(way==6):#右下方向ひっくり返す
                            board[rowcol[1]+cnt][rowcol[0]+cnt]=bw
                            canvas.create_oval(5+(rowcol[1]-1+cnt)*50,5+(rowcol[0]-1+cnt)*50,45+(rowcol[1]-1+cnt)*50,45+(rowcol[0]-1+cnt)*50,fill='black')
                        if(way==7):#左上方向ひっくり返す
                            board[rowcol[1]-cnt][rowcol[0]-cnt]=bw
                            canvas.create_oval(5+(rowcol[1]-1-cnt)*50,5+(rowcol[0]-1-cnt)*50,45+(rowcol[1]-1-cnt)*50,45+(rowcol[0]-1-cnt)*50,fill='black')
                        if(way==8):#左下方向ひっくり返す
                            board[rowcol[1]-cnt][rowcol[0]+cnt]=bw
                            canvas.create_oval(5+(rowcol[1]-1-cnt)*50,5+(rowcol[0]-1+cnt)*50,45+(rowcol[1]-1-cnt)*50,45+(rowcol[0]-1+cnt)*50,fill='black')
                        cnt-=1
            #一枚でもひっくり返したら指定された場所に黒色を置く
            if(ok==1):
                board[rowcol[1]][rowcol[0]]=bw
                canvas.create_oval(5+(rowcol[1]-1)*50,5+(rowcol[0]-1)*50,45+(rowcol[1]-1)*50,45+(rowcol[0]-1)*50,fill='black')

        if(bw==2): #白色(bw==2)の場合
            if(board[rowcol[1]+i][rowcol[0]+j]==1): #特定の方向が黒色
                cnt+=1
                if(way==1 or way==5 or way==7):
                    j-=1
                if(way==2 or way==6 or way==8):
                    j+=1
                if(way==3 or way==5 or way==6):
                    i+=1
                if(way==4 or way==7 or way==8):
                    i-=1
                while(board[rowcol[1]+i][rowcol[0]+j]==1): #その方向に黒色がいくつあるのか
                    cnt+=1
                    if(way==1 or way==5 or way==7):
                        j-=1
                    if(way==2 or way==6 or way==8):
                        j+=1
                    if(way==3 or way==5 or way==6):
                        i+=1
                    if(way==4 or way==7 or way==8):
                        i-=1
                if(board[rowcol[1]+i][rowcol[0]+j]==bw): #黒までをひっくり返す
                    ok=1
                    while(cnt>0):
                        if(way==1):#上方向ひっくり返す
                            board[rowcol[1]][rowcol[0]-cnt]=bw
                            canvas.create_oval(5+(rowcol[1]-1)*50,5+(rowcol[0]-1-cnt)*50,45+(rowcol[1]-1)*50,45+(rowcol[0]-1-cnt)*50,fill='white')
                        if(way==2):#下方向ひっくり返す
                            board[rowcol[1]][rowcol[0]+cnt]=bw
                            canvas.create_oval(5+(rowcol[1]-1)*50,5+(rowcol[0]-1+cnt)*50,45+(rowcol[1]-1)*50,45+(rowcol[0]-1+cnt)*50,fill='white')
                        if(way==3):#右方向ひっくり返す
                            board[rowcol[1]+cnt][rowcol[0]]=bw
                            canvas.create_oval(5+(rowcol[1]-1+cnt)*50,5+(rowcol[0]-1)*50,45+(rowcol[1]-1+cnt)*50,45+(rowcol[0]-1)*50,fill='white')
                        if(way==4):#左方向ひっくり返す
                            board[rowcol[1]-cnt][rowcol[0]]=bw
                            canvas.create_oval(5+(rowcol[1]-1-cnt)*50,5+(rowcol[0]-1)*50,45+(rowcol[1]-1-cnt)*50,45+(rowcol[0]-1)*50,fill='white')
                        if(way==5):#右上方向ひっくり返す
                            board[rowcol[1]+cnt][rowcol[0]-cnt]=bw
                            canvas.create_oval(5+(rowcol[1]-1+cnt)*50,5+(rowcol[0]-1-cnt)*50,45+(rowcol[1]-1+cnt)*50,45+(rowcol[0]-1-cnt)*50,fill='white')
                        if(way==6):#右下方向ひっくり返す
                            board[rowcol[1]+cnt][rowcol[0]+cnt]=bw
                            canvas.create_oval(5+(rowcol[1]-1+cnt)*50,5+(rowcol[0]-1+cnt)*50,45+(rowcol[1]-1+cnt)*50,45+(rowcol[0]-1+cnt)*50,fill='white')
                        if(way==7):#左上方向ひっくり返す
                            board[rowcol[1]-cnt][rowcol[0]-cnt]=bw
                            canvas.create_oval(5+(rowcol[1]-1-cnt)*50,5+(rowcol[0]-1-cnt)*50,45+(rowcol[1]-1-cnt)*50,45+(rowcol[0]-1-cnt)*50,fill='white')
                        if(way==8):#左下方向ひっくり返す
                            board[rowcol[1]-cnt][rowcol[0]+cnt]=bw
                            canvas.create_oval(5+(rowcol[1]-1-cnt)*50,5+(rowcol[0]-1+cnt)*50,45+(rowcol[1]-1-cnt)*50,45+(rowcol[0]-1+cnt)*50,fill='white')
                        cnt-=1
            #一枚でもひっくり返したら指定された場所に白色を置く
            if(ok==1):
                board[rowcol[1]][rowcol[0]]=bw
                canvas.create_oval(5+(rowcol[1]-1)*50,5+(rowcol[0]-1)*50,45+(rowcol[1]-1)*50,45+(rowcol[0]-1)*50,fill='white')
    #何もひっくり返せなかったとき            
    if(ok==0):
        return 1            

#ボード表示関数
def display(board):
    cnt=1 #何行目かを記憶する変数
    for i in range(10):
        if(i==0):#列番号表示
            for k in range(9):
                if(k==0):
                    print(' ',end=' ')
                else:
                    print(k,end=' ')
            print()
        for j in range(10):
            if(i!=0 and i!=9):#行番号表示
                if(j==0 and j!=9):
                    print(cnt,end=' ')
                    cnt+=1
            if(board[j][i]==0):#何も置かれていないマスの表示
                print('☐',end=' ')
            if(board[j][i]==1):#黒色表示
                print('○',end=' ')
            if(board[j][i]==2):#白色表示
                print('●',end=' ') 
        if(i!=0):
            print()

#ボードの黒色と白色の枚数を数える関数
def check(board,bw):
    cnt_black=0 #黒色の枚数
    cnt_white=0 #白色の枚数
    
    for i in range(1,9):
        for j in range(1,9):
            if(board[j][i]==1): #黒色の枚数チェック
                cnt_black+=1
            if(board[j][i]==2): #白色の枚数チェック
                cnt_white+=1
    if(bw==1): #黒色のターンのとき
        return cnt_black
    if(bw==2): #白色のターンのとき
        return cnt_white

#OKボタンがクリックされた時windows_sb2のウィンドウのentryから文字列を取得する関数
def button_ok(rowcol):
    global count
    #入力されている行列を取得する
    rowcol[0]=int(entry1.get())
    rowcol[1]=int(entry2.get())

    count+=1

    #entryの文字列をクリア
    entry1.delete(0,tk.END)
    entry2.delete(0,tk.END)

#変数、リストの定義
board=[[0 for i in range(10)]for i in range(10)] #オセロボードのリスト[列][行]
rowcol=[0,0] #行列のリスト [行,列]
flag=0 #状態記憶変数 0:正常 1:異常
masu=60 #残りのマスの変数
bw=1 #黒色か白色か記憶する変数 1:黒色　2:白色
result_black=0 #黒色の最終枚数
result_white=0 #白色の最終枚数
tm=0 #時間の変数
count=0 #グローバル変数の定義 button_okで使用する
buf=0 #便宜的な変数
start=0 #初める変数

#ウィンドウ(アプリ)の作成(メインウィンドウ)
windows = tk.Tk()
windows.geometry("500x600+100+100") #ウィンドウサイズ、位置指定
windows.title('othello') #ウィンドウ名
windows.configure(bg='beige') #背景色設定

#ウィンドウ(アプリ)の作成(サブ2ウィンドウ)
windows_sb2 = tk.Tk()
windows_sb2.geometry("200x120+650+100") #ウィンドウサイズ、位置指定
windows_sb2.title('The rule of othello') #ウィンドウ名
windows_sb2.configure(bg='beige') #背景色設定

#フレーム、エントリーの作成
frame = tk.Frame(windows_sb2,width=200,height=120,bg='beige')
entry1=tk.Entry(frame)
entry2=tk.Entry(frame)

#ラベルの作成
label_row = tk.Label(frame,font = ("Helvetica", 10), text = "row",bg='beige')
label_col = tk.Label(frame,font = ("Helvetica", 10), text = "col",bg='beige')

#ボタンの作成
button = tk.Button(frame,text='OK',command=lambda:button_ok(rowcol))
button.place(x=40,y=85)

#フレーム、エントリー、ラベルの配置
frame.place(x=0,y=0)
label_row.place(x=10,y=18)
label_col.place(x=10,y=53)
entry1.place(x=40,y=20)
entry2.place(x=40,y=55)

#canvasの設定
canvas = tk.Canvas(windows,width=400,height=400,background="white")

#canvasの配置
canvas.place(x=50,y=50)

#ボード生成
for i in range(1,9):
    for j in range(1,9):
        canvas.create_rectangle((j-1)*50, (i-1)*50, j*50, i*50, fill = 'green3',outline='black')

#ボード初期化
canvas.create_oval(155,155,195,195,fill='white')
canvas.create_oval(205,205,245,245,fill='white')
canvas.create_oval(205,155,245,195,fill='black')
canvas.create_oval(155,205,195,245,fill='black')

#ラベルの配置
label = tk.Label(windows, font = ("Helvetica", 20), text = "othello")

#ラベルの配置、背景色の設定
label.place(x=50,y=10)
label.configure(bg='beige')

#オセロボードの初期化
board[4][4]=2 #初期白色配置
board[5][5]=2 #初期白色配置
board[5][4]=1 #初期黒色配置
board[4][5]=1 #初期黒色配置

# オセロボード仕様 
# 0(☐)：何も置かれていないマス
# 1()：黒色が置かれているマス
# 2()：白色が置かれているマス
# 9(✕)：置いてはいけないマス
#
#　０１２３４５６７８９　列(col)
#０✕✕✕✕✕✕✕✕✕✕
#１✕☐☐☐☐☐☐☐☐✕
#２✕☐☐☐☐☐☐☐☐✕
#３✕☐☐☐☐☐☐☐☐✕
#４✕☐☐☐２１☐☐☐✕
#５✕☐☐☐１２☐☐☐✕
#６✕☐☐☐☐☐☐☐☐✕
#７✕☐☐☐☐☐☐☐☐✕
#８✕☐☐☐☐☐☐☐☐✕
#９✕✕✕✕✕✕✕✕✕✕
#行(row)

#置いてはいけないマスの設定
for i in range(10):
    board[i][0]=9
    board[i][9]=9
    board[0][i]=9
    board[9][i]=9

#ゲームスタート
print('ゲームスタート！！！')
bw=1 #黒色から始めるようにする
while masu>0:
    #display(board)
    flag=0

    #黒色のターン
    if(bw==1):
        print('---黒色のターン---\n')

        #ラベルの作成(どちらのターン)
        label_bw = tk.Label(windows,font = ("Helvetica", 20), text = "黒色のターン")

        #ラベルの配置、背景色の設定
        label_bw.place(x=50,y=460)
        label_bw.configure(bg='beige')

        #ラベルの作成(黒色白色何枚)
        label_howmany = tk.Label(windows,font = ("Helvetica", 20),text = f'黒：{check(board,1)}  白：{check(board,2)}')

        #ラベルの配置、背景色の設定
        label_howmany.place(x=150,y=10)
        label_howmany.configure(bg='beige')
       
        #どこに置くか入力待ち
        ok=input('右下のウィンドウにどこに置くか入力してください。\n入力し終わったら任意のキーを押し、エンターキーを押してください。')
        
        #置けるのか判定する
        flag=judge(bw,rowcol,board)
        if(flag==1):
            print('もう一度入力してください。')
            continue
        else:
            masu-=1 #一枚置いたことを記憶する
            bw=2
            #display(board)
    
    flag=0
    #白色のターン
    if(bw==2):
        print('---白色のターン---\n')

        #ラベルの作成
        label_bw = tk.Label(windows, font = ("Helvetica", 20),text = "白色のターン")

        #ラベルの配置、背景色の設定
        label_bw.place(x=50,y=460)
        label_bw.configure(bg='beige')

        #ラベルの作成(黒色白色何枚)
        label_howmany = tk.Label(windows,font = ("Helvetica", 20), text = f'黒：{check(board,1)}  白：{check(board,2)}')

        #ラベルの配置、背景色の設定
        label_howmany.place(x=150,y=10)
        label_howmany.configure(bg='beige')

        #どこに置くか
        ok=input('右下のウィンドウにどこに置くか入力してください。\n入力し終わったら任意のキーを押し、エンターキーを押してください。')
        #置けるのか判定する
        flag=judge(bw,rowcol,board)
        if(flag==1):
            print('もう一度入力してください。')
            continue
        else:
            masu-=1
            bw=1
            #display(board)
 
#スコア表示
#ウィンドウ(アプリ)の作成(サブ2ウィンドウ)
windows_sb1 = tk.Tk()
windows_sb1.geometry("400x300+650+300") #ウィンドウサイズ、位置指定
windows_sb1.title('The result of othello') #ウィンドウ名
windows_sb1.configure(bg='beige') #背景色設定

#ラベルの作成
label_result = tk.Label(windows_sb2, font = ("Helvetica", 20),text = f"result\n\n黒:{check(board,1)}  白:{check(board,2)}")
label_result.place(x=50,y=50)
label_result.configure(bg='beige')

windows.mainloop()
windows_sb1.mainloop()
windows_sb2.mainloop()
```