20242104 实验四《Python程序设计》实验报告

课程:《Python程序设计》
班级: 2421
姓名: 郭禹震
学号:20242104
实验教师:王志强
实验日期:2025年5月14日
必修/选修: 公选课

一、实验内容

(一)项目概述:

这是一个使用Python语言实现的象棋对弈单机版游戏,包含了传统象棋的游戏逻辑,并使用PythonGUI开发来生成直观的图形界面实现玩家间的游戏对弈。

(二)实验功能

(1)生成棋盘:首先,通过导入tkinter库用于创建GUI界面,messagebox用于显示提示框;然后通过定义主类(Chinesechess)创建一个米色背景画布并把它放到窗口;

接着,初始化棋盘参数(子力),棋盘,最后完成棋盘上所有元素的绘制。

(2)自主操作行棋对弈:本程序通过点击实现事件处理,即鼠标点击选中棋子并执行移动;同时,对每个棋子在移动前进行规则检查,若不合行棋规则就无法移动;最后,程序设定

红黑轮换,保证对弈的正常进行。

(3)AI人机对弈:通过在主类中引入AIplayer类,通过设置子力价值评估函数和Minimax游戏算法实现AI的判断与行棋功能。

(4)游戏模式选择:玩家可以在窗口菜单栏选择人人对战、人机对战,并自主选择在人机对战中是否执红先行(玩家在自主对弈和人机对弈中均可在菜单栏选择悔棋操作)。

(5)可扩展功能:1.优化AI算法,通过进一步复杂化条件增强AI判断能力,增强人机难度。 2.完善悔棋操作触发条件,提升玩家间的交互感。

 

(二)实验过程

(一)实验思路

作为从小学就接触象棋的爱好者,其实一直希望能将程序设计与这项爱好结合起来,本次设计我通过导入tkinter库创建GUI界面,完成基本构造布局,逐步完善行棋逻辑,实现基本功能运行,之后引入AI相关算法,实现人机对弈与悔棋等扩展性功能。

(二)实现过程

(1)创建一个简单的 tkinter 图形界面程序,该程序包含基本的窗口设置以及消息框功能演示

import tkinter as tk
from tkinter import messagebox

(2)类初始化与基本设置

class ChineseChess:
    def __init__(self, root):
        self.root = root
        self.root.title("中国象棋")
        self.canvas = tk.Canvas(root, width=540, height=600, bg="#DEB887")  # 棋盘背景色
        self.canvas.pack()

        # 棋盘参数
        self.cell_size = 60  # 格子大小
        self.margin = 30  # 边距

        # 初始化棋盘和棋子
        self.board = [[None for _ in range(9)] for _ in range(10)]
        self.init_board()

        # 游戏状态
        self.selected_piece = None  # 当前选中的棋子
        self.current_player = "red"  # 红方先行
        self.game_over = False  # 游戏是否结束

        # 绘制棋盘和棋子
        self.draw_board()

        # 绑定鼠标点击事件
        self.canvas.bind("<Button-1>", self.on_click)
        self.ai = None  # 新增AI实例变量
        self.ai_enabled = False  # AI开关
        self.move_history = []
        self.setup_menu()  # 添加菜单

(3)棋盘初始化

def init_board(self):
    """初始化棋子位置"""
    # 红方(下方)
    self.board[9][0] = ("red", "车")  # 车
    self.board[9][1] = ("red", "马")  # 马
    self.board[9][2] = ("red", "相")  # 相
    self.board[9][3] = ("red", "士")  # 士
    self.board[9][4] = ("red", "帅")  # 帅
    self.board[9][5] = ("red", "士")  # 士
    self.board[9][6] = ("red", "相")  # 相
    self.board[9][7] = ("red", "马")  # 马
    self.board[9][8] = ("red", "车")  # 车
    self.board[7][1] = ("red", "炮")  # 炮
    self.board[7][7] = ("red", "炮")  # 炮
    self.board[6][0] = ("red", "兵")  # 兵
    self.board[6][2] = ("red", "兵")  # 兵
    self.board[6][4] = ("red", "兵")  # 兵
    self.board[6][6] = ("red", "兵")  # 兵
    self.board[6][8] = ("red", "兵")  # 兵

    # 黑方(上方)
    self.board[0][0] = ("black", "车")  # 车
    self.board[0][1] = ("black", "马")  # 马
    self.board[0][2] = ("black", "象")  # 象
    self.board[0][3] = ("black", "士")  # 士
    self.board[0][4] = ("black", "将")  # 将
    self.board[0][5] = ("black", "士")  # 士
    self.board[0][6] = ("black", "象")  # 象
    self.board[0][7] = ("black", "马")  # 马
    self.board[0][8] = ("black", "车")  # 车
    self.board[2][1] = ("black", "炮")  # 炮
    self.board[2][7] = ("black", "炮")  # 炮
    self.board[3][0] = ("black", "卒")  # 卒
    self.board[3][2] = ("black", "卒")  # 卒
    self.board[3][4] = ("black", "卒")  # 卒
    self.board[3][6] = ("black", "卒")  # 卒
    self.board[3][8] = ("black", "卒")  # 卒

(4)绘制棋盘

def draw_board(self):
    """绘制棋盘和棋子"""
    self.canvas.delete("all")  # 清空画布

    # 1. 绘制棋盘网格
    for row in range(10):
        self.canvas.create_line(
            self.margin, self.margin + row * self.cell_size,
                         self.margin + 8 * self.cell_size, self.margin + row * self.cell_size,
            width=2
        )
    for col in range(9):
        if col == 0 or col == 8:
            # 边缘竖线贯穿整个棋盘
            self.canvas.create_line(
                self.margin + col * self.cell_size, self.margin,
                self.margin + col * self.cell_size, self.margin + 9 * self.cell_size,
                width=2
            )
        else:
            # 中间竖线在"楚河汉界"处断开
            self.canvas.create_line(
                self.margin + col * self.cell_size, self.margin,
                self.margin + col * self.cell_size, self.margin + 4 * self.cell_size,
                width=2
            )
            self.canvas.create_line(
                self.margin + col * self.cell_size, self.margin + 5 * self.cell_size,
                self.margin + col * self.cell_size, self.margin + 9 * self.cell_size,
                width=2
            )

    # 2. 绘制"楚河汉界"
    self.canvas.create_text(
        self.margin + 4 * self.cell_size, self.margin + 4.5 * self.cell_size,
        text="楚河        汉界", font=("楷体", 20), fill="black"
    )

    # 3. 绘制九宫格斜线
    # 上方九宫格
    self.canvas.create_line(
        self.margin + 3 * self.cell_size, self.margin,
        self.margin + 5 * self.cell_size, self.margin + 2 * self.cell_size,
        width=2
    )
    self.canvas.create_line(
        self.margin + 5 * self.cell_size, self.margin,
        self.margin + 3 * self.cell_size, self.margin + 2 * self.cell_size,
        width=2
    )
    # 下方九宫格
    self.canvas.create_line(
        self.margin + 3 * self.cell_size, self.margin + 7 * self.cell_size,
        self.margin + 5 * self.cell_size, self.margin + 9 * self.cell_size,
        width=2
    )
    self.canvas.create_line(
        self.margin + 5 * self.cell_size, self.margin + 7 * self.cell_size,
        self.margin + 3 * self.cell_size, self.margin + 9 * self.cell_size,
        width=2
    )

    # 4. 绘制棋子
    for row in range(10):
        for col in range(9):
            if self.board[row][col]:
                color, name = self.board[row][col]
                x = self.margin + col * self.cell_size
                y = self.margin + row * self.cell_size

                # 绘制棋子(圆形+文字)
                self.canvas.create_oval(
                    x - 25, y - 25, x + 25, y + 25,
                    fill="#DEB887", outline="red" if color == "red" else "black", width=2
                )
                self.canvas.create_text(
                    x, y, text=name, font=("楷体", 20),
                    fill="red" if color == "red" else "black"
                )

        # 5. 显示当前玩家和游戏状态
        status_text = f"当前回合: {'红方' if self.current_player == 'red' else '黑方'}"

        # 检查是否将军并更新状态文本
        if self.is_check():
            status_text += " (将军!)"

        self.canvas.create_text(
            self.margin + 4 * self.cell_size, self.margin + 9.5 * self.cell_size,
            text=status_text,
            font=("楷体", 16), fill="red" if self.current_player == "red" else "black"
        )

        # 6. 显示游戏结束状态
        if self.game_over:
            self.canvas.create_text(
                self.margin + 4 * self.cell_size, self.margin + 10 * self.cell_size,
                text="游戏结束!", font=("楷体", 20), fill="red"
            )

(5)棋子的移动逻辑

def on_click(self, event):
    """处理鼠标点击事件"""
    if self.game_over:
        return

    # 计算点击的棋盘坐标
    col = round((event.x - self.margin) / self.cell_size)
    row = round((event.y - self.margin) / self.cell_size)

    # 检查是否在棋盘范围内
    if not (0 <= row < 10 and 0 <= col < 9):
        return

    # 如果没有选中棋子,则尝试选中
    if self.selected_piece is None:
        if self.board[row][col] and self.board[row][col][0] == self.current_player:
            self.selected_piece = (row, col)
            self.highlight_piece(row, col)

该部分分为两个模块,上面的代码实现的是鼠标点击的选中操作,并由下面的代码实现选中后的高亮显示

def highlight_piece(self, row, col):
    """高亮选中的棋子"""
    x = self.margin + col * self.cell_size
    y = self.margin + row * self.cell_size
    self.canvas.create_oval(
        x - 28, y - 28, x + 28, y + 28,
        outline="green", width=3
    )

第二部分为选中后的行棋操作,代码如下:

else:
    old_row, old_col = self.selected_piece
    piece = self.board[old_row][old_col]

    if self.is_valid_move(old_row, old_col, row, col):
        # 记录被吃的子(如果有)
        captured_piece = self.board[row][col]

        # 模拟移动,检查是否会导致自己的将/帅被将军
        self.board[row][col] = piece
        self.board[old_row][old_col] = None

        if self.is_check():
            # 恢复移动
            self.board[old_row][old_col] = piece
            self.board[row][col] = captured_piece
            messagebox.showwarning("非法移动", "不能送将!")
            self.selected_piece = None
            return

        # 正式执行移动并记录历史
        self.board[row][col] = piece
        self.board[old_row][old_col] = None
        self.record_move((old_row, old_col), (row, col), captured_piece)

        # 检查是否将军对方
        self.current_player = "black" if self.current_player == "red" else "red"
        if self.is_check():
            # 显示将军提示
            self.draw_board()
            messagebox.showwarning("将军!", f"{'红方' if self.current_player == 'red' else '黑方'}被将军!")

            # 检查是否将死
            if self.is_checkmate():
                self.game_over = True
                winner = "黑方" if self.current_player == "red" else "红方"
                messagebox.showinfo("游戏结束", f"{winner}获胜!")

        self.draw_board()

        # 触发AI移动
        if self.ai_enabled and self.current_player == self.ai.color and not self.game_over:
            self.root.after(500, self.ai_move)

    self.selected_piece = None  # 取消选中

该部分调用了后续有关有效行棋规则检验,将军与将死的验证操作,以及在人机交互模式下AI在基础行棋时的响应。

(6)棋子移动验证

def is_valid_move(self, old_row, old_col, new_row, new_col):
    """检查移动是否合法"""
    piece = self.board[old_row][old_col]
    target_piece = self.board[new_row][new_col]

    # 1. 不能吃自己的棋子
    if target_piece and target_piece[0] == piece[0]:
        return False

    # 2. 获取棋子类型
    color, name = piece

    # 3. 简化版规则验证
    if name == "车":
        # 车走直线,路径上不能有障碍
        if old_row == new_row:  # 横向移动
            step = 1 if new_col > old_col else -1
            for col in range(old_col + step, new_col, step):
                if self.board[old_row][col]:
                    return False
        elif old_col == new_col:  # 纵向移动
            step = 1 if new_row > old_row else -1
            for row in range(old_row + step, new_row, step):
                if self.board[row][old_col]:
                    return False
        else:
            return False
        return True

    elif name == "马":
        # 马走"日"字,且马脚无子
        dx = abs(new_col - old_col)
        dy = abs(new_row - old_row)
        if (dx == 1 and dy == 2) or (dx == 2 and dy == 1):
            # 检查马脚
            if dx == 2:  # 横向跳
                mid_col = (old_col + new_col) // 2
                if self.board[old_row][mid_col]:
                    return False
            else:  # 纵向跳
                mid_row = (old_row + new_row) // 2
                if self.board[mid_row][old_col]:
                    return False
            return True
        return False

    elif name == "炮":
        # 炮走直线,吃子时中间必须有一个棋子
        if old_row == new_row:  # 横向移动
            step = 1 if new_col > old_col else -1
            count = 0  # 中间棋子计数
            for col in range(old_col + step, new_col, step):
                if self.board[old_row][col]:
                    count += 1
        elif old_col == new_col:  # 纵向移动
            step = 1 if new_row > old_row else -1
            count = 0
            for row in range(old_row + step, new_row, step):
                if self.board[row][old_col]:
                    count += 1
        else:
            return False

        # 炮的规则
        if target_piece:  # 吃子
            return count == 1
        else:  # 移动
            return count == 0

    elif name in ("兵", "卒"):
        # 兵/卒只能向前或过河后左右移动
        if color == "red":  # 红方(下方)
            if new_row > old_row:  # 不能后退
                return False
            if old_row >= 5:  # 未过河
                return new_col == old_col and new_row == old_row - 1
            else:  # 已过河
                return (new_col == old_col and new_row == old_row - 1) or \
                    (new_row == old_row and abs(new_col - old_col) == 1)
        else:  # 黑方(上方)
            if new_row < old_row:  # 不能后退
                return False
            if old_row <= 4:  # 未过河
                return new_col == old_col and new_row == old_row + 1
            else:  # 已过河
                return (new_col == old_col and new_row == old_row + 1) or \
                    (new_row == old_row and abs(new_col - old_col) == 1)

    elif name in ("士", "士"):  # 士的移动规则
        # 士只能在九宫格内斜走一格
        if color == "red":  # 红方(下方)
            palace_rows = (7, 8, 9)
            palace_cols = (3, 4, 5)
        else:  # 黑方(上方)
            palace_rows = (0, 1, 2)
            palace_cols = (3, 4, 5)

        # 检查目标位置是否在九宫格内
        if new_row not in palace_rows or new_col not in palace_cols:
            return False

        # 检查是否是斜走一格
        return abs(new_row - old_row) == 1 and abs(new_col - old_col) == 1

    elif name in ("相", "象"):  # 相/象的移动规则
        # 相/象走"田"字,且不能过河
        dx = abs(new_col - old_col)
        dy = abs(new_row - old_row)

        if dx == 2 and dy == 2:
            # 检查象眼(田字中心)是否有子
            mid_row = (old_row + new_row) // 2
            mid_col = (old_col + new_col) // 2
            if self.board[mid_row][mid_col]:
                return False

            # 检查是否过河
            if color == "red" and new_row < 5:  # 红相不能过河
                return False
            if color == "black" and new_row > 4:  # 黑象不能过河
                return False

            return True
        return False

    elif name in ("帅", "将"):  # 将/帅的移动规则
        # 将/帅只能在九宫格内走一格
        if color == "red":  # 红方(下方)
            palace_rows = (7, 8, 9)
            palace_cols = (3, 4, 5)
        else:  # 黑方(上方)
            palace_rows = (0, 1, 2)
            palace_cols = (3, 4, 5)

        # 检查目标位置是否在九宫格内
        if new_row not in palace_rows or new_col not in palace_cols:
            return False

        # 检查是否是走一格(横或竖)
        if not ((abs(new_row - old_row) == 1 and new_col == old_col) or \
                (abs(new_col - old_col) == 1 and new_row == old_row)):
            return False

        # 检查移动后是否会导致将帅直接对面
        # 临时模拟移动
        original_piece = self.board[new_row][new_col]
        self.board[new_row][new_col] = self.board[old_row][old_col]
        self.board[old_row][old_col] = None

        # 检查将帅是否直接对面
        kings_face_each_other = self.check_kings_facing()

        # 恢复模拟移动
        self.board[old_row][old_col] = self.board[new_row][new_col]
        self.board[new_row][new_col] = original_piece

        # 如果移动会导致将帅直接对面,则不允许
        if kings_face_each_other:
            return False

        return True
    return False

规定了所有子力的行棋规则,对将帅不能对面这项规则做了额外约束,约束代码如下

def check_kings_facing(self):
    """检查将帅是否直接对面(中间无棋子阻挡)"""
    # 查找将和帅的位置
    red_king_pos = None
    black_king_pos = None

    for row in range(10):
        for col in range(9):
            piece = self.board[row][col]
            if piece and piece[1] in ("帅", "将"):
                if piece[0] == "red":
                    red_king_pos = (row, col)
                else:
                    black_king_pos = (row, col)

    # 如果有一方的将/帅不在棋盘上(被吃掉了),则不算对面
    if not red_king_pos or not black_king_pos:
        return False

    red_row, red_col = red_king_pos
    black_row, black_col = black_king_pos

    # 将帅必须在同一列上
    if red_col != black_col:
        return False

    # 检查中间是否有棋子阻挡
    for row in range(black_row + 1, red_row):
        if self.board[row][red_col]:
            return False

    return True

(7)检验是否将军或将死

def check_kings_facing(self):
    """检查将帅是否直接对面(中间无棋子阻挡)"""
    # 查找将和帅的位置
    red_king_pos = None
    black_king_pos = None

    for row in range(10):
        for col in range(9):
            piece = self.board[row][col]
            if piece and piece[1] in ("帅", "将"):
                if piece[0] == "red":
                    red_king_pos = (row, col)
                else:
                    black_king_pos = (row, col)

    # 如果有一方的将/帅不在棋盘上(被吃掉了),则不算对面
    if not red_king_pos or not black_king_pos:
        return False

    red_row, red_col = red_king_pos
    black_row, black_col = black_king_pos

    # 将帅必须在同一列上
    if red_col != black_col:
        return False

    # 检查中间是否有棋子阻挡
    for row in range(black_row + 1, red_row):
        if self.board[row][red_col]:
            return False

    return True

def is_check(self):
    """检查当前玩家是否被将军"""
    # 找到当前玩家的将/帅位置
    king_pos = None
    opponent_color = "black" if self.current_player == "red" else "red"

    for row in range(10):
        for col in range(9):
            piece = self.board[row][col]
            if piece and piece[0] == self.current_player and piece[1] in ("帅", "将"):
                king_pos = (row, col)
                break
        if king_pos:
            break

    if not king_pos:
        return False  # 将/帅已经被吃掉了

    # 检查对手的所有棋子是否能攻击将/帅
    for row in range(10):
        for col in range(9):
            piece = self.board[row][col]
            if piece and piece[0] == opponent_color:
                if self.is_valid_move(row, col, king_pos[0], king_pos[1]):
                    return True

    return False

def is_checkmate(self):
    """检查当前玩家是否被将死"""
    if not self.is_check():
        return False

    # 尝试所有可能的移动,看看是否能解除将军状态
    for row in range(10):
        for col in range(9):
            piece = self.board[row][col]
            if piece and piece[0] == self.current_player:
                for r in range(10):
                    for c in range(9):
                        if self.is_valid_move(row, col, r, c):
                            # 模拟移动
                            original_piece = self.board[r][c]
                            self.board[r][c] = self.board[row][col]
                            self.board[row][col] = None

                            # 检查是否仍然被将军
                            still_in_check = self.is_check()

                            # 恢复移动
                            self.board[row][col] = self.board[r][c]
                            self.board[r][c] = original_piece

                            if not still_in_check:
                                return False  # 找到一步可以解除将军的走法

    return True  # 没有找到可以解除将军的走法

至此,这个象棋游戏的基础功能已经完全实现,下面是对其扩展功能的扩充——

(1)AI算法的引入

class AIPlayer:
    def __init__(self, game, color):
        self.game = game  # 主游戏引用
        self.color = color  # 'red'或'black'
        self.depth = 3  # 搜索深度

    def evaluate_board(self):
        """评估当前棋盘分数"""
        piece_values = {
            '车': 500, '马': 300, '炮': 300,
            '帅': 10000, '将': 10000,
            '士': 200, '相': 200, '象': 200,
            '兵': 100, '卒': 100
        }
        score = 0
        for row in range(10):
            for col in range(9):
                if self.game.board[row][col]:
                    color, name = self.game.board[row][col]
                    value = piece_values.get(name, 0)
                    score += value if color == self.color else -value
        return score

    def get_all_moves(self, color):
        """获取当前颜色所有合法移动"""
        moves = []
        for row in range(10):
            for col in range(9):
                piece = self.game.board[row][col]
                if piece and piece[0] == color:
                    for r in range(10):
                        for c in range(9):
                            if self.game.is_valid_move(row, col, r, c):
                                moves.append(((row, col), (r, c)))
        return moves

    def minimax(self, depth, alpha, beta, maximizing_player):
        """Minimax算法实现"""
        if depth == 0:
            return self.evaluate_board()

        if maximizing_player:
            max_eval = float('-inf')
            for move in self.get_all_moves(self.color):
                # 模拟移动
                old_row, old_col = move[0]
                new_row, new_col = move[1]
                captured = self.game.board[new_row][new_col]
                moving_piece = self.game.board[old_row][old_col]

                self.game.board[new_row][new_col] = moving_piece
                self.game.board[old_row][old_col] = None

                eval = self.minimax(depth - 1, alpha, beta, False)

                # 恢复移动
                self.game.board[old_row][old_col] = moving_piece
                self.game.board[new_row][new_col] = captured

                max_eval = max(max_eval, eval)
                alpha = max(alpha, eval)
                if beta <= alpha:
                    break
            return max_eval
        else:
            min_eval = float('inf')
            opponent_color = 'black' if self.color == 'red' else 'red'
            for move in self.get_all_moves(opponent_color):
                # 模拟移动
                old_row, old_col = move[0]
                new_row, new_col = move[1]
                captured = self.game.board[new_row][new_col]
                moving_piece = self.game.board[old_row][old_col]

                self.game.board[new_row][new_col] = moving_piece
                self.game.board[old_row][old_col] = None

                eval = self.minimax(depth - 1, alpha, beta, True)

                # 恢复移动
                self.game.board[old_row][old_col] = moving_piece
                self.game.board[new_row][new_col] = captured

                min_eval = min(min_eval, eval)
                beta = min(beta, eval)
                if beta <= alpha:
                    break
            return min_eval

    def find_best_move(self):
        """寻找最佳移动"""
        best_move = None
        max_eval = float('-inf')

        for move in self.get_all_moves(self.color):
            # 模拟移动
            old_row, old_col = move[0]
            new_row, new_col = move[1]
            captured = self.game.board[new_row][new_col]
            moving_piece = self.game.board[old_row][old_col]

            self.game.board[new_row][new_col] = moving_piece
            self.game.board[old_row][old_col] = None

            eval = self.minimax(self.depth - 1, float('-inf'), float('inf'), False)

            # 恢复移动
            self.game.board[old_row][old_col] = moving_piece
            self.game.board[new_row][new_col] = captured

            if eval > max_eval:
                max_eval = eval
                best_move = move

        return best_move

核心设计思路:

采用基于价值的评估方式,为每种棋子赋予固定分值(如车=500,马=300等)

通过递归搜索可能的走法,构建博弈树

在搜索深度限制内,选择对己方最有利、对对手最不利的走法

使用alpha-beta剪枝减少不必要的搜索分支,提高效率

关键组件解析:

评估函数(evaluate_board):

简单但有效地通过棋子价值差评估局面

己方棋子计正分,对方棋子计负分

将/帅赋予极高价值(10000),体现其关键性

走法生成(get_all_moves):

遍历棋盘所有己方棋子

对每个棋子检查所有合法目标位置

返回所有可能的(起点,终点)移动元组

Minimax核心(minimax):

最大层(maximizing_player):选择对己方最有利的走法

最小层:模拟对手选择对我方最不利的走法

通过depth参数控制搜索深度

alpha-beta剪枝及时终止不利分支的搜索——AI设定有些简单,有很大优化空间。

下面是设置AI玩家与执行AI移动的操作——

def set_ai(self, ai_color):
    """设置AI玩家"""
    self.ai = self.AIPlayer(self, ai_color)
    self.ai_enabled = True
    if self.current_player == ai_color:
        self.ai_move()

def disable_ai(self):
    """禁用AI"""
    self.ai_enabled = False
def ai_move(self):
    if not self.ai_enabled or self.current_player != self.ai.color or self.game_over:
        return

    best_move = self.ai.find_best_move()
    if best_move:
        old_pos, new_pos = best_move
        old_row, old_col = old_pos
        new_row, new_col = new_pos

        # 记录被吃的子(如果有)
        captured_piece = self.board[new_row][new_col]

        # 执行AI移动并记录历史
        self.board[new_row][new_col] = self.board[old_row][old_col]
        self.board[old_row][old_col] = None
        self.record_move((old_row, old_col), (new_row, new_col), captured_piece)

        # 检查是否将军
        self.current_player = 'black' if self.current_player == 'red' else 'red'
        if self.is_check():
            # 检查是否将死
            if self.is_checkmate():
                self.game_over = True
                winner = "红方" if self.current_player == "red" else "黑方"
                messagebox.showinfo("游戏结束", f"{winner}获胜!")

        self.draw_board()

在该部分设计中,结尾插入了将军与游戏结束的提示操作,该提示采用对话框弹出的形式提醒玩家,并终止了游戏,弥补了之前基础功能为实现的游戏结束的操作,避免了之前版本将军时图像显示不明显,

同时避免了之前将死无解仍能继续杀将,甚至是无将仍继续对局的情况。

(二)菜单栏自主选择的设计

本游戏设计了人机对战(红方),人机对战(黑方),人人对战三种功能安置在菜单栏供玩家选择,同时玩家也可以在菜单栏选择悔棋,或重新开始。代码实现如下——

def setup_menu(self):
    menubar = tk.Menu(self.root)
    game_menu = tk.Menu(menubar, tearoff=0)
    game_menu.add_command(label="人机对战(红方)", command=lambda: self.set_ai('black'))
    game_menu.add_command(label="人机对战(黑方)", command=lambda: self.set_ai('red'))
    game_menu.add_command(label="人人对战", command=self.disable_ai)
    game_menu.add_command(label="重新开始", command=self.restart_game)
    game_menu.add_separator()
    game_menu.add_command(label="悔棋", command=self.undo_move)  # 新增悔棋菜单项
    menubar.add_cascade(label="游戏模式", menu=game_menu)
    self.root.config(menu=menubar)

(三)重新开始的功能设计

def restart_game(self):
    """重新开始游戏"""
    self.board = [[None for _ in range(9)] for _ in range(10)]
    self.init_board()
    self.selected_piece = None
    self.current_player = "red"
    self.game_over = False
    self.draw_board()
    if self.ai_enabled and self.ai.color == "red":
        self.ai_move()

(四)悔棋功能设计

def record_move(self, old_pos, new_pos, captured_piece):
        """记录移动历史"""
        self.move_history.append({
            'old_pos': old_pos,
            'new_pos': new_pos,
            'piece': self.board[new_pos[0]][new_pos[1]],  # 移动的棋子
            'captured': captured_piece  # 被吃的子(如果有)
        })

def undo_move(self):
    """悔棋功能"""
    if not self.move_history or self.game_over:
        return

    if self.ai_enabled and len(self.move_history) < 2:
        # 人机对战需要同时撤销玩家和AI的两步
        return

    if self.ai_enabled:
        # 人机对战模式:一次撤销两步(玩家和AI各一步)
        if len(self.move_history) < 2:
            return
        # 先撤销AI的移动
        ai_move = self.move_history.pop()
        self.restore_move(ai_move)
        # 再撤销玩家的移动
        player_move = self.move_history.pop()
        self.restore_move(player_move)
    else:
        # 人人对战模式:一次撤销一步
        last_move = self.move_history.pop()
        self.restore_move(last_move)

    self.draw_board()

def restore_move(self, move_info):
    """恢复棋盘状态到移动前"""
    old_row, old_col = move_info['old_pos']
    new_row, new_col = move_info['new_pos']

    # 恢复移动的棋子
    self.board[old_row][old_col] = move_info['piece']
    # 恢复被吃的子(如果有)
    self.board[new_row][new_col] = move_info['captured']

    # 切换回原来的玩家
    self.current_player = 'red' if self.current_player == 'black' else 'black'

该部分分为,记录移动历史,撤销移动,恢复棋盘状态三个步骤,最终顺利完成小游戏形式的悔棋操作。

 

(三)实验结果展示

(四)实验运行视频

象棋对弈小游戏

 

(五)实验过程中遇到的问题和解决方法

(一)人机交互算法过程中忘记分配设定AI玩家,导致无法分配到AI对手,后来通过查找deepseek完善改部分代码。

(二)由deepseek启发的tkinter库的使用

先前本打算由数组定义棋盘,与其余规则,但不仅不美观,效果也不尽如人意,行列无法对齐,行棋逻辑也存在序号编排的不合理而错误

通过使用tkinter库创建GUI界面,有效解决了一系列问题,也使得该游戏更加美观生动。

(六)全部代码

import tkinter as tk
from tkinter import messagebox



class ChineseChess:
def __init__(self, root):
self.root = root
self.root.title("中国象棋")
self.canvas = tk.Canvas(root, width=540, height=600, bg="#DEB887") # 棋盘背景色
self.canvas.pack()

# 棋盘参数
self.cell_size = 60 # 格子大小
self.margin = 30 # 边距

# 初始化棋盘和棋子
self.board = [[None for _ in range(9)] for _ in range(10)]
self.init_board()

# 游戏状态
self.selected_piece = None # 当前选中的棋子
self.current_player = "red" # 红方先行
self.game_over = False # 游戏是否结束

# 绘制棋盘和棋子
self.draw_board()

# 绑定鼠标点击事件
self.canvas.bind("<Button-1>", self.on_click)
self.ai = None # 新增AI实例变量
self.ai_enabled = False # AI开关
self.move_history = []
self.setup_menu() # 添加菜单

def init_board(self):
"""初始化棋子位置"""
# 红方(下方)
self.board[9][0] = ("red", "车") # 车
self.board[9][1] = ("red", "马") # 马
self.board[9][2] = ("red", "相") # 相
self.board[9][3] = ("red", "士") # 士
self.board[9][4] = ("red", "帅") # 帅
self.board[9][5] = ("red", "士") # 士
self.board[9][6] = ("red", "相") # 相
self.board[9][7] = ("red", "马") # 马
self.board[9][8] = ("red", "车") # 车
self.board[7][1] = ("red", "炮") # 炮
self.board[7][7] = ("red", "炮") # 炮
self.board[6][0] = ("red", "兵") # 兵
self.board[6][2] = ("red", "兵") # 兵
self.board[6][4] = ("red", "兵") # 兵
self.board[6][6] = ("red", "兵") # 兵
self.board[6][8] = ("red", "兵") # 兵

# 黑方(上方)
self.board[0][0] = ("black", "车") # 车
self.board[0][1] = ("black", "马") # 马
self.board[0][2] = ("black", "象") # 象
self.board[0][3] = ("black", "士") # 士
self.board[0][4] = ("black", "将") # 将
self.board[0][5] = ("black", "士") # 士
self.board[0][6] = ("black", "象") # 象
self.board[0][7] = ("black", "马") # 马
self.board[0][8] = ("black", "车") # 车
self.board[2][1] = ("black", "炮") # 炮
self.board[2][7] = ("black", "炮") # 炮
self.board[3][0] = ("black", "卒") # 卒
self.board[3][2] = ("black", "卒") # 卒
self.board[3][4] = ("black", "卒") # 卒
self.board[3][6] = ("black", "卒") # 卒
self.board[3][8] = ("black", "卒") # 卒

def draw_board(self):
"""绘制棋盘和棋子"""
self.canvas.delete("all") # 清空画布

# 1. 绘制棋盘网格
for row in range(10):
self.canvas.create_line(
self.margin, self.margin + row * self.cell_size,
self.margin + 8 * self.cell_size, self.margin + row * self.cell_size,
width=2
)
for col in range(9):
if col == 0 or col == 8:
# 边缘竖线贯穿整个棋盘
self.canvas.create_line(
self.margin + col * self.cell_size, self.margin,
self.margin + col * self.cell_size, self.margin + 9 * self.cell_size,
width=2
)
else:
# 中间竖线在"楚河汉界"处断开
self.canvas.create_line(
self.margin + col * self.cell_size, self.margin,
self.margin + col * self.cell_size, self.margin + 4 * self.cell_size,
width=2
)
self.canvas.create_line(
self.margin + col * self.cell_size, self.margin + 5 * self.cell_size,
self.margin + col * self.cell_size, self.margin + 9 * self.cell_size,
width=2
)

# 2. 绘制"楚河汉界"
self.canvas.create_text(
self.margin + 4 * self.cell_size, self.margin + 4.5 * self.cell_size,
text="楚河 汉界", font=("楷体", 20), fill="black"
)

# 3. 绘制九宫格斜线
# 上方九宫格
self.canvas.create_line(
self.margin + 3 * self.cell_size, self.margin,
self.margin + 5 * self.cell_size, self.margin + 2 * self.cell_size,
width=2
)
self.canvas.create_line(
self.margin + 5 * self.cell_size, self.margin,
self.margin + 3 * self.cell_size, self.margin + 2 * self.cell_size,
width=2
)
# 下方九宫格
self.canvas.create_line(
self.margin + 3 * self.cell_size, self.margin + 7 * self.cell_size,
self.margin + 5 * self.cell_size, self.margin + 9 * self.cell_size,
width=2
)
self.canvas.create_line(
self.margin + 5 * self.cell_size, self.margin + 7 * self.cell_size,
self.margin + 3 * self.cell_size, self.margin + 9 * self.cell_size,
width=2
)

# 4. 绘制棋子
for row in range(10):
for col in range(9):
if self.board[row][col]:
color, name = self.board[row][col]
x = self.margin + col * self.cell_size
y = self.margin + row * self.cell_size

# 绘制棋子(圆形+文字)
self.canvas.create_oval(
x - 25, y - 25, x + 25, y + 25,
fill="#DEB887", outline="red" if color == "red" else "black", width=2
)
self.canvas.create_text(
x, y, text=name, font=("楷体", 20),
fill="red" if color == "red" else "black"
)

# 5. 显示当前玩家和游戏状态
status_text = f"当前回合: {'红方' if self.current_player == 'red' else '黑方'}"

# 检查是否将军并更新状态文本
if self.is_check():
status_text += " (将军!)"

self.canvas.create_text(
self.margin + 4 * self.cell_size, self.margin + 9.5 * self.cell_size,
text=status_text,
font=("楷体", 16), fill="red" if self.current_player == "red" else "black"
)

# 6. 显示游戏结束状态
if self.game_over:
self.canvas.create_text(
self.margin + 4 * self.cell_size, self.margin + 10 * self.cell_size,
text="游戏结束!", font=("楷体", 20), fill="red"
)

def on_click(self, event):
"""处理鼠标点击事件"""
if self.game_over:
return

# 计算点击的棋盘坐标
col = round((event.x - self.margin) / self.cell_size)
row = round((event.y - self.margin) / self.cell_size)

# 检查是否在棋盘范围内
if not (0 <= row < 10 and 0 <= col < 9):
return

# 如果没有选中棋子,则尝试选中
if self.selected_piece is None:
if self.board[row][col] and self.board[row][col][0] == self.current_player:
self.selected_piece = (row, col)
self.highlight_piece(row, col)

# 如果已经选中棋子,则尝试移动
else:
old_row, old_col = self.selected_piece
piece = self.board[old_row][old_col]

if self.is_valid_move(old_row, old_col, row, col):
# 记录被吃的子(如果有)
captured_piece = self.board[row][col]

# 模拟移动,检查是否会导致自己的将/帅被将军
self.board[row][col] = piece
self.board[old_row][old_col] = None

if self.is_check():
# 恢复移动
self.board[old_row][old_col] = piece
self.board[row][col] = captured_piece
messagebox.showwarning("非法移动", "不能送将!")
self.selected_piece = None
return

# 正式执行移动并记录历史
self.board[row][col] = piece
self.board[old_row][old_col] = None
self.record_move((old_row, old_col), (row, col), captured_piece)

# 检查是否将军对方
self.current_player = "black" if self.current_player == "red" else "red"
if self.is_check():
# 显示将军提示
self.draw_board()
messagebox.showwarning("将军!", f"{'红方' if self.current_player == 'red' else '黑方'}被将军!")

# 检查是否将死
if self.is_checkmate():
self.game_over = True
winner = "黑方" if self.current_player == "red" else "红方"
messagebox.showinfo("游戏结束", f"{winner}获胜!")

self.draw_board()

# 触发AI移动
if self.ai_enabled and self.current_player == self.ai.color and not self.game_over:
self.root.after(500, self.ai_move)

self.selected_piece = None # 取消选中


def highlight_piece(self, row, col):
"""高亮选中的棋子"""
x = self.margin + col * self.cell_size
y = self.margin + row * self.cell_size
self.canvas.create_oval(
x - 28, y - 28, x + 28, y + 28,
outline="green", width=3
)

def is_valid_move(self, old_row, old_col, new_row, new_col):
"""检查移动是否合法"""
piece = self.board[old_row][old_col]
target_piece = self.board[new_row][new_col]

# 1. 不能吃自己的棋子
if target_piece and target_piece[0] == piece[0]:
return False

# 2. 获取棋子类型
color, name = piece

# 3. 简化版规则验证
if name == "车":
# 车走直线,路径上不能有障碍
if old_row == new_row: # 横向移动
step = 1 if new_col > old_col else -1
for col in range(old_col + step, new_col, step):
if self.board[old_row][col]:
return False
elif old_col == new_col: # 纵向移动
step = 1 if new_row > old_row else -1
for row in range(old_row + step, new_row, step):
if self.board[row][old_col]:
return False
else:
return False
return True

elif name == "马":
# 马走"日"字,且马脚无子
dx = abs(new_col - old_col)
dy = abs(new_row - old_row)
if (dx == 1 and dy == 2) or (dx == 2 and dy == 1):
# 检查马脚
if dx == 2: # 横向跳
mid_col = (old_col + new_col) // 2
if self.board[old_row][mid_col]:
return False
else: # 纵向跳
mid_row = (old_row + new_row) // 2
if self.board[mid_row][old_col]:
return False
return True
return False

elif name == "炮":
# 炮走直线,吃子时中间必须有一个棋子
if old_row == new_row: # 横向移动
step = 1 if new_col > old_col else -1
count = 0 # 中间棋子计数
for col in range(old_col + step, new_col, step):
if self.board[old_row][col]:
count += 1
elif old_col == new_col: # 纵向移动
step = 1 if new_row > old_row else -1
count = 0
for row in range(old_row + step, new_row, step):
if self.board[row][old_col]:
count += 1
else:
return False

# 炮的规则
if target_piece: # 吃子
return count == 1
else: # 移动
return count == 0

elif name in ("兵", "卒"):
# 兵/卒只能向前或过河后左右移动
if color == "red": # 红方(下方)
if new_row > old_row: # 不能后退
return False
if old_row >= 5: # 未过河
return new_col == old_col and new_row == old_row - 1
else: # 已过河
return (new_col == old_col and new_row == old_row - 1) or \
(new_row == old_row and abs(new_col - old_col) == 1)
else: # 黑方(上方)
if new_row < old_row: # 不能后退
return False
if old_row <= 4: # 未过河
return new_col == old_col and new_row == old_row + 1
else: # 已过河
return (new_col == old_col and new_row == old_row + 1) or \
(new_row == old_row and abs(new_col - old_col) == 1)

elif name in ("士", "士"): # 士的移动规则
# 士只能在九宫格内斜走一格
if color == "red": # 红方(下方)
palace_rows = (7, 8, 9)
palace_cols = (3, 4, 5)
else: # 黑方(上方)
palace_rows = (0, 1, 2)
palace_cols = (3, 4, 5)

# 检查目标位置是否在九宫格内
if new_row not in palace_rows or new_col not in palace_cols:
return False

# 检查是否是斜走一格
return abs(new_row - old_row) == 1 and abs(new_col - old_col) == 1

elif name in ("相", "象"): # 相/象的移动规则
# 相/象走"田"字,且不能过河
dx = abs(new_col - old_col)
dy = abs(new_row - old_row)

if dx == 2 and dy == 2:
# 检查象眼(田字中心)是否有子
mid_row = (old_row + new_row) // 2
mid_col = (old_col + new_col) // 2
if self.board[mid_row][mid_col]:
return False

# 检查是否过河
if color == "red" and new_row < 5: # 红相不能过河
return False
if color == "black" and new_row > 4: # 黑象不能过河
return False

return True
return False

elif name in ("帅", "将"): # 将/帅的移动规则
# 将/帅只能在九宫格内走一格
if color == "red": # 红方(下方)
palace_rows = (7, 8, 9)
palace_cols = (3, 4, 5)
else: # 黑方(上方)
palace_rows = (0, 1, 2)
palace_cols = (3, 4, 5)

# 检查目标位置是否在九宫格内
if new_row not in palace_rows or new_col not in palace_cols:
return False

# 检查是否是走一格(横或竖)
if not ((abs(new_row - old_row) == 1 and new_col == old_col) or \
(abs(new_col - old_col) == 1 and new_row == old_row)):
return False

# 检查移动后是否会导致将帅直接对面
# 临时模拟移动
original_piece = self.board[new_row][new_col]
self.board[new_row][new_col] = self.board[old_row][old_col]
self.board[old_row][old_col] = None

# 检查将帅是否直接对面
kings_face_each_other = self.check_kings_facing()

# 恢复模拟移动
self.board[old_row][old_col] = self.board[new_row][new_col]
self.board[new_row][new_col] = original_piece

# 如果移动会导致将帅直接对面,则不允许
if kings_face_each_other:
return False

return True
return False

def check_kings_facing(self):
"""检查将帅是否直接对面(中间无棋子阻挡)"""
# 查找将和帅的位置
red_king_pos = None
black_king_pos = None

for row in range(10):
for col in range(9):
piece = self.board[row][col]
if piece and piece[1] in ("帅", "将"):
if piece[0] == "red":
red_king_pos = (row, col)
else:
black_king_pos = (row, col)

# 如果有一方的将/帅不在棋盘上(被吃掉了),则不算对面
if not red_king_pos or not black_king_pos:
return False

red_row, red_col = red_king_pos
black_row, black_col = black_king_pos

# 将帅必须在同一列上
if red_col != black_col:
return False

# 检查中间是否有棋子阻挡
for row in range(black_row + 1, red_row):
if self.board[row][red_col]:
return False

return True

def is_check(self):
"""检查当前玩家是否被将军"""
# 找到当前玩家的将/帅位置
king_pos = None
opponent_color = "black" if self.current_player == "red" else "red"

for row in range(10):
for col in range(9):
piece = self.board[row][col]
if piece and piece[0] == self.current_player and piece[1] in ("帅", "将"):
king_pos = (row, col)
break
if king_pos:
break

if not king_pos:
return False # 将/帅已经被吃掉了

# 检查对手的所有棋子是否能攻击将/帅
for row in range(10):
for col in range(9):
piece = self.board[row][col]
if piece and piece[0] == opponent_color:
if self.is_valid_move(row, col, king_pos[0], king_pos[1]):
return True

return False

def is_checkmate(self):
"""检查当前玩家是否被将死"""
if not self.is_check():
return False

# 尝试所有可能的移动,看看是否能解除将军状态
for row in range(10):
for col in range(9):
piece = self.board[row][col]
if piece and piece[0] == self.current_player:
for r in range(10):
for c in range(9):
if self.is_valid_move(row, col, r, c):
# 模拟移动
original_piece = self.board[r][c]
self.board[r][c] = self.board[row][col]
self.board[row][col] = None

# 检查是否仍然被将军
still_in_check = self.is_check()

# 恢复移动
self.board[row][col] = self.board[r][c]
self.board[r][c] = original_piece

if not still_in_check:
return False # 找到一步可以解除将军的走法

return True # 没有找到可以解除将军的走法

class AIPlayer:
def __init__(self, game, color):
self.game = game # 主游戏引用
self.color = color # 'red'或'black'
self.depth = 3 # 搜索深度

def evaluate_board(self):
"""评估当前棋盘分数"""
piece_values = {
'车': 500, '马': 300, '炮': 300,
'帅': 10000, '将': 10000,
'士': 200, '相': 200, '象': 200,
'兵': 100, '卒': 100
}
score = 0
for row in range(10):
for col in range(9):
if self.game.board[row][col]:
color, name = self.game.board[row][col]
value = piece_values.get(name, 0)
score += value if color == self.color else -value
return score

def get_all_moves(self, color):
"""获取当前颜色所有合法移动"""
moves = []
for row in range(10):
for col in range(9):
piece = self.game.board[row][col]
if piece and piece[0] == color:
for r in range(10):
for c in range(9):
if self.game.is_valid_move(row, col, r, c):
moves.append(((row, col), (r, c)))
return moves

def minimax(self, depth, alpha, beta, maximizing_player):
"""Minimax算法实现"""
if depth == 0:
return self.evaluate_board()

if maximizing_player:
max_eval = float('-inf')
for move in self.get_all_moves(self.color):
# 模拟移动
old_row, old_col = move[0]
new_row, new_col = move[1]
captured = self.game.board[new_row][new_col]
moving_piece = self.game.board[old_row][old_col]

self.game.board[new_row][new_col] = moving_piece
self.game.board[old_row][old_col] = None

eval = self.minimax(depth - 1, alpha, beta, False)

# 恢复移动
self.game.board[old_row][old_col] = moving_piece
self.game.board[new_row][new_col] = captured

max_eval = max(max_eval, eval)
alpha = max(alpha, eval)
if beta <= alpha:
break
return max_eval
else:
min_eval = float('inf')
opponent_color = 'black' if self.color == 'red' else 'red'
for move in self.get_all_moves(opponent_color):
# 模拟移动
old_row, old_col = move[0]
new_row, new_col = move[1]
captured = self.game.board[new_row][new_col]
moving_piece = self.game.board[old_row][old_col]

self.game.board[new_row][new_col] = moving_piece
self.game.board[old_row][old_col] = None

eval = self.minimax(depth - 1, alpha, beta, True)

# 恢复移动
self.game.board[old_row][old_col] = moving_piece
self.game.board[new_row][new_col] = captured

min_eval = min(min_eval, eval)
beta = min(beta, eval)
if beta <= alpha:
break
return min_eval

def find_best_move(self):
"""寻找最佳移动"""
best_move = None
max_eval = float('-inf')

for move in self.get_all_moves(self.color):
# 模拟移动
old_row, old_col = move[0]
new_row, new_col = move[1]
captured = self.game.board[new_row][new_col]
moving_piece = self.game.board[old_row][old_col]

self.game.board[new_row][new_col] = moving_piece
self.game.board[old_row][old_col] = None

eval = self.minimax(self.depth - 1, float('-inf'), float('inf'), False)

# 恢复移动
self.game.board[old_row][old_col] = moving_piece
self.game.board[new_row][new_col] = captured

if eval > max_eval:
max_eval = eval
best_move = move

return best_move

def setup_menu(self):
menubar = tk.Menu(self.root)
game_menu = tk.Menu(menubar, tearoff=0)
game_menu.add_command(label="人机对战(红方)", command=lambda: self.set_ai('black'))
game_menu.add_command(label="人机对战(黑方)", command=lambda: self.set_ai('red'))
game_menu.add_command(label="人人对战", command=self.disable_ai)
game_menu.add_command(label="重新开始", command=self.restart_game)
game_menu.add_separator()
game_menu.add_command(label="悔棋", command=self.undo_move) # 新增悔棋菜单项
menubar.add_cascade(label="游戏模式", menu=game_menu)
self.root.config(menu=menubar)

def record_move(self, old_pos, new_pos, captured_piece):
"""记录移动历史"""
self.move_history.append({
'old_pos': old_pos,
'new_pos': new_pos,
'piece': self.board[new_pos[0]][new_pos[1]], # 移动的棋子
'captured': captured_piece # 被吃的子(如果有)
})

def undo_move(self):
"""悔棋功能"""
if not self.move_history or self.game_over:
return

if self.ai_enabled and len(self.move_history) < 2:
# 人机对战需要同时撤销玩家和AI的两步
return

if self.ai_enabled:
# 人机对战模式:一次撤销两步(玩家和AI各一步)
if len(self.move_history) < 2:
return
# 先撤销AI的移动
ai_move = self.move_history.pop()
self.restore_move(ai_move)
# 再撤销玩家的移动
player_move = self.move_history.pop()
self.restore_move(player_move)
else:
# 人人对战模式:一次撤销一步
last_move = self.move_history.pop()
self.restore_move(last_move)

self.draw_board()

def restore_move(self, move_info):
"""恢复棋盘状态到移动前"""
old_row, old_col = move_info['old_pos']
new_row, new_col = move_info['new_pos']

# 恢复移动的棋子
self.board[old_row][old_col] = move_info['piece']
# 恢复被吃的子(如果有)
self.board[new_row][new_col] = move_info['captured']

# 切换回原来的玩家
self.current_player = 'red' if self.current_player == 'black' else 'black'

def set_ai(self, ai_color):
"""设置AI玩家"""
self.ai = self.AIPlayer(self, ai_color)
self.ai_enabled = True
if self.current_player == ai_color:
self.ai_move()

def disable_ai(self):
"""禁用AI"""
self.ai_enabled = False

def restart_game(self):
"""重新开始游戏"""
self.board = [[None for _ in range(9)] for _ in range(10)]
self.init_board()
self.selected_piece = None
self.current_player = "red"
self.game_over = False
self.draw_board()
if self.ai_enabled and self.ai.color == "red":
self.ai_move()




if __name__ == "__main__":
root = tk.Tk()
game = ChineseChess(root)
root.mainloop()

 

(七)参考资料

《Python游戏编程入门》

《游戏编程算法与技巧》

《人工智能:一种现代方法》

《棋类游戏AI开发实战》

《象棋残局大全》

《计算机博弈理论与技术》

《算法竞赛入门经典》

 

(八)课程总结与感想

这个学期有幸选到王老师的Python课,现在回想起来,这段学习经历实在难能可贵。王老师不仅教学功底深厚,而且平易近人、风趣幽默,总能用形象生动的比喻把抽象的概念讲得明明白白。虽然是一门面向初学者的通识课,但王老师的课程设计让我获益良多,可以说是我大学期间上过的公选课里最值得安利的一门。

在课程学习中,我从完全不懂编程的小白起步,慢慢掌握了Python的基础语法、函数运用以及简单的文件处理等知识。虽然课程定位是入门级别,但教学进度安排科学合理,既照顾到了零基础的同学,也让我这样的新手能够循序渐进地进步。特别值得一提的是,王老师经常结合生活实例来讲解,让我们明白编程不只是写代码,更是一种解决问题的思维方式。

通过这门课程,我不仅学会了Python的基本操作,更重要的是培养了对编程的兴趣和自信。相信这些知识和思维方法对我今后学习其他编程语言也会有很大的帮助。虽然课程已经结束,但课堂上学到的东西将会一直影响我未来的学习道路。

最后,要衷心感谢王老师的悉心教导。这门课让我真切感受到了学习的快乐和编程的魔力。以后如果有机会,我一定会继续钻研Python;同时也会积极向学弟学妹推荐这门课,希望他们也能从中收获成长。再次感谢王老师的谆谆教诲,衷心谢谢您!🥰🥰🥰

 

然后,作为面向非计算机专业开设的公选课,我认为还可以从以下几个方面进行优化:

1.拓展应用案例展示:建议增加Python在数据分析、办公自动化、机器学习等热门领域的应用实例,让同学们更直观地感受到编程的实际价值,从而提升学习动力。

2.促进学习交流互动:可以考虑设置小组讨论环节或建立线上交流平台。有时候老师讲解后可能还存在理解盲区,同学间的互助讨论往往能带来意想不到的启发。

3.教学感悟:

编程并非高不可攀的技能,只要勇于实践、不怕犯错,人人都能掌握基础编程能力

Python作为入门语言特别友好,是培养计算思维的理想选择

即便未来不从事IT行业,编程思维对提升逻辑能力和信息处理能力都大有裨益

4.致谢:特别感谢王老师一直以来的悉心指导,也要感谢课代表在课后提供的帮助。这门课最大的收获不仅是学会了Python,更重要的是培养了主动思考的习惯。我会继续向学弟学妹们推荐这门精品课程,让更多人受益。