"""五子棋游戏逻辑模块""" from typing import Optional, Tuple, List, Dict, Any def create_empty_board() -> List[List[int]]: """创建空棋盘 Returns: 15x15的二维列表,0表示空位 """ return [[0] * 15 for _ in range(15)] def parse_coord(coord_str: str) -> Optional[Tuple[int, int]]: """解析坐标字符串 Args: coord_str: 如 "A1", "O15", "h8" Returns: (row, col) 或 None """ coord_str = coord_str.strip().upper() if len(coord_str) < 2: return None # 解析列(A-O) col_char = coord_str[0] if not ('A' <= col_char <= 'O'): return None col = ord(col_char) - ord('A') # 解析行(1-15) try: row = int(coord_str[1:]) - 1 if not (0 <= row <= 14): return None except ValueError: return None return (row, col) def format_coord(row: int, col: int) -> str: """格式化坐标 Args: row: 0-14 col: 0-14 Returns: 如 "A1", "O15" """ col_char = chr(ord('A') + col) row_num = row + 1 return f"{col_char}{row_num}" def is_valid_position(row: int, col: int) -> bool: """检查坐标是否在棋盘范围内 Args: row: 行号 col: 列号 Returns: 是否有效 """ return 0 <= row <= 14 and 0 <= col <= 14 def count_consecutive(board: List[List[int]], row: int, col: int, direction: Tuple[int, int], player: int) -> int: """统计某方向连续同色棋子数(包括当前位置) Args: board: 棋盘状态 row, col: 起始位置 direction: 方向向量 (dr, dc) player: 玩家 (1:黑, 2:白) Returns: 连续棋子数 """ dr, dc = direction count = 1 # 包括当前位置 # 正方向 r, c = row + dr, col + dc while is_valid_position(r, c) and board[r][c] == player: count += 1 r += dr c += dc # 反方向 r, c = row - dr, col - dc while is_valid_position(r, c) and board[r][c] == player: count += 1 r -= dr c -= dc return count def check_win(board: List[List[int]], row: int, col: int, player: int) -> bool: """检查是否获胜(恰好五连珠) Args: board: 棋盘状态 row, col: 最后落子位置 player: 玩家 (1:黑, 2:白) Returns: 是否五连珠获胜 """ # 四个方向:横、竖、左斜、右斜 directions = [(0, 1), (1, 0), (1, 1), (1, -1)] for direction in directions: count = count_consecutive(board, row, col, direction, player) if count == 5: return True return False def analyze_line(board: List[List[int]], row: int, col: int, direction: Tuple[int, int], player: int) -> Dict[str, Any]: """分析某方向的棋型 Args: board: 棋盘状态 row, col: 待分析位置(假设已落子) direction: 方向向量 player: 玩家 Returns: { "consecutive": int, # 连续数 "left_open": bool, # 左侧是否开放 "right_open": bool, # 右侧是否开放 "pattern": str # 棋型类型 } """ dr, dc = direction # 统计正方向连续数 right_count = 0 r, c = row + dr, col + dc while is_valid_position(r, c) and board[r][c] == player: right_count += 1 r += dr c += dc right_open = is_valid_position(r, c) and board[r][c] == 0 # 统计反方向连续数 left_count = 0 r, c = row - dr, col - dc while is_valid_position(r, c) and board[r][c] == player: left_count += 1 r -= dr c -= dc left_open = is_valid_position(r, c) and board[r][c] == 0 # 总连续数(包括当前位置) consecutive = left_count + 1 + right_count # 判定棋型 pattern = "none" if consecutive >= 6: pattern = "overline" elif consecutive == 5: pattern = "five" elif consecutive == 4: if left_open and right_open: pattern = "live_four" elif left_open or right_open: pattern = "rush_four" elif consecutive == 3: if left_open and right_open: pattern = "live_three" elif left_open or right_open: pattern = "sleep_three" return { "consecutive": consecutive, "left_open": left_open, "right_open": right_open, "pattern": pattern } def check_forbidden(board: List[List[int]], row: int, col: int) -> Tuple[bool, str]: """检查黑方禁手 Args: board: 棋盘状态(不包含待落子) row, col: 待落子位置 Returns: (是否禁手, 禁手类型) """ # 只有黑方(玩家1)有禁手 player = 1 # 临时落子 original_value = board[row][col] board[row][col] = player # 四个方向 directions = [(0, 1), (1, 0), (1, 1), (1, -1)] live_threes = 0 fours = 0 has_overline = False for direction in directions: analysis = analyze_line(board, row, col, direction, player) if analysis["pattern"] == "overline": has_overline = True elif analysis["pattern"] == "live_three": live_threes += 1 elif analysis["pattern"] in ["live_four", "rush_four"]: fours += 1 # 恢复棋盘 board[row][col] = original_value # 判定禁手 if has_overline: return True, "长连禁手" if live_threes >= 2: return True, "三三禁手" if fours >= 2: return True, "四四禁手" return False, "" def render_board(board: List[List[int]], last_move: Optional[Tuple[int, int]] = None) -> str: """渲染棋盘为字符串 Args: board: 棋盘状态 last_move: 最后落子位置(可选,用于标记) Returns: 棋盘的字符串表示 """ lines = [] # 列标题 col_labels = " " + " ".join([chr(ord('A') + i) for i in range(15)]) lines.append(col_labels) # 绘制棋盘 for row in range(15): row_num = f"{row + 1:2d}" # 右对齐行号 row_cells = [] for col in range(15): cell = board[row][col] # 标记最后落子 if last_move and last_move == (row, col): if cell == 1: row_cells.append("⚫") elif cell == 2: row_cells.append("⚪") else: row_cells.append("➕") else: if cell == 0: row_cells.append("➕") elif cell == 1: row_cells.append("⚫") elif cell == 2: row_cells.append("⚪") lines.append(f" {row_num} {' '.join(row_cells)}") return "\n".join(lines)