from enum import Enum
import pygame
import sys
import random
# 初始化Pygame
pygame.init()
# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
GREEN = (0, 255, 0)
BOARD_COLOR = (245, 222, 179)
BUTTON_COLOR = (100, 100, 100)
# 窗口设置
WIDTH, HEIGHT = 1000, 800
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("成三棋")
# 字体设置
font = pygame.font.SysFont('simhei', 24)
big_font = pygame.font.SysFont('simhei', 36)
class GameState(Enum):
PLACE = 1
MOVE = 2
REMOVE = 3
GAME_OVER = 4
class Game:
def __init__(self):
self.reset()
def reset(self):
self.state = None
self.board = [''] * 24
self.placed = {'red': 0, 'black': 0}
self.turn = None
self.selected = -1
self.remove_list = []
self.buttons = [
self.create_button("玩家先手", (50, 700, 200, 60)),
self.create_button("电脑先手", (750, 700, 200, 60))
]
# 棋盘参数
self.center = (500, 400)
self.radius = [220, 150, 80]
self.points = self.calculate_points()
self.lines = self.get_all_lines()
self.neighbors = self.get_neighbors()
# 新增check_phase方法
def check_phase(self):
"""检查是否需要进入走子阶段"""
if self.state == GameState.PLACE and self.placed['red'] >= 9 and self.placed['black'] >= 9:
self.state = GameState.MOVE
def create_button(self, text, rect):
return {
'rect': pygame.Rect(rect),
'text': text,
'color': BUTTON_COLOR,
'visible': True
}
def calculate_points(self):
points = []
# 计算三个正方形的24个点
for r in self.radius:
square = [
(self.center[0] - r, self.center[1] - r), # 左上
(self.center[0], self.center[1] - r), # 上中
(self.center[0] + r, self.center[1] - r), # 右上
(self.center[0] + r, self.center[1]), # 右中
(self.center[0] + r, self.center[1] + r), # 右下
(self.center[0], self.center[1] + r), # 下中
(self.center[0] - r, self.center[1] + r), # 左下
(self.center[0] - r, self.center[1]) # 左中
]
points.extend(square)
return points
def get_all_lines(self):
return [
# 外层正方形
[0, 1, 2], [2, 3, 4], [4, 5, 6], [6, 7, 0],
# 中层正方形
[8, 9, 10], [10, 11, 12], [12, 13, 14], [14, 15, 8],
# 内层正方形
[16, 17, 18], [18, 19, 20], [20, 21, 22], [22, 23, 16],
# 垂直线
[1, 9, 17], [3, 11, 19], [5, 13, 21], [7, 15, 23]
]
def get_neighbors(self):
# 定义每个点的相邻点
return [
[1, 7], [0, 2, 9], [1, 3], [2, 4, 11], [3, 5], [4, 6, 13],
[5, 7], [0, 6, 15], [9, 15], [8, 10, 17, 1], [9, 11], [10, 12, 19, 3],
[11, 13], [12, 14, 21, 5], [13, 15], [14, 8, 23, 7], [17, 23],
[16, 18, 9], [17, 19], [18, 20, 11], [19, 21], [20, 22, 13],
[21, 23], [22, 16, 15]
]
def draw_board(self):
screen.fill(BOARD_COLOR)
# 绘制三个正方形
for r in self.radius:
rect = (self.center[0] - r, self.center[1] - r, 2 * r, 2 * r)
pygame.draw.rect(screen, BLACK, rect, 2)
# 绘制连接线
for i in [1, 3, 5, 7]:
pygame.draw.line(screen, BLACK, self.points[i], self.points[i + 8], 2)
pygame.draw.line(screen, BLACK, self.points[i], self.points[i + 16], 2)
# 绘制棋子
for i, pos in enumerate(self.points):
if self.board[i] == 'red':
pygame.draw.circle(screen, RED, pos, 25)
elif self.board[i] == 'black':
pygame.draw.circle(screen, BLACK, pos, 25)
# 绘制选中状态
if self.selected != -1:
pygame.draw.circle(screen, GREEN, self.points[self.selected], 20, 3)
# 绘制可吃子提示
for i in self.remove_list:
pygame.draw.circle(screen, YELLOW, self.points[i], 20, 3)
# 绘制状态提示
self.draw_status()
# 绘制按钮
for btn in self.buttons:
if btn['visible']:
pygame.draw.rect(screen, btn['color'], btn['rect'], border_radius=5)
text = big_font.render(btn['text'], True, WHITE)
screen.blit(text, (btn['rect'].x + 20, btn['rect'].y + 15))
# 绘制状态提示
self.draw_status()
def draw_status(self):
status_text = []
if self.state:
if self.state == GameState.PLACE:
status_text.append(f"布子阶段 - {self.turn}方回合")
status_text.append(f"红方已布子: {self.placed['red']}/9")
status_text.append(f"黑方已布子: {self.placed['black']}/9")
elif self.state == GameState.MOVE:
status_text.append("走子阶段")
elif self.state == GameState.REMOVE:
attacker = 'red' if self.turn == 'red' else 'black' # 修正显示逻辑
status_text.append(f"{attacker.upper()}方成三!请吃子")
# 确保文本渲染到屏幕
for i, text in enumerate(status_text):
text_surf = font.render(text, True, BLACK)
screen.blit(text_surf, (20, 20 + i * 30))
def check_three(self, player):
for line in self.lines:
if all(self.board[i] == player for i in line):
return True
return False
def get_removable(self, attacker):
"""修正攻击方和防守方关系"""
defender = 'black' if attacker == 'red' else 'red'
removable = []
for i in range(24):
if self.board[i] == defender:
safe = any(all(self.board[j] == defender for j in line)
for line in self.lines if i in line)
if not safe:
removable.append(i)
return removable
def check_win(self):
"""只在走子阶段检查胜利条件"""
if self.state != GameState.MOVE:
return None
# 检查棋子数量
red_count = self.board.count('red')
black_count = self.board.count('black')
if red_count < 3:
return 'black'
if black_count < 3:
return 'red'
# 检查移动能力
def can_move(player):
for i in range(24):
if self.board[i] == player:
if any(self.board[n] == '' for n in self.neighbors[i]):
return True
return False
current_player = 'red' if self.turn == 'red' else 'black'
if not can_move(current_player):
return 'black' if current_player == 'red' else 'red'
return None
def ai_move(self):
# 简单AI策略
if self.state == GameState.PLACE:
# 尝试完成三连
for i in range(24):
if self.board[i] == '':
self.board[i] = 'black'
if self.check_three('black'):
return i
self.board[i] = ''
# 阻止玩家三连
for i in range(24):
if self.board[i] == '':
self.board[i] = 'red'
if self.check_three('red'):
self.board[i] = ''
return i
self.board[i] = ''
# 随机选择
empty = [i for i in range(24) if self.board[i] == '']
return random.choice(empty)
elif self.state == GameState.MOVE:
# 寻找可移动棋子
moves = []
for src in range(24):
if self.board[src] == 'black':
for dest in self.neighbors[src]:
if self.board[dest] == '':
moves.append((src, dest))
# 优先成三的移动
for src, dest in moves:
temp = self.board.copy()
temp[src] = ''
temp[dest] = 'black'
if self.check_three('black'):
return (src, dest)
return random.choice(moves) if moves else None
def handle_click(self, pos):
# 修改状态判断逻辑
if self.state is None: # 改为判断state是否为None
for btn in self.buttons:
if btn['visible'] and btn['rect'].collidepoint(pos):
if btn['text'] == "玩家先手":
self.turn = 'red'
self.state = GameState.PLACE
self.hide_buttons()
elif btn['text'] == "电脑先手":
self.turn = 'black'
self.state = GameState.PLACE
self.hide_buttons()
return
# 获取点击位置
for i, (x, y) in enumerate(self.points):
if (pos[0] - x) ** 2 + (pos[1] - y) ** 2 <= 400:
return i
return -1
def hide_buttons(self):
for btn in self.buttons:
btn['visible'] = False
def run(self):
clock = pygame.time.Clock()
ai_delay = 0
ai_remove_target = -1 # 新增:记录AI要吃的棋子位置
while True:
# 处理事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
clicked_point = self.handle_click(pos)
# 玩家吃子处理
if self.state == GameState.REMOVE and self.turn == 'red':
if clicked_point in self.remove_list:
self.board[clicked_point] = ''
self.remove_list = []
# 检查是否进入走子阶段
if self.placed['red'] >= 9 and self.placed['black'] >= 9:
self.state = GameState.MOVE
else:
self.state = GameState.PLACE
self.turn = 'black'
ai_delay = 30
# 玩家布子处理
elif self.state == GameState.PLACE and self.turn == 'red':
if clicked_point is not None and self.board[clicked_point] == '':
self.board[clicked_point] = 'red'
self.placed['red'] += 1
# 检查成三
if self.check_three('red'):
self.remove_list = self.get_removable('red')
if self.remove_list:
self.state = GameState.REMOVE
else:
self.turn = 'black'
ai_delay = 30
self.check_phase()
# AI操作逻辑
if ai_delay > 0:
ai_delay -= 1
elif self.turn == 'black' and self.state != GameState.GAME_OVER:
if self.state == GameState.PLACE:
ai_pos = self.ai_move()
self.board[ai_pos] = 'black'
self.placed['black'] += 1
# 检查成三并处理吃子
if self.check_three('black'):
self.remove_list = self.get_removable('black')
if self.remove_list:
self.state = GameState.REMOVE # 进入吃子状态
ai_remove_target = random.choice(self.remove_list) # 记录要吃的棋子
ai_delay = 30 # 显示1秒后再吃子
else:
self.turn = 'red'
self.check_phase()
# 处理AI吃子延迟显示
if self.state == GameState.REMOVE and ai_delay == 15 and ai_remove_target != -1:
self.state = GameState.PLACE # 恢复布子状态
self.board[ai_remove_target] = ''
self.remove_list = []
ai_remove_target = -1
self.turn = 'red'
self.check_phase()
elif self.state == GameState.MOVE:
move = self.ai_move()
if move:
src, dest = move
self.board[src] = ''
self.board[dest] = 'black'
#self.move_count += 1
if self.check_three('black'):
self.remove_list = self.get_removable('black')
if self.remove_list:
self.state = GameState.REMOVE
self.move_count = 0
self.turn = 'red'
self.winner = self.check_win()
if self.winner:
self.state = GameState.GAME_OVER
# 绘制时显示AI将要吃的棋子
if ai_remove_target != -1:
pygame.draw.circle(screen, YELLOW, self.points[ai_remove_target], 30, 5)
# 在AI操作后添加阶段检查
if self.state == GameState.PLACE:
self.check_phase() # 每次操作后检查阶段转换
# 胜利检查(只在走子阶段)
if self.state == GameState.MOVE:
self.winner = self.check_win()
if self.winner:
self.state = GameState.GAME_OVER
# 绘制界面
self.draw_board()
if self.state == GameState.GAME_OVER:
self.draw_game_over()
pygame.display.flip()
clock.tick(30)
def draw_game_over(self):
if self.winner:
text = big_font.render(f"{self.winner.upper()}方胜利!",
True, RED if self.winner == 'red' else BLACK)
screen.blit(text, (WIDTH // 2 - 100, HEIGHT // 2))
if __name__ == "__main__":
game = Game()
game.run()