You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

151 lines
4.5 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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