[Python] 纯文本查看 复制代码
import turtle
import random
# 设置屏幕
screen = turtle.Screen()
screen.title("中国象棋小游戏 - 玩家 vs AI")
screen.setup(width=800, height=600)
# 常量定义
board_size = 9 # 9列
rows = 10 # 10行
cell_size = 60 # 每个格子宽度和高度
offset_x = -cell_size * (board_size - 1) / 2
offset_y = -cell_size * (rows - 1) / 2
# 棋盘绘制画笔
pen = turtle.Turtle()
pen.speed(0)
pen.hideturtle()
# 棋子列表
pieces = []
# 当前选中的棋子
selected_piece = None
# 当前回合
player_turn = True # 玩家先手
# 绘制棋盘
def draw_board():
pen.penup()
# 横线
for i in range(rows):
y = offset_y + i * cell_size
pen.goto(offset_x, y)
pen.pendown()
pen.goto(offset_x + (board_size - 1) * cell_size, y)
pen.penup()
# 竖线
for j in range(board_size):
x = offset_x + j * cell_size
start_y = offset_y
end_y = offset_y + 4 * cell_size
pen.goto(x, start_y)
pen.pendown()
pen.goto(x, end_y)
pen.penup()
start_y2 = offset_y + 5 * cell_size
end_y2 = offset_y + 9 * cell_size
pen.goto(x, start_y2)
pen.pendown()
pen.goto(x, end_y2)
pen.penup()
# 河界横线
mid_y = offset_y + 4 * cell_size
pen.goto(offset_x, mid_y)
pen.pendown()
pen.goto(offset_x + 4 * cell_size, mid_y)
pen.penup()
pen.goto(offset_x + 5 * cell_size, mid_y)
pen.pendown()
pen.goto(offset_x + 8 * cell_size, mid_y)
pen.penup()
# 棋子类
class Piece:
def __init__(self, x, y, label, color):
self.x = x
self.y = y
self.label = label
self.color = color
self.turtle = turtle.Turtle()
self.turtle.hideturtle()
self.turtle.penup()
self.turtle.shape("circle")
self.turtle.shapesize(2)
self.turtle.color(color)
self.turtle.goto(self.get_screen_position())
self.turtle.showturtle()
self.label_turtle = turtle.Turtle()
self.label_turtle.hideturtle()
self.label_turtle.penup()
self.draw_label()
def get_screen_position(self):
"""将棋盘坐标转换为屏幕坐标"""
return offset_x + self.x * cell_size, offset_y + self.y * cell_size
def draw_label(self):
"""在棋子上画出文字"""
self.label_turtle.clear()
self.label_turtle.goto(self.get_screen_position())
self.label_turtle.write(self.label, align="center", font=("Arial", 14, "bold"))
def move_to(self, x, y):
"""移动棋子"""
self.x = x
self.y = y
self.turtle.goto(self.get_screen_position())
self.draw_label()
# 初始化棋子
def setup_pieces():
global pieces
pieces = [
# 红方棋子
Piece(0, 9, "車", "red"), Piece(1, 9, "馬", "red"), Piece(2, 9, "炮", "red"),
Piece(4, 9, "將", "red"), Piece(8, 9, "車", "red"),
# 蓝方棋子
Piece(0, 0, "車", "blue"), Piece(1, 0, "馬", "blue"), Piece(2, 0, "炮", "blue"),
Piece(4, 0, "帅", "blue"), Piece(8, 0, "車", "blue")
]
# 检查点击位置是否有棋子
def find_piece_at(x, y):
for piece in pieces:
if piece.x == x and piece.y == y:
return piece
return None
# 检查车的合法移动
def is_valid_move_rook(piece, new_x, new_y):
"""判断车的移动是否合法"""
if piece.x != new_x and piece.y != new_y:
return False # 车只能沿直线移动
# 判断路径上是否有其他棋子
if piece.x == new_x: # 垂直移动
step = 1 if new_y > piece.y else -1
for y in range(piece.y + step, new_y, step):
if find_piece_at(new_x, y):
return False
elif piece.y == new_y: # 水平移动
step = 1 if new_x > piece.x else -1
for x in range(piece.x + step, new_x, step):
if find_piece_at(x, piece.y):
return False
return True
# 玩家点击事件处理
def on_click(x, y):
global selected_piece, player_turn
# 如果不是玩家回合,忽略点击
if not player_turn:
return
# 将屏幕坐标转换为棋盘坐标
board_x = round((x - offset_x) / cell_size)
board_y = round((y - offset_y) / cell_size)
# 判断是否在棋盘内
if 0 <= board_x < board_size and 0 <= board_y < rows:
clicked_piece = find_piece_at(board_x, board_y)
if selected_piece:
# 如果有选中的棋子,尝试移动
if not clicked_piece and is_valid_move_rook(selected_piece, board_x, board_y): # 目标位置为空
selected_piece.move_to(board_x, board_y)
selected_piece = None
check_game_over() # 检查游戏是否结束
player_turn = False # 结束玩家回合
ai_turn() # 轮到AI
else:
print("非法移动或目标位置有棋子!")
else:
# 如果没有选中的棋子,选择棋子
if clicked_piece and clicked_piece.color == "red": # 只能选红色棋子
selected_piece = clicked_piece
print(f"选中了棋子: {clicked_piece.label}")
# AI回合
def ai_turn():
global player_turn
# 获取所有蓝色棋子
ai_pieces = [piece for piece in pieces if piece.color == "blue"]
# 筛选所有红色棋子的位置
red_positions = {(piece.x, piece.y) for piece in pieces if piece.color == "red"}
# 尝试优先吃子
for piece in ai_pieces:
for dx in [-1, 0, 1]:
for dy in [-1, 0, 1]: # 遍历周围的8个格子
new_x = piece.x + dx
new_y = piece.y + dy
if (new_x, new_y) in red_positions: # 如果目标位置有红色棋子
piece.move_to(new_x, new_y)
print(f"AI吃掉棋子: {find_piece_at(new_x, new_y).label}")
# 移除被吃掉的棋子
pieces.remove(find_piece_at(new_x, new_y))
check_game_over() # 检查游戏是否结束
player_turn = True # 结束AI回合
return
# 随机寻找安全位置
for piece in ai_pieces:
attempts = 0
while attempts < 10: # 尝试最多10次
new_x = random.randint(0, board_size - 1)
new_y = random.randint(0, rows - 1)
if not find_piece_at(new_x, new_y): # 如果目标位置为空
piece.move_to(new_x, new_y)
print(f"AI移动棋子: {piece.label} 到 ({new_x}, {new_y})")
player_turn = True # 结束AI回合
return
attempts += 1
print("AI没有合法移动!")
player_turn = True # AI回合结束
# 检查游戏是否结束
def check_game_over():
red_king = any(piece.label == "將" and piece.color == "red" for piece in pieces)
blue_king = any(piece.label == "帅" and piece.color == "blue" for piece in pieces)
if not red_king:
print("蓝方胜利!")
screen.bye()
elif not blue_king:
print("红方胜利!")
screen.bye()
# 绘制棋盘和棋子
draw_board()
setup_pieces()
# 绑定鼠标点击事件
screen.onclick(on_click)
# 保持窗口
turtle.done()