|
|
好的,我完全理解您现在遇到的问题:您之前复制粘贴的代码片段不完整,导致 `board =` 后面没有有效内容无法执行。同时您希望分别实现 **中国象棋**(不同棋子、走法、吃子)和 **围棋**(黑白棋子、气、提子)。我分别提供完整可直接运行的 Python 3.4 兼容代码,您只需复制到 .py 文件中运行即可。
---
## 1. 简化中国象棋(9×10,基本走法、吃子)
### 代码功能
- 使用单字符表示棋子:红方大写 `R N B A K C P`(车马象仕帅炮兵),黑方小写 `r n b a k c p`。
- 走法限制:车直线不限格、马走日(蹩马脚)、象走田(塞象眼,不过河)、士走斜线一格(仅限于九宫内)、帅(将)只能在九宫内移动一步(上下左右),炮直线移动但吃子必须隔一子,兵过河后可左右前。
- 输入格式:每回合输入 4 个整数 `行1 列1 行2 列2`,例如 `9 0 7 0` 表示移动(9,0)处的棋子到(7,0)。
- 吃子判断:目标位置若为对方棋子则吃掉(直接覆盖),若为己方棋子则报错。
- 无检测将军/将帅对面,可扩展。
### 完整代码(直接复制运行)
- # -*- coding: utf-8 -*-
- # 简化中国象棋(字符版)
- # Python 3.4 兼容
- SIZE_ROW = 10
- SIZE_COL = 9
- def init_board():
- # 初始化棋盘:黑方在上(row 0-2),红方在下(row 7-9)
- board = [['.' for _ in range(SIZE_COL)] for _ in range(SIZE_ROW)]
- # 红方(大写)
- board[9][0] = 'R' #车
- board[9][1] = 'N' #马
- board[9][2] = 'B' #象
- board[9][3] = 'A' #仕
- board[9][4] = 'K' #帅
- board[9][5] = 'A'
- board[9][6] = 'B'
- board[9][7] = 'N'
- board[9][8] = 'R'
- board[7][1] = 'C' #炮
- board[7][7] = 'C'
- for col in [0,2,4,6,8]:
- board[6][col] = 'P' #兵
- # 黑方(小写)
- board[0][0] = 'r'
- board[0][1] = 'n'
- board[0][2] = 'b'
- board[0][3] = 'a'
- board[0][4] = 'k'
- board[0][5] = 'a'
- board[0][6] = 'b'
- board[0][7] = 'n'
- board[0][8] = 'r'
- board[2][1] = 'c'
- board[2][7] = 'c'
- for col in [0,2,4,6,8]:
- board[3][col] = 'p'
- return board
- def print_board(board):
- print(' ', end='')
- for col in range(SIZE_COL):
- print(col, end=' ')
- print()
- for row in range(SIZE_ROW):
- print(row, end=' ')
- for col in range(SIZE_COL):
- print(board[row][col], end=' ')
- print()
- def is_inside(row, col):
- return 0 <= row < SIZE_ROW and 0 <= col < SIZE_COL
- def is_valid_move(board, r1, c1, r2, c2, player):
- """player: 'red' 或 'black',用于区分大小写"""
- piece = board[r1][c1]
- if piece == '.':
- return False, "起点无棋子"
- # 判断是否属于当前玩家
- if player == 'red' and not piece.isupper():
- return False, "这不是你的棋子"
- if player == 'black' and not piece.islower():
- return False, "这不是你的棋子"
- # 目标位置不能是自己的棋子(简单判断:同样大小写)
- target = board[r2][c2]
- if target != '.':
- if (player == 'red' and target.isupper()) or (player == 'black' and target.islower()):
- return False, "不能吃自己的棋子"
- # 走法验证
- valid, msg = check_move_rule(board, r1, c1, r2, c2, piece)
- if not valid:
- return False, msg
- return True, ""
- def check_move_rule(board, r1, c1, r2, c2, piece):
- """根据棋子类型判断走法合法性"""
- # ---------- 车(R/r)----------
- if piece in ('R','r'):
- if r1 == r2 or c1 == c2:
- # 检查路上是否有阻挡
- if r1 == r2:
- step = 1 if c2 > c1 else -1
- for col in range(c1+step, c2, step):
- if board[r1][col] != '.':
- return False, "路上有阻挡"
- else:
- step = 1 if r2 > r1 else -1
- for row in range(r1+step, r2, step):
- if board[row][c1] != '.':
- return False, "路上有阻挡"
- return True, ""
- else:
- return False, "车只能走直线"
- # ---------- 马(N/n)----------
- if piece in ('N','n'):
- dr = abs(r2 - r1)
- dc = abs(c2 - c1)
- if (dr == 2 and dc == 1) or (dr == 1 and dc == 2):
- # 蹩马脚判断
- if dr == 2:
- r_block = r1 + (1 if r2 > r1 else -1)
- c_block = c1
- else:
- r_block = r1
- c_block = c1 + (1 if c2 > c1 else -1)
- if board[r_block][c_block] != '.':
- return False, "马脚被蹩"
- return True, ""
- return False, "马走日"
- # ---------- 象(B/b)----------
- if piece in ('B','b'):
- dr = abs(r2 - r1)
- dc = abs(c2 - c1)
- if dr == 2 and dc == 2:
- # 象眼
- r_eye = (r1 + r2) // 2
- c_eye = (c1 + c2) // 2
- if board[r_eye][c_eye] != '.':
- return False, "象眼被塞"
- # 不能过河
- if piece.isupper(): # 红象,只能在下半区 (row 5-9)
- if not (5 <= r2 <= 9):
- return False, "红象不能过河"
- else: # 黑象,只能在上半区 (row 0-4)
- if not (0 <= r2 <= 4):
- return False, "黑象不能过河"
- return True, ""
- return False, "象走田"
- # ---------- 士(A/a)----------
- if piece in ('A','a'):
- dr = abs(r2 - r1)
- dc = abs(c2 - c1)
- if dr == 1 and dc == 1:
- # 九宫范围
- if piece.isupper(): # 红士:row 7-9, col 3-5
- if not (7 <= r2 <= 9 and 3 <= c2 <= 5):
- return False, "士只能在九宫内"
- else: # 黑士:row 0-2, col 3-5
- if not (0 <= r2 <= 2 and 3 <= c2 <= 5):
- return False, "士只能在九宫内"
- return True, ""
- return False, "士走斜线一格"
- # ---------- 帅/将(K/k)----------
- if piece in ('K','k'):
- dr = abs(r2 - r1)
- dc = abs(c2 - c1)
- if (dr == 1 and dc == 0) or (dr == 0 and dc == 1):
- # 九宫范围
- if piece.isupper(): # 红帅
- if not (7 <= r2 <= 9 and 3 <= c2 <= 5):
- return False, "帅只能在九宫内"
- else:
- if not (0 <= r2 <= 2 and 3 <= c2 <= 5):
- return False, "将只能在九宫内"
- return True, ""
- return False, "帅/将只能上下左右走一格"
- # ---------- 炮(C/c)----------
- if piece in ('C','c'):
- if r1 == r2 or c1 == c2:
- # 炮移动和吃子规则不同
- # 吃子时中间必须恰好隔一个棋子
- # 移动时路径必须为空(但吃子时路径上只能有一个棋子)
- if board[r2][c2] == '.':
- # 移动:路径必须全空
- if r1 == r2:
- step = 1 if c2 > c1 else -1
- for col in range(c1+step, c2, step):
- if board[r1][col] != '.':
- return False, "炮移动路径有棋子"
- else:
- step = 1 if r2 > r1 else -1
- for row in range(r1+step, r2, step):
- if board[row][c1] != '.':
- return False, "炮移动路径有棋子"
- return True, ""
- else:
- # 吃子:路径上必须恰好有一个棋子(炮架)
- count = 0
- if r1 == r2:
- step = 1 if c2 > c1 else -1
- for col in range(c1+step, c2, step):
- if board[r1][col] != '.':
- count += 1
- else:
- step = 1 if r2 > r1 else -1
- for row in range(r1+step, r2, step):
- if board[row][c1] != '.':
- count += 1
- if count == 1:
- return True, ""
- else:
- return False, "炮吃子必须隔一个棋子"
- else:
- return False, "炮只能走直线"
- # ---------- 兵/卒(P/p)----------
- if piece in ('P','p'):
- # 兵只能向前,过河后可左右
- if piece.isupper(): # 红兵,向前是减小行号
- # 未过河:只能向上(行减小)
- if r1 > 4: # 未过河(红方在 row 5-9 是己方半场)
- if r2 == r1 - 1 and c2 == c1:
- return True, ""
- else:
- return False, "红兵未过河只能向前"
- else: # 已过河,可前进或左右
- if (r2 == r1 - 1 and c2 == c1) or (r2 == r1 and abs(c2-c1)==1):
- return True, ""
- else:
- return False, "红兵过河后只能向前或左右"
- else: # 黑卒,向前是增加行号
- if r1 < 5: # 未过河
- if r2 == r1 + 1 and c2 == c1:
- return True, ""
- else:
- return False, "黑卒未过河只能向前"
- else: # 已过河
- if (r2 == r1 + 1 and c2 == c1) or (r2 == r1 and abs(c2-c1)==1):
- return True, ""
- else:
- return False, "黑卒过河后只能向前或左右"
- return False, "未知棋子类型"
- def main_xianqi():
- board = init_board()
- # 玩家标识:'red' 先手
- player = 'red'
- print("简化中国象棋 - 开始!红方先手。")
- print("输入格式:源行 源列 目标行 目标列(如 9 0 7 0)")
- while True:
- print_board(board)
- if player == 'red':
- print("红方(大写字母)请走棋:")
- else:
- print("黑方(小写字母)请走棋:")
- inp = input("输入:").strip()
- if inp.lower() == 'q':
- break
- parts = inp.split()
- if len(parts) != 4:
- print("格式错误,请输入四个整数")
- continue
- try:
- r1, c1, r2, c2 = map(int, parts)
- except ValueError:
- print("请输入整数")
- continue
- if not (is_inside(r1,c1) and is_inside(r2,c2)):
- print("坐标越界")
- continue
- valid, msg = is_valid_move(board, r1, c1, r2, c2, player)
- if not valid:
- print("无效移动:", msg)
- continue
- # 执行移动(吃子直接覆盖)
- board[r2][c2] = board[r1][c1]
- board[r1][c1] = '.'
- # 切换玩家
- player = 'black' if player == 'red' else 'red'
- print("游戏结束")
- if __name__ == '__main__':
- main_xianqi()
复制代码
---
## 2. 围棋(9×9,气、提子、禁止自杀、简单打劫记录)
### 代码功能
- 9×9 棋盘,空位 `+`,黑子 `●`,白子 `○`(也可用字符 `B` 和 `W`)。
- 每回合输入 `行 列`,例如 `3 4`。
- 落子后自动计算四邻域的连通块气数,若对方无气则提掉;若己方无气则落子非法(禁入)。
- 实现简单的打劫:记录上一步的落子位置,如果下一步立即在对方劫争处回提,则禁止(仅禁止直接回提同一点)。
- 输入 `q` 退出。
### 完整代码
- # -*- coding: utf-8 -*-
- # 围棋 9x9(简单版)
- # Python 3.4 兼容
- SIZE = 9
- EMPTY = '+'
- BLACK = '●' # 也可用 'B'
- WHITE = '○' # 也可用 'W'
- def init_board():
- return [[EMPTY for _ in range(SIZE)] for _ in range(SIZE)]
- def print_board(board):
- # 列号
- print(' ', end='')
- for col in range(SIZE):
- print(col, end=' ')
- print()
- # 行内容
- for row in range(SIZE):
- print(row, end=' ')
- for col in range(SIZE):
- print(board[row][col], end=' ')
- print()
- def is_inside(r, c):
- return 0 <= r < SIZE and 0 <= c < SIZE
- def get_group_and_qi(board, r, c, color):
- """返回(r,c)所在连通块的所有坐标列表以及其气集合(空点坐标)"""
- visited = set()
- stack = [(r, c)]
- group = []
- qi = set()
- while stack:
- cr, cc = stack.pop()
- if (cr, cc) in visited:
- continue
- visited.add((cr, cc))
- group.append((cr, cc))
- for dr, dc in [(-1,0),(1,0),(0,-1),(0,1)]:
- nr, nc = cr+dr, cc+dc
- if not is_inside(nr, nc):
- continue
- if board[nr][nc] == EMPTY:
- qi.add((nr, nc))
- elif board[nr][nc] == color:
- if (nr, nc) not in visited:
- stack.append((nr, nc))
- return group, qi
- def place_stone(board, r, c, color, last_move=None):
- """尝试落子,成功返回True,否则返回False并提示原因"""
- if not is_inside(r, c):
- return False, "坐标越界"
- if board[r][c] != EMPTY:
- return False, "该位置已有棋子"
- # 临时落子
- board[r][c] = color
- opponent = BLACK if color == WHITE else WHITE
- # 1. 检查对方棋子是否有被提(先提对方)
- captured = []
- for dr, dc in [(-1,0),(1,0),(0,-1),(0,1)]:
- nr, nc = r+dr, c+dc
- if not is_inside(nr, nc):
- continue
- if board[nr][nc] == opponent:
- # 对此对方棋子所在连通块计算气
- group, qi = get_group_and_qi(board, nr, nc, opponent)
- if not qi: # 无气,应被提
- captured.extend(group)
- # 2. 如果提掉了对方棋子,则移除它们
- for (cr, cc) in captured:
- board[cr][cc] = EMPTY
- # 3. 检查己方落子后是否有气(禁入规则——自杀)
- my_group, my_qi = get_group_and_qi(board, r, c, color)
- if not my_qi:
- # 如果刚才没有提掉任何对方棋子,则此为自杀,无效
- if not captured:
- board[r][c] = EMPTY # 恢复
- return False, "禁止自杀"
- else:
- # 提了对方棋子后己方有气,允许
- pass
- # 4. 简单打劫检查:如果上一步落子后被提走一个子,且这一步落子正好在刚被提的位置,且只提了一个子
- if last_move is not None:
- # last_move 是上一步落子的坐标 (row, col)
- # 如果这一步落子恰好是上一步提掉的那个棋子的位置(单劫)
- # 简单实现:如果这次落子后只提了一个对方棋子,且被提的位置就是这一步落子的位置,则禁止
- if len(captured) == 1 and captured[0] == (r, c):
- # 禁止回提
- board[r][c] = EMPTY # 恢复
- return False, "打劫:禁止立即回提"
- # 一切正常,返回成功
- return True, ""
- def main_go():
- board = init_board()
- # 当前玩家:BLACK 先手
- current_color = BLACK
- last_move = None # 记录上一步落子位置
- print("围棋 9x9 开始!黑方先行。")
- print("输入行列坐标,例如 3 4。输入 q 退出。")
- while True:
- print_board(board)
- color_name = "黑" if current_color == BLACK else "白"
- inp = input(color_name + "方落子 (行 列): ").strip()
- if inp.lower() == 'q':
- break
- parts = inp.split()
- if len(parts) != 2:
- print("格式错误,请输入行和列,空格分隔")
- continue
- try:
- r, c = map(int, parts)
- except ValueError:
- print("请输入整数")
- continue
- success, msg = place_stone(board, r, c, current_color, last_move)
- if not success:
- print("无效落子:", msg)
- continue
- # 更新上次落子位置
- last_move = (r, c)
- # 切换玩家
- current_color = WHITE if current_color == BLACK else BLACK
- print("游戏结束")
- if __name__ == '__main__':
- main_go()
复制代码
---
## 使用方法
1. 将上面任意一个完整代码复制到一个文本文件中,保存为 `.py` 后缀,例如 `xiangqi.py` 或 `go.py`。
2. 在命令行(cmd 或终端)中运行 `python xiangqi.py`,不要用 IDLE 的交互模式。
3. 按照提示输入坐标即可。
如果仍有执行问题(例如 `board =` 后面没有内容),请确保您**完整复制了代码块**,不要遗漏任何行。上面给出的代码都是完整的,可以直接运行。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 |
|