早速コードを添付します。
すぐに改良するかもしれません。
一緒に作りましょう☺
ゲームの説明書
3人で対戦するオセロです。
赤青黄に分かれて対戦します。
順番は赤青黄の順で対戦します。
また一番下のリセットボタンを押すことでゲームをはじめからやり直すことができます。
import tkinter as tks
from tkinter import messagebox
# 定数の設定
BOARD_SIZE = 8 # オセロボードのサイズ(8x8)
COLORS = {'R': 'red', 'B': 'blue', 'Y': 'yellow', '': 'white'} # オセロの色のマッピング
DIRECTIONS = [(1, 0), (-1, 0), (0, 1), (0, -1), (1, 1), (1, -1), (-1, 1), (-1, -1)] # 8方向を表すベクトル
# オセロのゲームロジック部分
class OthelloBoard:
def __init__(self):
# 初期化処理
self.board = [['' for _ in range(BOARD_SIZE)] for _ in range(BOARD_SIZE)] # 空のボードを作成
self.initialize_board() # ボードを初期状態に設定
self.current_turn = 'R' # 最初のターンは赤
self.game_over = False # ゲーム開始時点では終了していない
def initialize_board(self):
# ボードの初期配置
# 中央にそれぞれの色のオセロを配置する
self.board[3][3] = 'R'
self.board[4][4] = 'R'
self.board[3][4] = 'B'
self.board[4][5] = 'B'
self.board[3][2] = 'Y'
self.board[4][3] = 'Y'
self.board[5][4] = 'Y'
def place_stone(self, x, y):
# オセロを配置する処理
if self.board[x][y] or not self.valid_move(x, y, self.current_turn):
return False
# 8方向ごとにオセロを裏返す処理
for dx, dy in DIRECTIONS:
self.flip_stones(x, y, dx, dy, self.current_turn)
self.board[x][y] = self.current_turn # オセロを配置
# 次のターンに移行
self.next_turn()
# ゲーム終了をチェック
self.check_game_over()
return True
def valid_move(self, x, y, color):
if self.board[x][y]:
return False
for dx, dy in DIRECTIONS:
if self.can_flip(x, y, dx, dy, color):
return True
return False
def can_flip(self, x, y, dx, dy, color):
x += dx
y += dy
if x < 0 or x >= BOARD_SIZE or y < 0 or y >= BOARD_SIZE or self.board[x][y] == color or not self.board[x][y]:
return False
while 0 <= x < BOARD_SIZE and 0 <= y < BOARD_SIZE:
if not self.board[x][y]:
return False
if self.board[x][y] == color:
return True
x += dx
y += dy
return False
def flip_stones(self, x, y, dx, dy, color):
if not self.can_flip(x, y, dx, dy, color):
return
x += dx
y += dy
while 0 <= x < BOARD_SIZE and 0 <= y < BOARD_SIZE and self.board[x][y] and self.board[x][y] != color:
self.board[x][y] = color
x += dx
y += dy
def next_turn(self):
# ターンを次のプレイヤーに変更
turns = ['R', 'B', 'Y']
count_check = 0
while True:
self.current_turn = turns[(turns.index(self.current_turn) + 1) % 3]
for x in range(BOARD_SIZE):
for y in range(BOARD_SIZE):
if self.valid_move(x, y, self.current_turn):
return
count_check += 1
if count_check == 3:
self.game_over = True
return
def check_game_over(self):
for color in ['R', 'B', 'Y']:
for x in range(BOARD_SIZE):
for y in range(BOARD_SIZE):
if self.valid_move(x, y, color):
return
self.game_over = True
def count_stones(self):
return {'R': sum(row.count('R') for row in self.board),
'B': sum(row.count('B') for row in self.board),
'Y': sum(row.count('Y') for row in self.board)}
# オセロのGUI部分
class OthelloGUI:
def __init__(self, master):
# 初期化処理
self.master = master
self.board = OthelloBoard()
# キャンバスの作成と配置
self.canvas = tks.Canvas(master, bg="white")
self.canvas.pack(fill=tks.BOTH, expand=True)
self.canvas.bind("<Button-1>", self.on_canvas_click)
# キャンバスがリサイズされたときの処理をバインド
self.canvas.bind("<Configure>", self.draw_board)
# ターン表示用のラベルの作成と配置
self.turn_label = tks.Label(master, text="", font=("Arial", 16))
self.turn_label.pack(pady=10)
# ゲームリセット用のボタンの作成と配置
self.reset_button = tks.Button(master, text="リセット", command=self.reset_game)
self.reset_button.pack(fill=tks.X)
self.update_turn_label() # ゲーム開始時のターンを表示
def on_canvas_click(self, event):
width, height = self.canvas.winfo_width(), self.canvas.winfo_height()
cell_size = min(width, height) / BOARD_SIZE
board_size = cell_size * BOARD_SIZE
start_x = (width - board_size) / 2
start_y = (height - board_size) / 2
x, y = int((event.x - start_x) // cell_size), int((event.y - start_y) // cell_size)
if 0 <= x < BOARD_SIZE and 0 <= y < BOARD_SIZE: # クリック位置がボード上であることを確認
self.place_stone(x, y)
def draw_board(self, event=None):
self.canvas.delete("all")
# ウィンドウのサイズを取得
width, height = self.canvas.winfo_width(), self.canvas.winfo_height()
# 碁盤の大きさを計算
cell_size = min(width, height) / BOARD_SIZE
board_size = cell_size * BOARD_SIZE
# 碁盤の開始位置を計算
start_x = (width - board_size) / 2
start_y = (height - board_size) / 2
# 碁盤の背景を緑色にする
self.canvas.create_rectangle(start_x, start_y, start_x + board_size, start_y + board_size, fill='green', outline='black', width=3)
for x in range(BOARD_SIZE):
for y in range(BOARD_SIZE):
top_left_x = start_x + x * cell_size
top_left_y = start_y + y * cell_size
bottom_right_x = start_x + (x + 1) * cell_size
bottom_right_y = start_y + (y + 1) * cell_size
color = self.board.board[x][y]
if color == 'R':
self.canvas.create_oval(top_left_x, top_left_y, bottom_right_x, bottom_right_y, fill="red")
elif color == 'B':
self.canvas.create_oval(top_left_x, top_left_y, bottom_right_x, bottom_right_y, fill="blue")
elif color == 'Y':
self.canvas.create_oval(top_left_x, top_left_y, bottom_right_x, bottom_right_y, fill="yellow")
# 各セルの外枠
self.canvas.create_rectangle(top_left_x, top_left_y, bottom_right_x, bottom_right_y, outline='black')
def place_stone(self, x, y):
if not self.board.game_over and self.board.place_stone(x, y):
self.update_turn_label() # ターンの変更時にラベルを更新
self.update_buttons()
if self.board.game_over:
counts = self.board.count_stones()
winner = max(counts, key=counts.get)
messagebox.showinfo("ゲーム終了", f"赤: {counts['R']}, 青: {counts['B']}, 黄: {counts['Y']}。勝者: {COLORS[winner]}")
def reset_game(self):
self.board = OthelloBoard()
self.update_turn_label() # ゲームリセット時にラベルを更新
self.update_buttons()
def update_turn_label(self):
self.turn_label.config(text=f"現在のターン: {COLORS[self.board.current_turn]}")
def update_buttons(self):
self.draw_board()
if __name__ == '__main__':
root = tks.Tk() # メインウィンドウの作成
gui = OthelloGUI(root) # GUIのインスタンスを作成
root.mainloop() # メインループを開始