tkinterを用いたオセロゲーム
開発環境:VScode python 3.10.2
実行結果
仕様:下記のpythonプログラムを実行すると2つのウィンドウが表示される(図1)。図1の右のウィンドウにおきたいマス(行>row(1-8行)、列>col(1-8列))を入力し「ok」をクリック。その後、vscodeのコンソール上で任意の文字を入力すると、図3のように駒が置かれる。
#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(✕):置いてはいけないマス
#
# 0123456789 列(col)
#0✕✕✕✕✕✕✕✕✕✕
#1✕☐☐☐☐☐☐☐☐✕
#2✕☐☐☐☐☐☐☐☐✕
#3✕☐☐☐☐☐☐☐☐✕
#4✕☐☐☐21☐☐☐✕
#5✕☐☐☐12☐☐☐✕
#6✕☐☐☐☐☐☐☐☐✕
#7✕☐☐☐☐☐☐☐☐✕
#8✕☐☐☐☐☐☐☐☐✕
#9✕✕✕✕✕✕✕✕✕✕
#行(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()