通过Python编写的中国象棋小游戏
通过Python编写的中国象棋小游戏
- 以下为游戏原始代码
- 以下为游戏优化行进规则后的代码
确保代码简洁,结构清晰,方便后续扩展或添加功能,比如悔棋、保存游戏等。但用户可能只需要基本功能,所以先完成核心部分。
以下为游戏原始代码
import sys
class ChessPiece:
def __init__(self, name, color):
self.name = name
self.color = color # 'red' 或 'black'
def display(self):
colors = {'red': '\033[91m', 'black': '\033[94m'}
return f"{colors[self.color]}{self.name}\033[0m"
class ChineseChess:
def __init__(self):
self.board = [[None for _ in range(9)] for _ in range(10)]
self.current_player = 'red'
self.setup_board()
def setup_board(self):
# 初始化棋子布局
pieces = [
('車', '馬', '象', '士', '將', '士', '象', '馬', '車'),
(None, None, None, None, None, None, None, None, None),
(None, '炮', None, None, None, None, None, '炮', None),
('兵', None, '兵', None, '兵', None, '兵', None, '兵'),
(None, None, None, None, None, None, None, None, None),
(None, None, None, None, None, None, None, None, None),
('卒', None, '卒', None, '卒', None, '卒', None, '卒'),
(None, '砲', None, None, None, None, None, '砲', None),
(None, None, None, None, None, None, None, None, None),
('俥', '傌', '相', '仕', '帥', '仕', '相', '傌', '俥')
]
for row in range(10):
for col in range(9):
name = pieces[row][col]
if name:
color = 'red' if row in [9, 8, 7] else 'black'
self.board[row][col] = ChessPiece(name, color)
def print_board(self):
print("\n ", end="")
for col in range(9):
print(f" {chr(65 + col)} ", end="")
print("\n +" + "----+" * 9)
for row in range(10):
print(f"{row} |", end="")
for col in range(9):
piece = self.board[row][col]
if piece:
print(f" {piece.display()} |", end="")
else:
print(" |", end="")
print(f" {row}\n +" + "----+" * 9)
def is_valid_move(self, start_row, start_col, end_row, end_col):
# 实现各棋子的移动规则(此处为简化版,需完善)
piece = self.board[start_row][start_col]
if not piece or piece.color != self.current_player:
return False
dx = abs(end_col - start_col)
dy = abs(end_row - start_row)
target = self.board[end_row][end_col]
# 通用规则检查
if target and target.color == self.current_player:
return False
# 各棋子特殊规则
name = piece.name
if name in ['將', '帥']:
return dx <= 1 and dy <= 1 and 3 <= end_col <= 5 and (
(self.current_player == 'red' and 7 <= end_row <= 9) or
(self.current_player == 'black' and 0 <= end_row <= 2))
elif name in ['士', '仕']:
return dx == 1 and dy == 1 and 3 <= end_col <= 5 and (
(self.current_player == 'red' and 7 <= end_row <= 9) or
(self.current_player == 'black' and 0 <= end_row <= 2))
elif name in ['象', '相']:
# 简化象的走法(需添加蹩脚检查)
return dx == 2 and dy == 2 and end_row <= 4 if self.current_player == 'black' else end_row >= 5
elif name in ['馬', '傌']:
# 简化马走日(需添加蹩脚检查)
return (dx == 1 and dy == 2) or (dx == 2 and dy == 1)
elif name in ['車', '俥']:
return self.check_straight_line(start_row, start_col, end_row, end_col)
elif name in ['炮', '砲']:
obstacles = self.count_obstacles(start_row, start_col, end_row, end_col)
if target:
return obstacles == 1 # 炮需要隔一个棋子吃子
else:
return obstacles == 0 # 移动时不能有障碍
elif name in ['兵', '卒']:
# 简化兵的前进规则
direction = 1 if self.current_player == 'black' else -1
if (self.current_player == 'black' and start_row < 5) or \
(self.current_player == 'red' and start_row > 4):
return (end_row - start_row == direction and dx == 0) or \
(abs(dx) == 1 and dy == 0)
else:
return end_row - start_row == direction and dx == 0
return False
def check_straight_line(self, sr, sc, er, ec):
if sr != er and sc != ec:
return False
step_r = 1 if er > sr else -1 if er < sr else 0
step_c = 1 if ec > sc else -1 if ec < sc else 0
r, c = sr + step_r, sc + step_c
while (r, c) != (er, ec):
if self.board[r][c] is not None:
return False
r += step_r
c += step_c
return True
def count_obstacles(self, sr, sc, er, ec):
count = 0
if sr == er:
step = 1 if ec > sc else -1
for c in range(sc + step, ec, step):
if self.board[sr][c]:
count += 1
else:
step = 1 if er > sr else -1
for r in range(sr + step, er, step):
if self.board[r][sc]:
count += 1
return count
def move_piece(self, start_row, start_col, end_row, end_col):
if self.is_valid_move(start_row, start_col, end_row, end_col):
self.board[end_row][end_col] = self.board[start_row][start_col]
self.board[start_row][start_col] = None
self.current_player = 'black' if self.current_player == 'red' else 'red'
return True
return False
def play(self):
while True:
self.print_board()
print(f"\n当前玩家: {self.current_player}")
try:
move = input("输入起始位置和目标位置(例如:A2 A3): ").upper().split()
if len(move) != 2:
raise ValueError
sc = ord(move[0][0]) - 65
sr = int(move[0][1])
ec = ord(move[1][0]) - 65
er = int(move[1][1])
if 0 <= sr <= 9 and 0 <= sc <= 8 and 0 <= er <= 9 and 0 <= ec <= 8:
if self.move_piece(sr, sc, er, ec):
continue
print("无效移动,请重试!")
except (ValueError, IndexError):
print("输入格式错误,请使用类似 A0 B2 的格式")
if __name__ == "__main__":
game = ChineseChess()
game.play()
以下为游戏优化行进规则后的代码
import sys
class ChessPiece:
def __init__(self, name, color):
self.name = name
self.color = color # 'red' 或 'black'
def display(self):
colors = {'red': '\033[91m', 'black': '\033[94m'}
return f"{colors[self.color]}{self.name}\033[0m"
class ChineseChess:
def __init__(self):
self.board = [[None for _ in range(9)] for _ in range(10)]
self.current_player = 'red'
self.setup_board()
def setup_board(self):
# 初始化棋子布局
pieces = [
('車', '馬', '象', '士', '將', '士', '象', '馬', '車'),
(None, None, None, None, None, None, None, None, None),
(None, '炮', None, None, None, None, None, '炮', None),
('兵', None, '兵', None, '兵', None, '兵', None, '兵'),
(None, None, None, None, None, None, None, None, None),
(None, None, None, None, None, None, None, None, None),
('卒', None, '卒', None, '卒', None, '卒', None, '卒'),
(None, '砲', None, None, None, None, None, '砲', None),
(None, None, None, None, None, None, None, None, None),
('俥', '傌', '相', '仕', '帥', '仕', '相', '傌', '俥')
]
for row in range(10):
for col in range(9):
name = pieces[row][col]
if name:
color = 'red' if row in [9, 8, 7] else 'black'
self.board[row][col] = ChessPiece(name, color)
def print_board(self):
print("\n ", end="")
for col in range(9):
print(f" {chr(65 + col)} ", end="")
print("\n +" + "----+" * 9)
for row in range(10):
print(f"{row} |", end="")
for col in range(9):
piece = self.board[row][col]
if piece:
print(f" {piece.display()} |", end="")
else:
print(" |", end="")
print(f" {row}\n +" + "----+" * 9)
def is_valid_move(self, start_row, start_col, end_row, end_col):
piece = self.board[start_row][start_col]
if not piece or piece.color != self.current_player:
return False
dx = abs(end_col - start_col)
dy = abs(end_row - start_row)
target = self.board[end_row][end_col]
# 通用规则检查
if target and target.color == self.current_player:
return False
# 各棋子特殊规则
name = piece.name
if name in ['將', '帥']:
return self.validate_king(start_row, start_col, end_row, end_col, dx, dy)
elif name in ['士', '仕']:
return self.validate_advisor(start_row, start_col, end_row, end_col, dx, dy)
elif name in ['象', '相']:
return self.validate_bishop(start_row, start_col, end_row, end_col, dx, dy)
elif name in ['馬', '傌']:
return self.validate_knight(start_row, start_col, end_row, end_col, dx, dy)
elif name in ['車', '俥']:
return self.check_straight_line(start_row, start_col, end_row, end_col)
elif name in ['炮', '砲']:
return self.validate_cannon(start_row, start_col, end_row, end_col)
elif name in ['兵', '卒']:
return self.validate_pawn(start_row, start_col, end_row, end_col, dx, dy)
return False
def validate_king(self, sr, sc, er, ec, dx, dy):
"""将/帅移动规则"""
# 移动距离为一格且直线
if dx + dy != 1 or (dx != 0 and dy != 0):
return False
# 目标在九宫内
if not (3 <= ec <= 5):
return False
if self.current_player == 'red':
if not (7 <= er <= 9):
return False
else:
if not (0 <= er <= 2):
return False
return True
def validate_advisor(self, sr, sc, er, ec, dx, dy):
"""士/仕移动规则"""
# 斜走一格
if dx != 1 or dy != 1:
return False
# 目标在九宫内
if not (3 <= ec <= 5):
return False
if self.current_player == 'red':
return 7 <= er <= 9
else:
return 0 <= er <= 2
def validate_bishop(self, sr, sc, er, ec, dx, dy):
"""象/相移动规则"""
if dx != 2 or dy != 2:
return False
# 检查象眼
if self.board[(sr + er)//2][(sc + ec)//2] is not None:
return False
# 不能过河
if self.current_player == 'red':
return er >= 5 # 红方相不过河
else:
return er <= 4 # 黑方象不过河
def validate_knight(self, sr, sc, er, ec, dx, dy):
"""马移动规则"""
if not ((dx == 2 and dy == 1) or (dx == 1 and dy == 2)):
return False
# 检查蹩马腿
if dx == 2: # 横向移动
mid_col = (sc + ec) // 2
if self.board[sr][mid_col] is not None:
return False
else: # 纵向移动
mid_row = (sr + er) // 2
if self.board[mid_row][sc] is not None:
return False
return True
def validate_cannon(self, sr, sc, er, ec):
"""炮移动规则"""
if not self.check_straight_line(sr, sc, er, ec):
return False
obstacles = self.count_obstacles(sr, sc, er, ec)
target = self.board[er][ec]
if target: # 吃子时需要1个障碍
return obstacles == 1
else: # 移动时无障碍
return obstacles == 0
def validate_pawn(self, sr, sc, er, ec, dx, dy):
"""兵/卒移动规则"""
color = self.current_player
forward = er - sr if color == 'black' else sr - er
# 移动方向必须向前(过河前)或允许横向(过河后)
if color == 'black':
crossed = sr >= 5 # 黑卒过河条件
else:
crossed = sr <= 4 # 红兵过河条件
# 检查移动类型
if crossed:
# 过河后可以横向或纵向移动
if dy == 0: # 横向移动
return dx == 1 and forward == 0
else: # 纵向移动
return forward == 1
else:
# 未过河只能向前
return dx == 0 and forward == 1
def check_straight_line(self, sr, sc, er, ec):
"""检查直线路径是否畅通"""
if sr != er and sc != ec:
return False
step_r = 1 if er > sr else -1 if er < sr else 0
step_c = 1 if ec > sc else -1 if ec < sc else 0
r, c = sr + step_r, sc + step_c
while (r, c) != (er, ec):
if self.board[r][c] is not None:
return False
r += step_r
c += step_c
return True
def count_obstacles(self, sr, sc, er, ec):
"""统计直线路径上的障碍物数量"""
count = 0
if sr == er:
start, end = sorted([sc, ec])
for c in range(start + 1, end):
if self.board[sr][c] is not None:
count += 1
else:
start, end = sorted([sr, er])
for r in range(start + 1, end):
if self.board[r][sc] is not None:
count += 1
return count
# 其他方法保持不变...
if __name__ == "__main__":
game = ChineseChess()
game.play()