#!/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()