|
|
|
@ -0,0 +1,151 @@
|
|
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
"""
|
|
|
|
|
Created on Sat May 24 19:54:17 2025
|
|
|
|
|
|
|
|
|
|
@author: zhangzekai
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
import pygame
|
|
|
|
|
from enum import Enum
|
|
|
|
|
|
|
|
|
|
# 初始化pygame
|
|
|
|
|
pygame.init()
|
|
|
|
|
|
|
|
|
|
# 常量定义
|
|
|
|
|
SCREEN_SIZE = (600, 600)
|
|
|
|
|
CELL_SIZE = 40
|
|
|
|
|
CELL_NUM = 15
|
|
|
|
|
SPACE = 20
|
|
|
|
|
STAR_POINTS = [(4, 4), (10, 10), (10, 4), (4, 10), (7, 7)]
|
|
|
|
|
|
|
|
|
|
# 颜色常量
|
|
|
|
|
BACKGROUND_COLOR = (204, 153, 102)
|
|
|
|
|
LINE_COLOR = (200, 200, 200)
|
|
|
|
|
BLACK_CHESS_COLOR = (30, 30, 30)
|
|
|
|
|
WHITE_CHESS_COLOR = (225, 225, 225)
|
|
|
|
|
STAR_POINT_COLOR = (0, 0, 0)
|
|
|
|
|
TEXT_COLOR = (210, 210, 0)
|
|
|
|
|
|
|
|
|
|
# 游戏状态枚举
|
|
|
|
|
class GameState(Enum):
|
|
|
|
|
ONGOING = 1
|
|
|
|
|
BLACK_WIN = 2
|
|
|
|
|
WHITE_WIN = 3
|
|
|
|
|
|
|
|
|
|
# 初始化窗口
|
|
|
|
|
screen = pygame.display.set_mode(SCREEN_SIZE)
|
|
|
|
|
pygame.display.set_caption('五子棋-EduCoder')
|
|
|
|
|
|
|
|
|
|
# 初始化游戏状态
|
|
|
|
|
board = [[0 for _ in range(CELL_NUM)] for _ in range(CELL_NUM)] # 棋盘状态 0:空 1:黑 2:白
|
|
|
|
|
current_player = 1 # 当前玩家 1:黑 2:白
|
|
|
|
|
game_state = GameState.ONGOING
|
|
|
|
|
|
|
|
|
|
def get_line_num(tx, ty, dx, dy, board, player):
|
|
|
|
|
"""计算指定方向连续棋子数量"""
|
|
|
|
|
count = 0
|
|
|
|
|
while True:
|
|
|
|
|
tx += dx
|
|
|
|
|
ty += dy
|
|
|
|
|
if not (0 <= tx < CELL_NUM and 0 <= ty < CELL_NUM):
|
|
|
|
|
break
|
|
|
|
|
if board[ty][tx] != player:
|
|
|
|
|
break
|
|
|
|
|
count += 1
|
|
|
|
|
return count
|
|
|
|
|
|
|
|
|
|
def check_win(board, x, y, player):
|
|
|
|
|
"""检查是否获胜"""
|
|
|
|
|
directions = [
|
|
|
|
|
[(-1, 0), (1, 0)], # 水平
|
|
|
|
|
[(0, -1), (0, 1)], # 垂直
|
|
|
|
|
[(-1, -1), (1, 1)], # 主对角线
|
|
|
|
|
[(-1, 1), (1, -1)] # 副对角线
|
|
|
|
|
]
|
|
|
|
|
for d in directions:
|
|
|
|
|
dx1, dy1 = d[0]
|
|
|
|
|
dx2, dy2 = d[1]
|
|
|
|
|
num1 = get_line_num(x, y, dx1, dy1, board, player)
|
|
|
|
|
num2 = get_line_num(x, y, dx2, dy2, board, player)
|
|
|
|
|
if num1 + num2 + 1 >= 5:
|
|
|
|
|
return True
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def draw_board():
|
|
|
|
|
"""绘制棋盘"""
|
|
|
|
|
screen.fill(BACKGROUND_COLOR)
|
|
|
|
|
# 绘制网格线
|
|
|
|
|
for i in range(CELL_NUM):
|
|
|
|
|
pygame.draw.line(screen, LINE_COLOR,
|
|
|
|
|
(SPACE, SPACE + i * CELL_SIZE),
|
|
|
|
|
(SPACE + (CELL_NUM-1)*CELL_SIZE, SPACE + i * CELL_SIZE))
|
|
|
|
|
pygame.draw.line(screen, LINE_COLOR,
|
|
|
|
|
(SPACE + i * CELL_SIZE, SPACE),
|
|
|
|
|
(SPACE + i * CELL_SIZE, SPACE + (CELL_NUM-1)*CELL_SIZE))
|
|
|
|
|
# 绘制星位
|
|
|
|
|
for (x, y) in STAR_POINTS:
|
|
|
|
|
if board[y][x] == 0:
|
|
|
|
|
center = (x * CELL_SIZE + SPACE, y * CELL_SIZE + SPACE)
|
|
|
|
|
pygame.draw.circle(screen, STAR_POINT_COLOR, center, 3)
|
|
|
|
|
# 绘制棋子
|
|
|
|
|
for y in range(CELL_NUM):
|
|
|
|
|
for x in range(CELL_NUM):
|
|
|
|
|
if board[y][x] == 1:
|
|
|
|
|
color = BLACK_CHESS_COLOR
|
|
|
|
|
elif board[y][x] == 2:
|
|
|
|
|
color = WHITE_CHESS_COLOR
|
|
|
|
|
else:
|
|
|
|
|
continue
|
|
|
|
|
center = (x * CELL_SIZE + SPACE, y * CELL_SIZE + SPACE)
|
|
|
|
|
pygame.draw.circle(screen, color, center, 16)
|
|
|
|
|
# 绘制胜利信息
|
|
|
|
|
if game_state != GameState.ONGOING:
|
|
|
|
|
font = pygame.font.Font(None, 60)
|
|
|
|
|
text = "Black Wins!" if game_state == GameState.BLACK_WIN else "White Wins!"
|
|
|
|
|
text_surface = font.render(text, True, TEXT_COLOR)
|
|
|
|
|
text_rect = text_surface.get_rect(center=(SCREEN_SIZE[0]//2, SCREEN_SIZE[1]//2))
|
|
|
|
|
screen.blit(text_surface, text_rect)
|
|
|
|
|
|
|
|
|
|
def handle_click(pos):
|
|
|
|
|
"""处理鼠标点击事件"""
|
|
|
|
|
global current_player, game_state
|
|
|
|
|
x, y = pos
|
|
|
|
|
# 转换为棋盘坐标
|
|
|
|
|
grid_x = (x - SPACE) / CELL_SIZE
|
|
|
|
|
grid_y = (y - SPACE) / CELL_SIZE
|
|
|
|
|
# 检查是否在棋盘范围内
|
|
|
|
|
if not (0 <= grid_x < CELL_NUM and 0 <= grid_y < CELL_NUM):
|
|
|
|
|
return
|
|
|
|
|
# 计算最近交叉点坐标
|
|
|
|
|
xi = round(grid_x)
|
|
|
|
|
yi = round(grid_y)
|
|
|
|
|
# 检查落点有效性
|
|
|
|
|
if board[yi][xi] != 0:
|
|
|
|
|
return
|
|
|
|
|
# 检查点击精度(距离交叉点不超过1/4格子)
|
|
|
|
|
distance = ((grid_x - xi)**2 + (grid_y - yi)**2)**0.5
|
|
|
|
|
if distance > 0.25:
|
|
|
|
|
return
|
|
|
|
|
# 落子
|
|
|
|
|
board[yi][xi] = current_player
|
|
|
|
|
# 检查胜利
|
|
|
|
|
if check_win(board, xi, yi, current_player):
|
|
|
|
|
game_state = GameState.BLACK_WIN if current_player == 1 else GameState.WHITE_WIN
|
|
|
|
|
else:
|
|
|
|
|
current_player = 2 if current_player == 1 else 1
|
|
|
|
|
|
|
|
|
|
# 游戏主循环
|
|
|
|
|
running = True
|
|
|
|
|
while running:
|
|
|
|
|
for event in pygame.event.get():
|
|
|
|
|
if event.type == pygame.QUIT:
|
|
|
|
|
running = False
|
|
|
|
|
elif event.type == pygame.MOUSEBUTTONUP and game_state == GameState.ONGOING:
|
|
|
|
|
handle_click(pygame.mouse.get_pos())
|
|
|
|
|
|
|
|
|
|
draw_board()
|
|
|
|
|
pygame.display.update()
|
|
|
|
|
|
|
|
|
|
pygame.quit()
|
|
|
|
|
exit()
|