
import tkinter as tk
from tkinter import messagebox
class Gobang:
def __init__(self):
self.window = tk.Tk()
self.window.title("五子棋")
# 棋盘大小
self.board_size = 15
self.cell_size = 40
self.board_margin = 80
# 创建画布
canvas_size = self.board_size * self.cell_size + self.board_margin + 30
self.canvas = tk.Canvas(self.window, width=canvas_size, height=canvas_size)
self.canvas.pack(padx=10, pady=10)
try:
# 加载背景图片
self.bg_image = tk.PhotoImage(file="./background.png")
# 显示背景图片
self.canvas.create_image(canvas_size//2, canvas_size//2,
image=self.bg_image)
except Exception as e:
print("背景图片加载失败:", e)
# 如果加载图片失败,使用纯色背景
self.canvas.create_rectangle(0, 0, canvas_size, canvas_size,
fill='#CDBA96', outline='#CDBA96')
# 初始化棋盘数据
self.board = [[0] * self.board_size for _ in range(self.board_size)]
self.current_player = 1
# 绘制棋盘
self.draw_board()
# 绑定鼠标点击事件
self.canvas.bind('<Button-1>', self.handle_click)
def draw_board(self):
# 显示当前执子角色
current_player_text = "当前执子:黑方" if self.current_player == 1 else "当前执子:白方"
self.canvas.create_text(self.board_margin + (self.board_size-1) * self.cell_size / 2,
self.board_margin - 40,
text=current_player_text,
font=('Arial', 14, 'bold'),
fill='#000000')
# 绘制横线和坐标
for i in range(self.board_size):
y = self.board_margin + i * self.cell_size
# 绘制横线
self.canvas.create_line(self.board_margin, y,
self.board_margin + (self.board_size-1) * self.cell_size, y,
width=2.0, fill='#000000') # 加粗线条
# 添加纵坐标标记(A-O)
self.canvas.create_text(self.board_margin - 20, y,
text=chr(65 + i), font=('Arial', 11))
# 绘制竖线和坐标
for i in range(self.board_size):
x = self.board_margin + i * self.cell_size
# 绘制竖线
self.canvas.create_line(x, self.board_margin,
x, self.board_margin + (self.board_size-1) * self.cell_size,
width=2.0, fill='#000000') # 加粗线条
# 添加横坐标标记(1-15)
self.canvas.create_text(x, self.board_margin - 20,
text=str(i + 1), font=('Arial', 11))
def place_piece(self, x, y):
# 在棋盘数据中记录
self.board[y][x] = self.current_player
piece_x = self.board_margin + x * self.cell_size
piece_y = self.board_margin + y * self.cell_size
# 绘制阴影
shadow_offset = 2
self.canvas.create_oval(piece_x-15+shadow_offset, piece_y-15+shadow_offset,
piece_x+15+shadow_offset, piece_y+15+shadow_offset,
fill='#666666', outline='#666666')
# 设置棋子基本属性
piece_color = 'black' if self.current_player == 1 else '#FFFFFF'
gradient_color = '#444444' if self.current_player == 1 else '#e0e0e0'
outline_color = 'black'
# 主棋子
self.canvas.create_oval(piece_x-15, piece_y-15,
piece_x+15, piece_y+15,
fill=piece_color, outline=outline_color)
# 渐变效果
self.canvas.create_oval(piece_x-12, piece_y-12,
piece_x+8, piece_y+8,
fill=gradient_color, stipple='gray50')
# 高光效果
self.canvas.create_oval(piece_x-10, piece_y-10,
piece_x-4, piece_y-4,
fill='white', stipple='gray75')
# 添加渐变效果
if self.current_player == 1: # 黑棋
gradient_color = '#444444'
gradient_pos = 8 # 渐变位置
else: # 白棋
gradient_color = '#e0e0e0'
gradient_pos = 8 # 调整白棋渐变位置
self.canvas.create_oval(piece_x-12, piece_y-12,
piece_x+gradient_pos, piece_y+gradient_pos,
fill=gradient_color, stipple='gray50')
# 添加高光效果
if self.current_player == 1: # 黑棋
shine_size = 6
shine_pos = -10
else: # 白棋
shine_size = 6
shine_pos = -10
self.canvas.create_oval(piece_x+shine_pos, piece_y+shine_pos,
piece_x+shine_pos+shine_size, piece_y+shine_pos+shine_size,
fill='white', stipple='gray75')
def redraw_all_pieces(self):
# 重新绘制所有已放置的棋子
for y in range(self.board_size):
for x in range(self.board_size):
if self.board[y][x] != 0:
# 临时保存当前玩家
original_player = self.current_player
# 设置为对应的玩家
self.current_player = self.board[y][x]
# 绘制棋子
self.place_piece(x, y)
# 恢复当前玩家
self.current_player = original_player
def handle_click(self, event):
# 将点击位置转换为棋盘坐标
x = round((event.x - self.board_margin) / self.cell_size)
y = round((event.y - self.board_margin) / self.cell_size)
# 检查是否在有效范围内
if 0 <= x < self.board_size and 0 <= y < self.board_size:
if self.board[y][x] == 0: # 如果该位置没有棋子
self.place_piece(x, y)
if self.check_win(x, y):
self.window.update()
winner = "黑方" if self.current_player == 1 else "白方"
messagebox.showinfo("游戏结束", f"{winner}获胜!")
self.reset_game()
self.current_player = 3 - self.current_player
# 重绘棋盘以更新当前执子显示
self.canvas.delete("all")
canvas_size = self.board_size * self.cell_size + self.board_margin + 30
try:
self.canvas.create_image(canvas_size//2, canvas_size//2,
image=self.bg_image)
except:
self.canvas.create_rectangle(0, 0, canvas_size, canvas_size,
fill='#CDBA96', outline='#CDBA96')
self.draw_board()
# 重新绘制所有棋子
self.redraw_all_pieces()
def check_win(self, x, y):
directions = [(1,0), (0,1), (1,1), (1,-1)] # 横、竖、右斜、左斜
for dx, dy in directions:
count = 1
winning_pieces = [(x, y)] # 记录获胜棋子的位置
# 正向检查
temp_x, temp_y = x + dx, y + dy
while 0 <= temp_x < self.board_size and 0 <= temp_y < self.board_size:
if self.board[temp_y][temp_x] == self.current_player:
count += 1
winning_pieces.append((temp_x, temp_y))
temp_x += dx
temp_y += dy
else:
break
# 反向检查
temp_x, temp_y = x - dx, y - dy
while 0 <= temp_x < self.board_size and 0 <= temp_y < self.board_size:
if self.board[temp_y][temp_x] == self.current_player:
count += 1
winning_pieces.append((temp_x, temp_y))
temp_x -= dx
temp_y -= dy
else:
break
if count >= 5:
self.highlight_winning_pieces(winning_pieces)
return True
return False
def highlight_winning_pieces(self, positions):
for x, y in positions:
piece_x = self.board_margin + x * self.cell_size
piece_y = self.board_margin + y * self.cell_size
# 绘制高亮边框
self.canvas.create_oval(piece_x-16, piece_y-16,
piece_x+16, piece_y+16,
outline='red',
width=2)
def reset_game(self):
# 清空棋盘数据
self.board = [[0] * self.board_size for _ in range(self.board_size)]
# 清空画布
self.canvas.delete("all")
# 重新绘制背景
canvas_size = self.board_size * self.cell_size + self.board_margin + 30
try:
# 重新显示背景图片
self.canvas.create_image(canvas_size//2, canvas_size//2,
image=self.bg_image)
except:
# 如果加载图片失败,使用纯色背景
self.canvas.create_rectangle(0, 0, canvas_size, canvas_size,
fill='#CDBA96', outline='#CDBA96')
# 重新绘制棋盘
self.draw_board()
# 重置当前玩家
self.current_player = 1
def run(self):
self.window.mainloop()
if __name__ == "__main__":
game = Gobang()
game.run()