用python实现中国象棋

一.象棋规则

象棋是二人对弈的棋类游戏,棋盘由 9 条竖线和 10 条横线交叉构成,中间 “河界” 分楚汉,两端 “九宫” 各 9 个交叉点。棋子分红黑,各 16 枚,含 7 兵种。

1.棋子走法

1.1 红方棋子

  • :1 个,是红方的核心棋子,只能在九宫之内活动,可上可下,可左可右,每次走动只能按竖线或横线走动一格。
  • :2 个,是帅的贴身保镖,只能在九宫内走动,行棋路径只能是九宫内的斜线。
  • :2 个,每次循对角线走两格,俗称 “相飞田”。
  • :2 个,无论横线、竖线均可行走,只要无子阻拦,步数不受限制。
  • :2 个,走 “日” 字,每步走一直一斜,具有很高的灵活性和攻击性。
  • :2 个,行动迅速而易于成势,需要借助其他棋子的力量进行攻击,有击必应。
  • :5 个,只能向前走,第一步只能走一格,以后每步可以走一格或两格,但未过河前不能左右移动,过河后可以左右移动。

1.2 黑方棋子

  • :1 个,作用与红方的帅相同,是黑方的核心棋子,只能在九宫格内活动,每次只能横竖移动一格。
  • :2 个,作用与红方的仕相同,负责在九宫格内保护将,走的是斜线,每次只能斜着走一格。
  • :2 个,走法与红方的相相同,每次循对角线走两格,俗称 “象飞田”。
  • :2 个,走法与红方的车相同,无论横线、竖线均可行走,只要无子阻拦,步数不受限制。
  • :2 个,走法与红方的马相同,走 “日” 字,每步走一直一斜。
  • :2 个,走法与红方的炮相同,行动迅速而易于成势,需要借助其他棋子的力量进行攻击,有击必应。
  • :5 个,走法与红方的兵相同,只能向前走,第一步只能走一格,以后每步可以走一格或两格,但未过河前不能左右移动,过河后可以左右移动。

2.吃子与胜负

  1. 吃子:走到对方棋子位置,将其从棋盘移除。
  2. 胜负:将死对方 “将(帅)” 或对方认输则胜;双方均无能力将死对方,判和棋。

二.详细分析

每个棋子按照上述规则在棋盘上移动、吃子,双方通过合理运用棋子的走法,以将死对方的将(帅)为目标,最终决出胜负。

若一个棋子,他只能在这米字格里横竖方向的移动,便是象棋当中将(帅)的走法;

只能在米字格中沿斜线行走的话,就是士;

而可以横竖方向,无论距离的走,便是车;

若与车的行走完全一致,但必须跳过一颗棋子进行吃子的是炮(砲);

当两块格子组成"日"字,只能走其对角线,这就是马;

若需走四个格子对角线的话,这样跳过"田"字的是象,注意只能在己方阵营行动;

一颗只能向前移动在己方阵营,过届之后才能能左右行走且无法向后回头的是兵(卒)

抽象为计算机模型:

用二维列表表示棋盘,每个元素代表棋盘上的一个位置。

定义棋子类,每个棋子对象有其颜色、类型等属性,以及移动合法性判断方法。

实现棋盘初始化、棋子移动、吃子、判断胜负等功能。

三.用python 实现象棋

1.初始构建棋盘

用二维列表表示棋盘,每个元素代表棋盘上的一个位置。

def create_chessboard():
    # 创建一个10x9的二维列表,初始值为None,代表空位置
    chessboard = [[None] * 9 for _ in range(10)]
    return chessboard

2.定义各类棋子和属性(同类区分双方部分名称)

定义棋子类,每个棋子对象有其颜色、类型等属性,以及移动合法性判断方法。

class Piece:
    def __init__(self, color, kind):
        # 棋子颜色,如'红'或'黑'
        self.color = color
        # 棋子类型,如'将'、'车'等
        self.kind = kind

    def is_move_valid(self, start, end, board):
        # 该方法需在子类中具体实现,用于判断棋子从start到end的移动是否合法
        pass


class King(Piece):
    def is_move_valid(self, start, end, board):
        x1, y1 = start
        x2, y2 = end
        # 判断将(帅)是否在九宫格内
        if self.color == '红':
            if not (3 <= x1 <= 5 and 7 <= y1 <= 9):
                return False
        else:
            if not (3 <= x1 <= 5 and 0 <= y1 <= 2):
                return False
        # 判断是否沿横竖方向移动一格
        return abs(x1 - x2) + abs(y1 - y2) == 1


class Advisor(Piece):
    def is_move_valid(self, start, end, board):
        x1, y1 = start
        x2, y2 = end
        # 判断士是否在九宫格内
        if self.color == '红':
            if not (3 <= x1 <= 5 and 7 <= y1 <= 9):
                return False
        else:
            if not (3 <= x1 <= 5 and 0 <= y1 <= 2):
                return False
        # 判断是否沿斜线移动一格
        return abs(x1 - x2) == 1 and abs(y1 - y2) == 1


class Elephant(Piece):
    def is_move_valid(self, start, end, board):
        x1, y1 = start
        x2, y2 = end
        # 判断象是否过河
        if (self.color == '红' and y2 < 5) or (self.color == '黑' and y2 > 4):
            return False
        # 判断是否走“田”字对角且“田”字中心无棋子(不塞象眼)
        if abs(x1 - x2) == 2 and abs(y1 - y2) == 2:
            mid_x = (x1 + x2) // 2
            mid_y = (y1 + y2) // 2
            return board[mid_y][mid_x] is None
        return False


class Horse(Piece):
    def is_move_valid(self, start, end, board):
        x1, y1 = start
        x2, y2 = end
        dx = abs(x1 - x2)
        dy = abs(y1 - y2)
        # 判断是否走“日”字对角且不蹩马腿
        if (dx == 2 and dy == 1) or (dx == 1 and dy == 2):
            block_x = x1 if dx == 2 else (x1 + x2) // 2
            block_y = y1 if dy == 2 else (y1 + y2) // 2
            return board[block_y][block_x] is None
        return False


class Chariot(Piece):
    def is_move_valid(self, start, end, board):
        x1, y1 = start
        x2, y2 = end
        # 判断是否在横竖方向移动且路径无阻挡
        if x1 == x2:
            for y in range(min(y1, y2) + 1, max(y1, y2)):
                if board[y][x1] is not None:
                    return False
        elif y1 == y2:
            for x in range(min(x1, x2) + 1, max(x1, x2)):
                if board[y1][x] is not None:
                    return False
        else:
            return False
        return True


class Cannon(Piece):
    def is_move_valid(self, start, end, board):
        x1, y1 = start
        x2, y2 = end
        # 判断移动路径是否为空或有且仅有一个炮台
        if x1 == x2:
            count = 0
            for y in range(min(y1, y2) + 1, max(y1, y2)):
                if board[y][x1] is not None:
                    count += 1
            if (end[1] == start[1] and count == 0) or (end[1]!= start[1] and count == 1):
                return True
        elif y1 == y2:
            count = 0
            for x in range(min(x1, x2) + 1, max(x1, x2)):
                if board[y1][x] is not None:
                    count += 1
            if (end[0] == start[0] and count == 0) or (end[0]!= start[0] and count == 1):
                return True
        return False


class Soldier(Piece):
    def is_move_valid(self, start, end, board):
        x1, y1 = start
        x2, y2 = end
        # 判断兵(卒)是否符合移动规则
        if self.color == '红':
            if y1 < 5:
                if y2!= y1 + 1 or x2!= x1:
                    return False
            else:
                if y2!= y1 + 1 and x2 not in [x1 - 1, x1 + 1]:
                    return False
        else:
            if y1 > 4:
                if y2!= y1 - 1 or x2!= x1:
                    return False
            else:
                if y2!= y1 - 1 and x2 not in [x1 - 1, x1 + 1]:
                    return False
        return True

3.构建获胜条件,判断胜负功能等

实现棋盘初始化、棋子移动、吃子、判断胜负等功能。

class ChessGame:
    def __init__(self):
        self.board = create_chessboard()
        self.init_pieces()

    def init_pieces(self):
        # 红方棋子初始化
        self.board[9][0] = Chariot('红', '车')
        self.board[9][1] = Horse('红', '马')
        self.board[9][2] = Elephant('红', '象')
        self.board[9][3] = Advisor('红', '士')
        self.board[9][4] = King('红', '将')
        self.board[9][5] = Advisor('红', '士')
        self.board[9][6] = Elephant('红', '象')
        self.board[9][7] = Horse('红', '马')
        self.board[9][8] = Chariot('红', '车')
        self.board[7][1] = Cannon('红', '炮')
        self.board[7][7] = Cannon('红', '炮')
        for i in range(0, 9, 2):
            self.board[6][i] = Soldier('红', '兵')

        # 黑方棋子初始化
        self.board[0][0] = Chariot('黑', '车')
        self.board[0][1] = Horse('黑', '马')
        self.board[0][2] = Elephant('黑', '象')
        self.board[0][3] = Advisor('黑', '士')
        self.board[0][4] = King('黑', '帅')
        self.board[0][5] = Advisor('黑', '士')
        self.board[0][6] = Elephant('黑', '象')
        self.board[0][7] = Horse('黑', '马')
        self.board[0][8] = Chariot('黑', '车')
        self.board[2][1] = Cannon('黑', '炮')
        self.board[2][7] = Cannon('黑', '炮')
        for i in range(0, 9, 2):
            self.board[3][i] = Soldier('黑', '卒')

    def move_piece(self, start, end):
        # 检查起始和目标位置是否在棋盘内
        if 0 <= start[0] < 10 and 0 <= start[1] < 9 and 0 <= end[0] < 10 and 0 <= end[1] < 9:
            piece = self.board[start[0]][start[1]]
            if piece is not None:
                if piece.is_move_valid(start, end, self.board):
                    if self.board[end[0]][end[1]] is not None and self.board[end[0]][end[1]].color!= piece.color:
                        # 吃子
                        self.board[end[0]][end[1]] = None
                    self.board[end[0]][end[1]] = self.board[start[0]][start[1]]
                    self.board[start[0]][start[1]] = None
                    return True
        return False

    def is_checkmate(self, color):
        king_pos = None
        # 找到将(帅)的位置
        for i in range(10):
            for j in range(9):
                if self.board[i][j] is not None and self.board[i][j].color == color and self.board[i][j].kind in ['将', '帅']:
                    king_pos = (i, j)
        if king_pos is None:
            return False
        # 检查是否有对方棋子能吃掉将(帅)
        for i in range(10):
            for j in range(9):
                if self.board[i][j] is not None and self.board[i][j].color!= color:
                    if self.board[i][j].is_move_valid((i, j), king_pos, self.board):
                        return True
        return False

4.测试运行

# 测试代码
game = ChessGame()
# 尝试移动红方车
game.move_piece((9, 0), (7, 0))
print(game.is_checkmate('黑'))

5.整体代码及测试

5.1 整体代码

def create_chessboard():
    """创建一个10x9的二维列表,初始值为None,代表空位置。
    :return: 表示棋盘的二维列表
    """
    return [[None] * 9 for _ in range(10)]


class Piece:
    """定义棋子的基类,包含颜色和类型属性,以及一个抽象方法用于判断移动是否合法。
    Attributes:
        color (str): 棋子颜色,如'红'或'黑'。
        kind (str): 棋子类型,如'将'、'车'等。
    """
    def __init__(self, color, kind):
        self.color = color
        self.kind = kind

    def is_move_valid(self, start, end, board):
        """判断棋子从start到end的移动是否合法。
        此方法为抽象方法,需在子类中具体实现。
        :param start: 起始位置,格式为(x, y)的元组。
        :param end: 目标位置,格式为(x, y)的元组。
        :param board: 棋盘,二维列表。
        :return: bool,移动是否合法。
        """
        pass


class King(Piece):
    def is_move_valid(self, start, end, board):
        """帅(将)的移动规则:只能在九宫格内活动,每次沿横竖方向移动一格。
        :param start: 起始位置,格式为(x, y)的元组。
        :param end: 目标位置,格式为(x, y)的元组。
        :param board: 棋盘,二维列表。
        :return: bool,移动是否合法。
        """
        x1, y1 = start
        x2, y2 = end
        if self.color == '红':
            if not (3 <= x1 <= 5 and 7 <= y1 <= 9):
                return False
        else:
            if not (3 <= x1 <= 5 and 0 <= y1 <= 2):
                return False
        return abs(x1 - x2) + abs(y1 - y2) == 1


class Advisor(Piece):
    def is_move_valid(self, start, end, board):
        """仕(士)的移动规则:只能在九宫内走动,行棋路径只能是九宫内的斜线。
        :param start: 起始位置,格式为(x, y)的元组。
        :param end: 目标位置,格式为(x, y)的元组。
        :param board: 棋盘,二维列表。
        :return: bool,移动是否合法。
        """
        x1, y1 = start
        x2, y2 = end
        if self.color == '红':
            if not (3 <= x1 <= 5 and 7 <= y1 <= 9):
                return False
        else:
            if not (3 <= x1 <= 5 and 0 <= y1 <= 2):
                return False
        return abs(x1 - x2) == 1 and abs(y1 - y2) == 1


class Elephant(Piece):
    def is_move_valid(self, start, end, board):
        """相(象)的移动规则:循对角线走两格,俗称“相飞田”,不能过河。
        :param start: 起始位置,格式为(x, y)的元组。
        :param end: 目标位置,格式为(x, y)的元组。
        :param board: 棋盘,二维列表。
        :return: bool,移动是否合法。
        """
        x1, y1 = start
        x2, y2 = end
        if (self.color == '红' and y2 < 5) or (self.color == '黑' and y2 > 4):
            return False
        if abs(x1 - x2) == 2 and abs(y1 - y2) == 2:
            mid_x = (x1 + x2) // 2
            mid_y = (y1 + y2) // 2
            return board[mid_y][mid_x] is None
        return False


class Horse(Piece):
    def is_move_valid(self, start, end, board):
        """马的移动规则:走“日”字,每步走一直一斜,注意“蹩马腿”。
        :param start: 起始位置,格式为(x, y)的元组。
        :param end: 目标位置,格式为(x, y)的元组。
        :param board: 棋盘,二维列表。
        :return: bool,移动是否合法。
        """
        x1, y1 = start
        x2, y2 = end
        dx = abs(x1 - x2)
        dy = abs(y1 - y2)
        if (dx == 2 and dy == 1) or (dx == 1 and dy == 2):
            block_x = x1 if dx == 2 else (x1 + x2) // 2
            block_y = y1 if dy == 2 else (y1 + y2) // 2
            return board[block_y][block_x] is None
        return False


class Chariot(Piece):
    def is_move_valid(self, start, end, board):
        """车的移动规则:无论横线、竖线均可行走,只要无子阻拦,步数不受限制。
        :param start: 起始位置,格式为(x, y)的元组。
        :param end: 目标位置,格式为(x, y)的元组。
        :param board: 棋盘,二维列表。
        :return: bool,移动是否合法。
        """
        x1, y1 = start
        x2, y2 = end
        if x1 == x2:
            for y in range(min(y1, y2) + 1, max(y1, y2)):
                if board[y][x1] is not None:
                    return False
        elif y1 == y2:
            for x in range(min(x1, x2) + 1, max(x1, x2)):
                if board[y1][x] is not None:
                    return False
        else:
            return False
        return True


class Cannon(Piece):
    def is_move_valid(self, start, end, board):
        """炮的移动规则:移动方式与车相同,吃子时需借助一个棋子作为炮台。
        :param start: 起始位置,格式为(x, y)的元组。
        :param end: 目标位置,格式为(x, y)的元组。
        :param board: 棋盘,二维列表。
        :return: bool,移动是否合法。
        """
        x1, y1 = start
        x2, y2 = end
        if x1 == x2:
            count = 0
            for y in range(min(y1, y2) + 1, max(y1, y2)):
                if board[y][x1] is not None:
                    count += 1
            if (end[1] == start[1] and count == 0) or (end[1]!= start[1] and count == 1):
                return True
        elif y1 == y2:
            count = 0
            for x in range(min(x1, x2) + 1, max(x1, x2)):
                if board[y1][x] is not None:
                    count += 1
            if (end[0] == start[0] and count == 0) or (end[0]!= start[0] and count == 1):
                return True
        return False


class Soldier(Piece):
    def is_move_valid(self, start, end, board):
        """兵(卒)的移动规则:未过河时只能向前移动一格,过河后可向前或横向移动一格。
        :param start: 起始位置,格式为(x, y)的元组。
        :param end: 目标位置,格式为(x, y)的元组。
        :param board: 棋盘,二维列表。
        :return: bool,移动是否合法。
        """
        x1, y1 = start
        x2, y2 = end
        if self.color == '红':
            if y1 < 5:
                if y2!= y1 + 1 or x2!= x1:
                    return False
            else:
                if y2 not in [y1 - 1, y1 + 1] or (y2 == y1 and x2 not in [x1 - 1, x1 + 1]):
                    return False
        else:
            if y1 > 4:
                if y2!= y1 - 1 or x2!= x1:
                    return False
            else:
                if y2 not in [y1 - 1, y1 + 1] or (y2 == y1 and x2 not in [x1 - 1, x1 + 1]):
                    return False
        return True


class ChessGame:
    def __init__(self):
        """初始化棋盘和棋子。"""
        self.board = create_chessboard()
        self.init_pieces()

    def init_pieces(self):
        """初始化棋盘上的棋子。"""
        # 红方棋子初始化
        self.board[9][0] = Chariot('红', '车')
        self.board[9][1] = Horse('红', '马')
        self.board[9][2] = Elephant('红', '象')
        self.board[9][3] = Advisor('红', '士')
        self.board[9][4] = King('红', '将')
        self.board[9][5] = Advisor('红', '士')
        self.board[9][6] = Elephant('红', '象')
        self.board[9][7] = Horse('红', '马')
        self.board[9][8] = Chariot('红', '车')
        self.board[7][1] = Cannon('红', '炮')
        self.board[7][7] = Cannon('红', '炮')
        for i in range(0, 9, 2):
            self.board[6][i] = Soldier('红', '兵')

        # 黑方棋子初始化
        self.board[0][0] = Chariot('黑', '车')
        self.board[0][1] = Horse('黑', '马')
        self.board[0][2] = Elephant('黑', '象')
        self.board[0][3] = Advisor('黑', '士')
        self.board[0][4] = King('黑', '帅')
        self.board[0][5] = Advisor('黑', '士')
        self.board[0][6] = Elephant('黑', '象')
        self.board[0][7] = Horse('黑', '马')
        self.board[0][8] = Chariot('黑', '车')
        self.board[2][1] = Cannon('黑', '炮')
        self.board[2][7] = Cannon('黑', '炮')
        for i in range(0, 9, 2):
            self.board[3][i] = Soldier('黑', '卒')

    def move_piece(self, start, end):
        """移动棋子从start位置到end位置。
        :param start: 起始位置,格式为(x, y)的元组。
        :param end: 目标位置,格式为(x, y)的元组。
        :return: bool,移动是否成功。
        """
        # 检查起始和目标位置是否在棋盘内
        if 0 <= start[0] < 10 and 0 <= start[1] < 9 and 0 <= end[0] < 10 and 0 <= end[1] < 9:
            piece = self.board[start[0]][start[1]]
            if piece is not None:
                if piece.is_move_valid(start, end, self.board):
                    if self.board[end[0]][end[1]] is not None and self.board[end[0]][end[1]].color!= piece.color:
                        # 吃子
                        self.board[end[0]][end[1]] = None
                    self.board[end[0]][end[1]] = self.board[start[0]][start[1]]
                    self.board[start[0]][start[1]] = None
                    return True
        return False

    def is_checkmate(self, color):
        """判断指定颜色的棋子是否被将死。
        :param color: 棋子颜色,如'红'或'黑'。
        :return: bool,是否被将死。
        """
        king_pos = None
        # 找到将(帅)的位置
        for i in range(10):
            for j in range(9):
                if self.board[i][j] is not None and self.board[i][j].color == color and self.board[i][j].kind in ['将', '帅']:
                    king_pos = (i, j)
        if king_pos is None:
            return False
        # 检查是否有对方棋子能吃掉将(帅)
        for i in range(10):
            for j in range(9):
                if self.board[i][j] is not None and self.board[i][j].color!= color:
                    if self.board[i][j].is_move_valid((i, j), king_pos, self.board):
                        return True
        return False
def create_chessboard():
    """创建10x9的二维列表表示棋盘,初始值为None代表空位置。"""
    return [[None] * 9 for _ in range(10)]


class Piece:
    """棋子基类,包含颜色和类型属性,及移动合法性判断抽象方法。"""
    def __init__(self, color, kind):
        self.color = color
        self.kind = kind

    def is_move_valid(self, start, end, board):
        """判断棋子从start到end移动是否合法,需子类实现。"""
        pass


class King(Piece):
    def is_move_valid(self, start, end, board):
        """帅(将):只能在九宫格内沿横竖方向移动一格。"""
        x1, y1 = start
        x2, y2 = end
        if self.color == '红':
            if not (3 <= x1 <= 5 and 7 <= y1 <= 9):
                return False
        else:
            if not (3 <= x1 <= 5 and 0 <= y1 <= 2):
                return False
        return abs(x1 - x2) + abs(y1 - y2) == 1


class Advisor(Piece):
    def is_move_valid(self, start, end, board):
        """仕(士):只能在九宫内沿斜线移动一格。"""
        x1, y1 = start
        x2, y2 = end
        if self.color == '红':
            if not (3 <= x1 <= 5 and 7 <= y1 <= 9):
                return False
        else:
            if not (3 <= x1 <= 5 and 0 <= y1 <= 2):
                return False
        return abs(x1 - x2) == 1 and abs(y1 - y2) == 1


class Elephant(Piece):
    def is_move_valid(self, start, end, board):
        """相(象):循对角线走两格(相飞田),不能过河,塞象眼则不能走。"""
        x1, y1 = start
        x2, y2 = end
        if (self.color == '红' and y2 < 5) or (self.color == '黑' and y2 > 4):
            return False
        if abs(x1 - x2) == 2 and abs(y1 - y2) == 2:
            mid_x = (x1 + x2) // 2
            mid_y = (y1 + y2) // 2
            return board[mid_y][mid_x] is None
        return False


class Horse(Piece):
    def is_move_valid(self, start, end, board):
        """马:走“日”字,蹩马腿则不能走。"""
        x1, y1 = start
        x2, y2 = end
        dx = abs(x1 - x2)
        dy = abs(y1 - y2)
        if (dx == 2 and dy == 1) or (dx == 1 and dy == 2):
            block_x = x1 if dx == 2 else (x1 + x2) // 2
            block_y = y1 if dy == 2 else (y1 + y2) // 2
            return board[block_y][block_x] is None
        return False


class Chariot(Piece):
    def is_move_valid(self, start, end, board):
        """车:可在横竖方向不限格数移动,路径无阻挡。"""
        x1, y1 = start
        x2, y2 = end
        if x1 == x2:
            for y in range(min(y1, y2) + 1, max(y1, y2)):
                if board[y][x1] is not None:
                    return False
        elif y1 == y2:
            for x in range(min(x1, x2) + 1, max(x1, x2)):
                if board[y1][x] is not None:
                    return False
        else:
            return False
        return True


class Cannon(Piece):
    def is_move_valid(self, start, end, board):
        """炮:移动同车,吃子时需借助炮台。"""
        x1, y1 = start
        x2, y2 = end
        if x1 == x2:
            count = 0
            for y in range(min(y1, y2) + 1, max(y1, y2)):
                if board[y][x1] is not None:
                    count += 1
            if (end[1] == start[1] and count == 0) or (end[1]!= start[1] and count == 1):
                return True
        elif y1 == y2:
            count = 0
            for x in range(min(x1, x2) + 1, max(x1, x2)):
                if board[y1][x] is not None:
                    count += 1
            if (end[0] == start[0] and count == 0) or (end[0]!= start[0] and count == 1):
                return True
        return False


class Soldier(Piece):
    def is_move_valid(self, start, end, board):
        """兵(卒):未过河前直走一格,过河后可直走或横走一格。"""
        x1, y1 = start
        x2, y2 = end
        if self.color == '红':
            if y1 < 5:
                if y2!= y1 + 1 or x2!= x1:
                    return False
            else:
                if y2 not in [y1 - 1, y1 + 1] or (y2 == y1 and x2 not in [x1 - 1, x1 + 1]):
                    return False
        else:
            if y1 > 4:
                if y2!= y1 - 1 or x2!= x1:
                    return False
            else:
                if y2 not in [y1 - 1, y1 + 1] or (y2 == y1 and x2 not in [x1 - 1, x1 + 1]):
                    return False
        return True


class ChessGame:
    def __init__(self):
        """初始化棋盘和棋子。"""
        self.board = create_chessboard()
        self.init_pieces()

    def init_pieces(self):
        """初始化棋盘上红黑双方棋子。"""
        # 红方棋子初始化
        self.board[9][0] = Chariot('红', '车')
        self.board[9][1] = Horse('红', '马')
        self.board[9][2] = Elephant('红', '象')
        self.board[9][3] = Advisor('红', '士')
        self.board[9][4] = King('红', '将')
        self.board[9][5] = Advisor('红', '士')
        self.board[9][6] = Elephant('红', '象')
        self.board[9][7] = Horse('红', '马')
        self.board[9][8] = Chariot('红', '车')
        self.board[7][1] = Cannon('红', '炮')
        self.board[7][7] = Cannon('红', '炮')
        for i in range(0, 9, 2):
            self.board[6][i] = Soldier('红', '兵')

        # 黑方棋子初始化
        self.board[0][0] = Chariot('黑', '车')
        self.board[0][1] = Horse('黑', '马')
        self.board[0][2] = Elephant('黑', '象')
        self.board[0][3] = Advisor('黑', '士')
        self.board[0][4] = King('黑', '帅')
        self.board[0][5] = Advisor('黑', '士')
        self.board[0][6] = Elephant('黑', '象')
        self.board[0][7] = Horse('黑', '马')
        self.board[0][8] = Chariot('黑', '车')
        self.board[2][1] = Cannon('黑', '炮')
        self.board[2][7] = Cannon('黑', '炮')
        for i in range(0, 9, 2):
            self.board[3][i] = Soldier('黑', '卒')

    def move_piece(self, start, end):
        """移动棋子,检查合法性并执行,吃子时移除对方棋子。"""
        if 0 <= start[0] < 10 and 0 <= start[1] < 9 and 0 <= end[0] < 10 and 0 <= end[1] < 9:
            piece = self.board[start[0]][start[1]]
            if piece is not None:
                if piece.is_move_valid(start, end, self.board):
                    if self.board[end[0]][end[1]] is not None and self.board[end[0]][end[1]].color!= piece.color:
                        self.board[end[0]][end[1]] = None
                    self.board[end[0]][end[1]] = self.board[start[0]][start[1]]
                    self.board[start[0]][start[1]] = None
                    return True
        return False

    def is_checkmate(self, color):
        """判断指定颜色的将(帅)是否被将死。"""
        king_pos = None
        for i in range(10):
            for j in range(9):
                if self.board[i][j] is not None and self.board[i][j].color == color and self.board[i][j].kind in ['将', '帅']:
                    king_pos = (i, j)
        if king_pos is None:
            return False
        for i in range(10):
            for j in range(9):
                if self.board[i][j] is not None and self.board[i][j].color!= color:
                    if self.board[i][j].is_move_valid((i, j), king_pos, self.board):
                        return True
        return False
  1. 类和函数备注:简化了 docstring,突出关键信息,去除重复和冗长描述。例如,类的 docstring 只保留核心功能说明,函数 docstring 强调功能要点。
  2. 规则描述:在棋子移动合法性判断函数的备注中,简洁地概括了棋子移动规则,避免复杂表述。
优化代码
'''
代码结构优化:将棋子的初始化部分提取到一个独立的函数中,使__init__方法更简洁。同时,将棋盘的大小定义为常量,方便修改和维护。
代码逻辑优化:在is_move_valid方法中,对一些条件判断进行了合并和简化,提高代码的可读性。对于Cannon类的移动判断,逻辑更加清晰。
代码风格优化:遵循 Python 的命名规范,使用更具描述性的变量名,并适当添加注释以提高代码的可理解性。
'''

# 定义棋盘的行数和列数
BOARD_ROWS = 10
BOARD_COLS = 9

def create_chessboard():
    """创建10x9的二维列表表示棋盘,初始值为None代表空位置。"""
    return [[None] * BOARD_COLS for _ in range(BOARD_ROWS)]

class Piece:
    """棋子基类,包含颜色和类型属性,及移动合法性判断抽象方法。"""
    def __init__(self, color, kind):
        self.color = color
        self.kind = kind

    def is_move_valid(self, start, end, board):
        """判断棋子从start到end移动是否合法,需子类实现。"""
        pass

class King(Piece):
    def is_move_valid(self, start, end, board):
        """帅(将):只能在九宫格内沿横竖方向移动一格。"""
        x1, y1 = start
        x2, y2 = end
        # 九宫格范围判断
        if (self.color == '红' and (x1 < 3 or x1 > 5 or y1 < 7 or y1 > 9)) or \
                (self.color == '黑' and (x1 < 3 or x1 > 5 or y1 < 0 or y1 > 2)):
            return False
        return abs(x1 - x2) + abs(y1 - y2) == 1

class Advisor(Piece):
    def is_move_valid(self, start, end, board):
        """仕(士):只能在九宫内沿斜线移动一格。"""
        x1, y1 = start
        x2, y2 = end
        # 九宫格范围判断
        if (self.color == '红' and (x1 < 3 or x1 > 5 or y1 < 7 or y1 > 9)) or \
                (self.color == '黑' and (x1 < 3 or x1 > 5 or y1 < 0 or y1 > 2)):
            return False
        return abs(x1 - x2) == 1 and abs(y1 - y2) == 1

class Elephant(Piece):
    def is_move_valid(self, start, end, board):
        """相(象):循对角线走两格(相飞田),不能过河,塞象眼则不能走。"""
        x1, y1 = start
        x2, y2 = end
        # 不能过河判断
        if (self.color == '红' and y2 < 5) or (self.color == '黑' and y2 > 4):
            return False
        if abs(x1 - x2) == 2 and abs(y1 - y2) == 2:
            mid_x = (x1 + x2) // 2
            mid_y = (y1 + y2) // 2
            return board[mid_y][mid_x] is None
        return False

class Horse(Piece):
    def is_move_valid(self, start, end, board):
        """马:走“日”字,蹩马腿则不能走。"""
        x1, y1 = start
        x2, y2 = end
        dx = abs(x1 - x2)
        dy = abs(y1 - y2)
        if (dx == 2 and dy == 1) or (dx == 1 and dy == 2):
            block_x = x1 if dx == 2 else (x1 + x2) // 2
            block_y = y1 if dy == 2 else (y1 + y2) // 2
            return board[block_y][block_x] is None
        return False

class Chariot(Piece):
    def is_move_valid(self, start, end, board):
        """车:可在横竖方向不限格数移动,路径无阻挡。"""
        x1, y1 = start
        x2, y2 = end
        if x1 == x2:
            for y in range(min(y1, y2) + 1, max(y1, y2)):
                if board[y][x1] is not None:
                    return False
        elif y1 == y2:
            for x in range(min(x1, x2) + 1, max(x1, x2)):
                if board[y1][x] is not None:
                    return False
        else:
            return False
        return True

class Cannon(Piece):
    def is_move_valid(self, start, end, board):
        """炮:移动同车,吃子时需借助炮台。"""
        x1, y1 = start
        x2, y2 = end
        if x1 == x2:
            pieces_between = sum(board[y][x1] is not None for y in range(min(y1, y2) + 1, max(y1, y2)))
            if (x2 == x1 and pieces_between == 0) or (x2!= x1 and pieces_between == 1):
                return True
        elif y1 == y2:
            pieces_between = sum(board[y1][x] is not None for x in range(min(x1, x2) + 1, max(x1, x2)))
            if (y2 == y1 and pieces_between == 0) or (y2!= y1 and pieces_between == 1):
                return True
        return False

class Soldier(Piece):
    def is_move_valid(self, start, end, board):
        """兵(卒):未过河前直走一格,过河后可直走或横走一格。"""
        x1, y1 = start
        x2, y2 = end
        if self.color == '红':
            if y1 < 5:
                return y2 == y1 + 1 and x2 == x1
            else:
                return (y2 == y1 + 1 or y2 == y1) and x2 in [x1 - 1, x1 + 1, x1]
        else:
            if y1 > 4:
                return y2 == y1 - 1 and x2 == x1
            else:
                return (y2 == y1 - 1 or y2 == y1) and x2 in [x1 - 1, x1 + 1, x1]

class ChessGame:
    def __init__(self):
        """初始化棋盘和棋子。"""
        self.board = create_chessboard()
        self.init_pieces()

    def init_pieces(self):
        """初始化棋盘上红黑双方棋子。"""
        red_pieces = [
            (Chariot, '车', 9, 0), (Horse, '马', 9, 1), (Elephant, '象', 9, 2), (Advisor, '士', 9, 3), (King, '将', 9, 4),
            (Advisor, '士', 9, 5), (Elephant, '象', 9, 6), (Horse, '马', 9, 7), (Chariot, '车', 9, 8),
            (Cannon, '炮', 7, 1), (Cannon, '炮', 7, 7)
        ]
        for piece_class, kind, row, col in red_pieces:
            self.board[row][col] = piece_class('红', kind)
        for i in range(0, BOARD_COLS, 2):
            self.board[6][i] = Soldier('红', '兵')

        black_pieces = [
            (Chariot, '车', 0, 0), (Horse, '马', 0, 1), (Elephant, '象', 0, 2), (Advisor, '士', 0, 3), (King, '帅', 0, 4),
            (Advisor, '士', 0, 5), (Elephant, '象', 0, 6), (Horse, '马', 0, 7), (Chariot, '车', 0, 8),
            (Cannon, '炮', 2, 1), (Cannon, '炮', 2, 7)
        ]
        for piece_class, kind, row, col in black_pieces:
            self.board[row][col] = piece_class('黑', kind)
        for i in range(0, BOARD_COLS, 2):
            self.board[3][i] = Soldier('黑', '卒')

    def move_piece(self, start, end):
        """移动棋子,检查合法性并执行,吃子时移除对方棋子。"""
        if 0 <= start[0] < BOARD_ROWS and 0 <= start[1] < BOARD_COLS and \
                0 <= end[0] < BOARD_ROWS and 0 <= end[1] < BOARD_COLS:
            piece = self.board[start[0]][start[1]]
            if piece is not None:
                if piece.is_move_valid(start, end, self.board):
                    if self.board[end[0]][end[1]] is not None and self.board[end[0]][end[1]].color!= piece.color:
                        self.board[end[0]][end[1]] = None
                    self.board[end[0]][end[1]] = self.board[start[0]][start[1]]
                    self.board[start[0]][start[1]] = None
                    return True
        return False

    def is_checkmate(self, color):
        """判断指定颜色的将(帅)是否被将死。"""
        king_pos = None
        for i in range(BOARD_ROWS):
            for j in range(BOARD_COLS):
                if self.board[i][j] is not None and self.board[i][j].color == color and \
                        self.board[i][j].kind in ['将', '帅']:
                    king_pos = (i, j)
        if king_pos is None:
            return False
        for i in range(BOARD_ROWS):
            for j in range(BOARD_COLS):
                if self.board[i][j] is not None and self.board[i][j].color!= color:
                    if self.board[i][j].is_move_valid((i, j), king_pos, self.board):
                        return True
        return False

5.2 测试运行

game = ChessGame()
#尝试移动红方车
game.move_piece((9, 0), (7, 0)) print(game.is_checkmate('黑'))

整理不易,诚望各位看官点赞 收藏 评论 予以支持,这将成为我持续更新的动力源泉。若您在阅览时存有异议或建议,敬请留言指正批评,让我们携手共同学习,共同进取,吾辈自当相互勉励!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值