找回密码
 中文实名注册
搜索
查看: 277|回复: 0

象棋

[复制链接]

7

主题

72

回帖

2万

积分

超级版主

积分
21062
发表于 2025-7-4 18:36:41 | 显示全部楼层 |阅读模式
[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()

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 中文实名注册

本版积分规则

快速回复 返回顶部 返回列表