请注意以下棋类完全由本人原创构思+ai代码构成,简单梳理可玩性后推出【规则封装至程序】

瘸子棋.py

import numpy as np
import os
import sys
from enum import Enum

class GameState(Enum):
    MENU = 1
    PLAYING = 2
    RULES = 3
    GAME_OVER = 4

class LameChessGame:
    def __init__(self, n=17):
        if n % 2 == 0:
            n += 1  # 确保棋盘有中心点
        self.n = n
        self.board = np.full((n, n), ' ', dtype=str)  # 初始化棋盘
        self.center = n // 2
        self.pawn_pos = (self.center, self.center)  # 瘸子初始位置
        self.board[self.center][self.center] = 'P'  # 放置瘸子

        # 设置终点位置
        self.goal_A = (self.center, 0)
        self.goal_B = (self.center, n - 1)
        self.board[self.goal_A] = 'G'  # A终点标记
        self.board[self.goal_B] = 'G'  # B终点标记

        self.current_player = 'A'  # A先手
        self.valves = {'A': [], 'B': []}  # 存储转向阀位置
        self.turn_positions = []  # 记录转动路径
        self.move_count = 0
        self.winner = None
        self.game_state = GameState.MENU
        self.valid_placements = []  # 存储当前可放置位置
        self.preview_dict = {}  # 预览位置字典(位置->数字编号)
        self.consecutive_no_moves = 0  # 连续无移动回合计数

    def clear_screen(self):
        """清屏函数"""
        os.system('cls' if os.name == 'nt' else 'clear')

    def print_header(self):
        """打印游戏标题"""
        print("=" * 60)
        print(f"{'瘸 子 棋 游 戏':^60}")
        print("=" * 60)
        print(f"{'棋盘大小: ' + str(self.n) + 'x' + str(self.n):^60}")
        print("=" * 60)

    def print_board(self, preview_dict=None):
        """打印当前棋盘状态"""
        if preview_dict is None:
            preview_dict = {}

        # 列坐标
        col_header = "     " + " ".join(f"{i:02d}" for i in range(self.n))
        print(col_header)
        print("   ┌" + "──" * self.n + "─┐")

        for r in range(self.n):
            row_str = f"{r:02d} │ "
            for c in range(self.n):
                pos = (r, c)
                cell = self.board[r][c]

                # 显示预览位置数字
                display_char = None
                if pos in preview_dict:
                    num = preview_dict[pos]
                    display_char = f'\033[1;37;44m{num}\033[0m'  # 蓝底白字加粗

                if display_char:
                    row_str += display_char
                elif cell == 'G' and pos == self.goal_A:  # A终点
                    row_str += '\033[91m★\033[0m'
                elif cell == 'G' and pos == self.goal_B:  # B终点
                    row_str += '\033[94m★\033[0m'
                elif cell == 'P':  # 瘸子
                    row_str += '\033[92m♞\033[0m'
                elif cell == 'A':  # A阀门
                    row_str += '\033[91m■\033[0m'
                elif cell == 'B':  # B阀门
                    row_str += '\033[94m■\033[0m'
                elif cell == ' ':  # 空位
                    row_str += '·'
                else:  # 其他
                    row_str += f'{cell}'

                row_str += ' '  # 格子间空格

            row_str += "│"
            print(row_str)

        print("   └" + "──" * self.n + "─┘")
        print(
            f"玩家 \033[91mA\033[0m 目标: ({self.goal_A[0]}, {self.goal_A[1]}) | 玩家 \033[94mB\033[0m 目标: ({self.goal_B[0]}, {self.goal_B[1]})")
        print(f"当前回合: 玩家 \033[{'91' if self.current_player == 'A' else '94'}m{self.current_player}\033[0m")
        print(f"移动次数: {self.move_count}")

    def get_adjacent_positions(self, pos):
        """获取相邻位置"""
        r, c = pos
        positions = []
        for dr, dc in [(0, 1), (1, 0), (0, -1), (-1, 0)]:
            nr, nc = r + dr, c + dc
            if 0 <= nr < self.n and 0 <= nc < self.n:
                positions.append((nr, nc))
        return positions

    def place_valve(self):
        """放置转向阀阶段(强制放置)"""
        self.clear_screen()
        self.print_header()

        adjacent = self.get_adjacent_positions(self.pawn_pos)
        self.valid_placements = [pos for pos in adjacent if self.board[pos] == ' ' or self.board[pos] == 'G']
        self.preview_dict = {}  # 重置预览字典

        # 如果没有可放置位置,直接跳过
        if not self.valid_placements:
            print("\n\033[33m无可放置位置,跳过放置阶段\033[0m")
            input("按Enter继续...")
            return False

        # 创建位置-数字映射
        for i, pos in enumerate(self.valid_placements):
            if i < 9:  # 只显示1-9
                self.preview_dict[pos] = i + 1

        # 打印棋盘并显示预览位置数字
        self.print_board(preview_dict=self.preview_dict)

        print(f"\n\033[92m请选择放置位置:\033[0m")
        for i, pos in enumerate(self.valid_placements):
            # 为每个选项显示数字编号
            num_display = f"[\033[44m{i+1}\033[0m]" if i < 9 else f"[{i+1}]"
            print(f"{num_display}: ({pos[0]}, {pos[1]})")

        while True:
            try:
                choice = input("请输入放置位置编号: ")
                choice = int(choice)
                if 1 <= choice <= len(self.valid_placements):
                    pos = self.valid_placements[choice - 1]
                    r, c = pos

                    # 放置转向阀
                    self.board[r][c] = self.current_player
                    self.valves[self.current_player].append((r, c))
                    print(
                        f"玩家 \033[{'91' if self.current_player == 'A' else '94'}m{self.current_player}\033[0m 在 ({r},{c}) 放置了转向阀")
                    return True
                else:
                    print("\033[33m编号无效,请重新选择\033[0m")
            except:
                print("\033[33m输入无效,请重新选择\033[0m")

    def is_valve_in_straight_line(self, valve_pos):
        """检查阀门是否在瘸子的同一行或同一列(水平或垂直方向)"""
        r1, c1 = self.pawn_pos
        r2, c2 = valve_pos
        return r1 == r2 or c1 == c2

    def check_path_to_valve(self, valve_pos):
        """检查到阀门的路径是否畅通(只检查水平和垂直方向)"""
        r1, c1 = self.pawn_pos
        r2, c2 = valve_pos

        # 首先检查是否在水平或垂直方向
        if not self.is_valve_in_straight_line(valve_pos):
            return False

        # 确定方向向量
        dr = r2 - r1
        dc = c2 - c1

        # 标准化方向
        step_r = 0 if dr == 0 else 1 if dr > 0 else -1
        step_c = 0 if dc == 0 else 1 if dc > 0 else -1

        # 计算步数
        steps = max(abs(dr), abs(dc))

        # 检查路径上的每个格子(不包括起点和终点)
        for i in range(1, steps):
            r = r1 + i * step_r
            c = c1 + i * step_c
            cell = self.board[r][c]

            # 只允许空格、终点或当前玩家的阀门
            if cell == ' ' or cell == 'G' or cell == self.current_player:
                continue
            else:
                return False

        return True

    def calculate_rotation(self, valve_pos):
        """计算旋转后的位置"""
        pr, pc = self.pawn_pos
        vr, vc = valve_pos

        # 计算相对向量
        dr, dc = pr - vr, pc - vc

        # 计算旋转后的位置 (90度)
        clockwise = (vr - dc, vc + dr)  # 顺时针
        counter_clockwise = (vr + dc, vc - dr)  # 逆时针

        valid_positions = []
        for direction, pos in [('顺时针', clockwise), ('逆时针', counter_clockwise)]:
            r, c = pos
            # 检查位置是否在棋盘内
            if not (0 <= r < self.n and 0 <= c < self.n):
                continue

            # 检查落点是否为空或终点(仅允许移动到自己的终点)
            cell = self.board[r][c]
            if cell == ' ':
                pass  # 空位总是允许
            elif cell == 'G':  # 终点位置
                # 玩家A只能移动到A终点,玩家B只能移动到B终点
                if (self.current_player == 'A' and (r, c) != self.goal_A) or \
                        (self.current_player == 'B' and (r, c) != self.goal_B):
                    continue  # 跳过对方终点
            else:
                continue  # 其他情况不允许

            # 检查路径是否畅通
            if not self.check_path_to_valve(valve_pos):
                continue

            # 避免回到原点
            if len(self.turn_positions) > 1 and pos == self.turn_positions[-2]:
                continue

            valid_positions.append((direction, pos))

        return valid_positions

    def rotate_pawn(self):
        """转动瘸子阶段"""
        self.turn_positions = [self.pawn_pos]
        valve_usage = {}  # 本回合阀门使用计数(每回合重置)
        moved = False  # 标记本回合是否进行了移动

        while True:
            self.clear_screen()
            self.print_header()

            available_rotations = []
            self.preview_dict = {}  # 重置预览字典

            # 检查所有可用的转向阀(只考虑水平和垂直方向)
            for valve_pos in self.valves[self.current_player]:
                # 首先检查阀门是否在水平和垂直方向
                if not self.is_valve_in_straight_line(valve_pos):
                    continue

                # 检查使用次数(本回合内)
                if valve_usage.get(valve_pos, 0) < 3:
                    rotations = self.calculate_rotation(valve_pos)
                    for direction, pos in rotations:
                        available_rotations.append((valve_pos, direction, pos))

            # 创建预览位置字典
            for idx, (_, _, pos) in enumerate(available_rotations, start=1):
                if idx <= 9:  # 只显示1-9
                    self.preview_dict[pos] = idx

            # 打印棋盘并显示预览位置数字
            self.print_board(preview_dict=self.preview_dict)

            if not available_rotations:
                if not moved:  # 如果整个回合都没移动过
                    print("\n\033[33m无可用的转动操作\033[0m")
                else:
                    print("\n\033[33m无法继续转动\033[0m")
                input("按Enter结束转动阶段...")
                return moved

            # 显示可用操作
            print("\n\033[92m可用转动操作:\033[0m")
            for i, (valve, direction, pos) in enumerate(available_rotations):
                # 为每个选项使用不同颜色
                direction_color = '\033[96m' if direction == '顺时针' else '\033[95m'
                # 如果位置有预览数字,显示在操作中
                preview_num = self.preview_dict.get(pos, ' ')
                preview_display = f"[\033[44m{preview_num}\033[0m]" if pos in self.preview_dict else "[ ]"
                print(
                    f"{preview_display} {i + 1}: 使用阀({valve[0]},{valve[1]}) {direction_color}{direction}\033[0m → 移动到({pos[0]},{pos[1]})")
            print("\033[48;5;196m 0 \033[0m: 结束转动阶段")

            # 玩家选择
            try:
                choice = input("请选择操作编号: ")
                if choice == '0':
                    break

                choice = int(choice)
                if 1 <= choice <= len(available_rotations):
                    valve_pos, direction, new_pos = available_rotations[choice - 1]

                    # 更新使用次数
                    valve_usage[valve_pos] = valve_usage.get(valve_pos, 0) + 1

                    # 移动瘸子
                    old_r, old_c = self.pawn_pos
                    new_r, new_c = new_pos
                    self.board[old_r][old_c] = ' '
                    self.board[new_r][new_c] = 'P'
                    self.pawn_pos = (new_r, new_c)
                    self.turn_positions.append(new_pos)
                    moved = True  # 标记已移动
                    self.move_count += 1

                    direction_color = '\033[96m' if direction == '顺时针' else '\033[95m'
                    print(
                        f"\n玩家 \033[{'91' if self.current_player == 'A' else '94'}m{self.current_player}\033[0m 使用阀{valve_pos} {direction_color}{direction}\033[0m 移动到 ({new_r},{new_c})")

                    # 检查胜利条件
                    if (self.current_player == 'A' and new_pos == self.goal_A) or \
                            (self.current_player == 'B' and new_pos == self.goal_B):
                        self.winner = self.current_player
                        return True
                else:
                    print("\033[33m编号无效,请重新选择\033[0m")
            except:
                print("\033[33m输入无效,请重新选择\033[0m")

        return moved

    def play_turn(self):
        """执行一个完整回合"""
        # 放置阶段(强制放置)
        placed = self.place_valve()

        # 转动阶段
        moved = self.rotate_pawn()

        # 如果本回合有移动操作,重置无移动计数
        if placed or moved:
            self.consecutive_no_moves = 0
        else:
            self.consecutive_no_moves += 1
            print(f"\n\033[33m玩家 {self.current_player} 本回合无有效操作\033[0m")
            print(f"连续无操作回合: {self.consecutive_no_moves}/2")
            input("按Enter继续...")

        # 检查胜利条件
        if self.winner:
            return True

        # 切换玩家
        self.current_player = 'B' if self.current_player == 'A' else 'A'
        return False

    def show_rules(self):
        """显示游戏规则(更新版)"""
        self.clear_screen()
        self.print_header()
        print("\n\033[93m游戏规则:\033[0m")
        print("1. 在一个n×n的棋盘上,A和B轮流博弈")
        print("2. 棋盘中心有一个♞棋子(瘸子)")
        print("3. 每回合玩家必须:")
        print("   a. 在瘸子相邻的4个方向放置一个转向阀(■)(如有位置)")
        print("   b. 使用自己的转向阀进行90度旋转移动(如有可能)")
        print("4. 关键限制:")
        print("   - 只能使用与瘸子在同一行或同一列(水平或垂直方向)的阀门")
        print("   - 不能使用对角线方向上的阀门")
        print("5. 旋转规则:")
        print("   - 路径上不能有对方阀门")
        print("   - 落点必须是空位(·)或己方终点(★)")
        print("   - 同一阀门一回合最多使用3次")
        print("6. 阀门使用:")
        print("   - 阀门永久有效,可跨回合使用")
        print("7. 胜利条件:")
        print("   - 玩家A将♞移动到左侧终点★(中心行,第0列)")
        print("   - 玩家B将♞移动到右侧终点★(中心行,最后一列)")
        print("8. 平局条件:")
        print("   - 双方连续两回合无法进行任何移动")
        print("\n\033[93m操作说明:\033[0m")
        print("- 放置阶段:棋盘上蓝色数字显示的位置是可选放置位置")
        print("- 放置阶段:选择对应数字编号放置阀门")
        print("- 转动阶段:棋盘上蓝色数字显示的位置是可选目标位置")
        print("- 转动阶段:选择对应数字编号进行转动")
        print("- 转动选项显示方向:\033[96m顺时针\033[0m 或 \033[95m逆时针\033[0m")
        print("\n按Enter返回主菜单...")
        input()

    def show_menu(self):
        """显示主菜单"""
        self.clear_screen()
        self.print_header()
        print("\n\033[93m主菜单:\033[0m")
        print("\033[48;5;40m 1 \033[0m 开始新游戏")
        print("\033[48;5;45m 2 \033[0m 游戏规则")
        print("\033[48;5;196m 3 \033[0m 退出游戏")

        while True:
            choice = input("\n请选择: ")
            if choice == '1':
                self.__init__(self.n)  # 重置游戏
                self.game_state = GameState.PLAYING
                return
            elif choice == '2':
                self.game_state = GameState.RULES
                return
            elif choice == '3':
                sys.exit(0)
            else:
                print("\033[33m无效选择,请重新输入\033[0m")

    def show_game_over(self):
        """显示游戏结束画面"""
        self.clear_screen()
        self.print_header()
        self.print_board()

        if self.winner == 'DRAW':
            print("\n╔════════════════════════╗")
            print("║       \033[93m平 局!\033[0m         ║")
            print("╚════════════════════════╝")
            print("双方连续两回合无法进行任何移动")
        else:
            color = '\033[91m' if self.winner == 'A' else '\033[94m'
            print(f"\n╔════════════════════════╗")
            print(f"║  玩家 {color}{self.winner}\033[0m \033[93m获胜!\033[0m  ║")
            print("╚════════════════════════╝")

        print("\n\033[93m选择:\033[0m")
        print("\033[48;5;40m 1 \033[0m 返回主菜单")
        print("\033[48;5;196m 2 \033[0m 退出游戏")

        while True:
            choice = input("\n请选择: ")
            if choice == '1':
                self.game_state = GameState.MENU
                return
            elif choice == '2':
                sys.exit(0)
            else:
                print("\033[33m无效选择,请重新输入\033[0m")

    def play_game(self):
        """主游戏循环"""
        self.consecutive_no_moves = 0

        while True:
            if self.game_state == GameState.MENU:
                self.show_menu()
            elif self.game_state == GameState.RULES:
                self.show_rules()
                self.game_state = GameState.MENU
            elif self.game_state == GameState.PLAYING:
                game_ended = self.play_turn()

                if self.winner:
                    self.game_state = GameState.GAME_OVER
                    continue

                # 检查平局条件
                if self.consecutive_no_moves >= 2:
                    self.winner = 'DRAW'
                    self.game_state = GameState.GAME_OVER

            elif self.game_state == GameState.GAME_OVER:
                self.show_game_over()


# 启动游戏
if __name__ == "__main__":
    # 检查终端尺寸
    if os.name == 'nt':  # Windows
        os.system('mode con: cols=80 lines=50')

    game = LameChessGame(17)  # 17x17棋盘
    game.play_game()

推推棋.py

import numpy as np
import random
import time
import os


class PushGame:
    def __init__(self, rows=7, cols=5):  # 修改为7行5列
        self.set_board_size(rows, cols)
        self.reset_game()
        
    def set_board_size(self, rows, cols):
        """设置棋盘大小并计算相关参数"""
        self.rows = rows
        self.cols = cols
        self.center = (rows // 2, cols // 2)  # 7//2=3, 5//2=2 -> (3,2)
        self.win_count = 1  # 获胜所需中心点计数

    def reset_game(self):
        """重置游戏状态"""
        # 创建空棋盘
        self.board = np.full((self.rows, self.cols), '.', dtype='U1')
        
        # 初始化中心点计数
        self.center_counts = [0, 0]  # [A的中心点计数, B的中心点计数]

        # 初始化玩家位置 - 底边和顶边全放棋子
        # A (玩家0) 在底部一行(所有列)
        for j in range(self.cols):
            self.board[-1, j] = 'A'
        
        # B (玩家1) 在顶部一行(所有列)
        for j in range(self.cols):
            self.board[0, j] = 'B'

        self.current_player = 0  # 0=A, 1=B
        self.last_positions = []  # 存储最近的位置用于检测僵局
        self.game_history = []  # 存储完整游戏历史
        self.move_count = 0  # 移动计数器
        self.last_push_info = None  # 记录上一步的推动信息

    def get_state_key(self):
        """生成唯一状态标识"""
        return hash(str(self.board) + str(self.current_player) + str(self.center_counts))

    def is_valid_position(self, x, y):
        """检查坐标是否有效"""
        return 0 <= x < self.rows and 0 <= y < self.cols

    def get_adjacent_pieces(self, x, y):
        """获取相邻位置的棋子信息"""
        directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]  # 右, 下, 左, 上
        adjacent = []

        for dx, dy in directions:
            nx, ny = x + dx, y + dy
            if self.is_valid_position(nx, ny):
                piece = self.board[nx, ny]
                if piece != '.':  # 忽略空位
                    adjacent.append(((nx, ny), piece, (dx, dy)))
        return adjacent

    def can_push_special(self, x, y, direction):
        """检查特殊推动是否可行"""
        dx, dy = direction
        player_char = 'A' if self.current_player == 0 else 'B'

        # 检查推动方向上的相邻位置
        ax, ay = x + dx, y + dy
        if not self.is_valid_position(ax, ay) or self.board[ax, ay] == '.':
            return False

        # 检查特殊规则条件
        adjacent_piece = self.board[ax, ay]
        if dx == 0:  # 水平推动
            if adjacent_piece != player_char:  # 必须是自己棋子
                return False
        else:  # 垂直推动
            if adjacent_piece == player_char:  # 必须是对手棋子
                return False

        # 检查目标位置是否为空
        tx, ty = ax + dx, ay + dy
        return self.is_valid_position(tx, ty) and self.board[tx, ty] == '.'

    def can_push_normal(self, x, y, direction):
        """检查普通推动是否可行"""
        dx, dy = direction
        cx, cy = x, y

        # 检查第一步是否有效
        nx, ny = cx + dx, cy + dy
        if not self.is_valid_position(nx, ny) or self.board[nx, ny] != '.':
            return False

        return True

    def push_piece(self, x, y, direction, move_type):
        """执行推动操作"""
        dx, dy = direction
        player_char = 'A' if self.current_player == 0 else 'B'

        if move_type == 'special':
            # 特殊推动:移动两个棋子
            ax, ay = x + dx, y + dy
            tx, ty = ax + dx, ay + dy

            # 移动相邻棋子
            self.board[tx, ty] = self.board[ax, ay]
            self.board[ax, ay] = '.'

            # 移动主棋子
            self.board[x + dx, y + dy] = self.board[x, y]
            self.board[x, y] = '.'
            
        elif move_type == 'normal':
            # 普通推动:推动直到遇到障碍
            cx, cy = x, y
            while True:
                nx, ny = cx + dx, cy + dy
                if not self.is_valid_position(nx, ny) or self.board[nx, ny] != '.':
                    break
                cx, cy = nx, ny

            # 移动棋子到最终位置
            self.board[cx, cy] = self.board[x, y]
            self.board[x, y] = '.'

    def find_winner(self):
        """检查胜利条件"""
        if self.center_counts[0] >= self.win_count:
            return 0  # A获胜
        elif self.center_counts[1] >= self.win_count:
            return 1  # B获胜
        return -1  # 无胜者

    def is_draw(self):
        """检查是否平局"""
        # 检查僵局条件(连续3次重复局面)
        if len(self.last_positions) >= 6:
            if (self.last_positions[-1] == self.last_positions[-3] == self.last_positions[-5] and
                    self.last_positions[-2] == self.last_positions[-4] == self.last_positions[-6]):
                return True

        # 检查是否无合法移动
        if not self.get_valid_moves():
            self.current_player = 1 - self.current_player
            if not self.get_valid_moves():
                return True
            self.current_player = 1 - self.current_player

        return False

    def get_valid_moves(self):
        """获取所有合法移动"""
        valid_moves = []
        player_char = 'A' if self.current_player == 0 else 'B'
        directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]  # 右, 下, 左, 上

        # 查找所有可能的移动
        for x in range(self.rows):
            for y in range(self.cols):
                if self.board[x, y] == player_char:
                    # 检查特殊推动
                    for direction in directions:
                        if self.can_push_special(x, y, direction):
                            valid_moves.append((x, y, direction, 'special'))

                    # 检查普通推动
                    for direction in directions:
                        if self.can_push_normal(x, y, direction):
                            valid_moves.append((x, y, direction, 'normal'))

        # 禁止反推规则
        if self.last_push_info is not None:
            if self.current_player != self.last_push_info['from_player']:
                pushed_pos = self.last_push_info['pushed_piece_final_pos']
                pushed_dir = self.last_push_info['pushed_direction']
                reverse_dir = (-pushed_dir[0], -pushed_dir[1])

                filtered_moves = []
                for move in valid_moves:
                    x, y, dir, mtype = move
                    if mtype == 'special' and (x, y) == pushed_pos and dir == reverse_dir:
                        continue
                    filtered_moves.append(move)
                valid_moves = filtered_moves

        return valid_moves

    def make_move(self, move=None):
        """执行移动"""
        if move is None:
            valid_moves = self.get_valid_moves()
            if not valid_moves:
                return False
            move = random.choice(valid_moves)

        x, y, direction, move_type = move
        self.push_piece(x, y, direction, move_type)

        # 检查是否有棋子到达中心点
        cx, cy = self.center
        if self.board[cx, cy] != '.':
            if self.board[cx, cy] == 'A':
                self.center_counts[0] += 1
            elif self.board[cx, cy] == 'B':
                self.center_counts[1] += 1
            self.board[cx, cy] = '.'

        # 记录上一步的推动信息(垂直特殊推动)
        self.last_push_info = None
        if move_type == 'special' and direction[0] != 0:
            pushed_piece_final_pos = (x + 2 * direction[0], y + 2 * direction[1])
            self.last_push_info = {
                'pushed_piece_final_pos': pushed_piece_final_pos,
                'pushed_direction': direction,
                'from_player': self.current_player
            }

        # 记录游戏状态
        self.last_positions.append(self.get_state_key())
        self.game_history.append((
            self.current_player,
            (x, y),
            direction,
            move_type,
            np.copy(self.board),
            self.center_counts.copy()
        ))

        # 检查游戏结束条件
        winner = self.find_winner()
        if winner != -1:
            return winner

        if self.is_draw():
            return 2  # 平局

        # 切换到下一个玩家
        self.current_player = 1 - self.current_player
        self.move_count += 1
        return None

    def simulate_game(self, max_moves=1000):
        """模拟完整游戏"""
        self.reset_game()
        result = None

        for _ in range(max_moves):
            result = self.make_move()
            if result is not None:
                break

        if result is None:
            return 2  # 平局
        return result

    def visualize_board(self, piece_colors=None):
        """可视化棋盘"""
        reset_color = '\033[0m'
        center_color = '\033[93m'  # 中心点颜色 (黄色)
        default_color = reset_color

        player_char = 'A' if self.current_player == 0 else 'B'

        # 显示中心点计数
        print(f"中心点计数: A={self.center_counts[0]}/{self.win_count}, B={self.center_counts[1]}/{self.win_count}")

        # 显示棋盘
        for i, row in enumerate(self.board):
            for j, cell in enumerate(row):
                if cell == 'A' or cell == 'B':
                    if piece_colors and (i, j) in piece_colors:
                        color_code = piece_colors[(i, j)]
                    elif piece_colors is None:
                        color_code = '\033[91m' if cell == 'A' else '\033[94m'
                    elif cell == player_char:
                        color_code = '\033[91m' if self.current_player == 0 else '\033[94m'
                    else:
                        color_code = '\033[90m'  # 对手颜色

                    print(f"{color_code}●{reset_color}", end=" ")
                elif (i, j) == self.center:
                    print(f"{center_color}★{reset_color}", end=" ")
                else:
                    print("·", end=" ")
            print()

        player_colors = {
            0: '\033[91mA\033[0m',
            1: '\033[94mB\033[0m'
        }


def show_rules():
    """显示简化后的游戏规则"""
    os.system('cls' if os.name == 'nt' else 'clear')
    print("推推棋游戏规则")
    print("=" * 40)
    print("1. 目标:先将1个棋子送入中心点(★)者获胜")
    print()
    print("2. 棋盘布局:")
    print(f"   - 7行×5列棋盘,底部行是A方(红●),顶部行是B方(蓝●)")  # 修改尺寸说明
    print("   - 中心位置标记为★")
    print()
    print("3. 移动方式:")
    print("   ① 普通推动:向相邻空位推自己的棋,会一直移动到遇障碍为止")
    print("   ② 特殊推动:")
    print("      - 水平推(左/右):只能推相邻的自己的棋,被推棋前进一格")
    print("      - 垂直推(上/下):只能推相邻的对手的棋,被推棋前进一格")
    print()
    print("4. 特殊规则:")
    print("   - 棋子进入中心点后会被移除,同时增加对应玩家计数")
    print("   - 被垂直推动的棋子,下一回合不能被反方向推回")
    print("   - 连续3次重复局面或双方无合法移动均判为平局")
    print("=" * 40)

    # 显示初始棋盘
    print("\n初始棋盘状态:")
    game = PushGame()
    game.visualize_board()

    input("\n按任意键返回主菜单...")


def interactive_game():
    """交互式游戏"""
    game = PushGame()
    direction_symbols = {
        (0, 1): '→',
        (1, 0): '↓',
        (0, -1): '←',
        (-1, 0): '↑'
    }

    # 不同棋子的颜色集合
    piece_colors = [
        '\033[91m', '\033[92m', '\033[93m', '\033[94m', 
        '\033[95m', '\033[96m', '\033[97m', '\033[31m', 
        '\033[32m', '\033[33m'
    ]
    reset_color = '\033[0m'

    print(f"欢迎来到推推棋游戏! 棋盘大小: {game.rows}行×{game.cols}列")
    print("操作说明:")
    print("- 输入移动编号选择要执行的操作")
    print("- 输入 'exit' 可随时退出游戏")
    print("- 移动类型:普通(→↓←↑)、特殊(会标注)")

    # 显示初始棋盘
    print(f"\n{game.rows}行×{game.cols}列棋盘初始状态:")
    game.visualize_board()
    input("\n按回车键开始游戏...")

    while True:  # 外层循环用于多局游戏
        game = PushGame()
        exit_flag = False

        while True:  # 内层循环用于单局游戏
            # 清屏并显示棋盘
            os.system('cls' if os.name == 'nt' else 'clear')
            
            # 显示当前棋盘信息
            print(f"棋盘大小: {game.rows}行×{game.cols}列 | 获胜所需中心点: {game.win_count}")

            # 获取所有合法移动
            valid_moves = game.get_valid_moves()

            # 创建棋子颜色映射字典
            color_map = {}
            if valid_moves:
                piece_positions = set((x, y) for x, y, _, _ in valid_moves)
                sorted_pieces = sorted(piece_positions, key=lambda pos: (pos[0], pos[1]))

                # 为每个可移动棋子分配颜色
                for i, pos in enumerate(sorted_pieces):
                    color_index = i % len(piece_colors)
                    color_map[pos] = piece_colors[color_index]

            # 显示棋盘
            game.visualize_board(piece_colors=color_map)

            if not valid_moves:
                print("无合法移动! 游戏结束")
                break

            # 按棋子分组移动选项
            moves_by_piece = {}
            for move in valid_moves:
                x, y, direction, move_type = move
                piece_key = (x, y)
                if piece_key not in moves_by_piece:
                    moves_by_piece[piece_key] = []
                moves_by_piece[piece_key].append((direction, move_type))

            # 显示合法移动
            print("\n可移动选项:")
            move_counter = 1
            move_map = {}
            color_index = 0

            # 按位置排序棋子
            sorted_pieces = sorted(moves_by_piece.keys(), key=lambda pos: (pos[0], pos[1]))

            for piece in sorted_pieces:
                x, y = piece
                color_code = piece_colors[color_index % len(piece_colors)]
                color_index += 1

                # 打印棋子标题
                print(f"{color_code}棋子 {color_index}{reset_color} 的移动:")

                # 获取并排序该棋子的移动选项
                directions = moves_by_piece[piece]
                sorted_directions = sorted(directions, key=lambda d: d[0])

                # 打印移动选项
                for direction, move_type in sorted_directions:
                    dir_symbol = direction_symbols[direction]
                    move_type_str = "特殊" if move_type == 'special' else "普通"
                    move_map[move_counter] = (x, y, direction, move_type)

                    print(f"  {color_code}{move_counter}. {dir_symbol} {move_type_str}{reset_color}")
                    move_counter += 1
                print()  # 添加空行分隔

            # 获取玩家输入
            player_char = 'A' if game.current_player == 0 else 'B'
            player_color = '\033[91m' if game.current_player == 0 else '\033[94m'
            user_input = input(
                f"\n{player_color}玩家 {player_char}{reset_color} 的回合 (输入编号): ").strip().lower()

            if user_input == 'exit':
                exit_flag = True
                break

            # 处理输入
            if user_input.isdigit():
                move_index = int(user_input)
                if move_index in move_map:
                    move = move_map[move_index]
                else:
                    print(f"无效编号: {move_index}!")
                    time.sleep(1)
                    continue
            else:
                print("请输入有效编号!")
                time.sleep(1)
                continue

            # 执行移动
            result = game.make_move(move)

            if result == 0:
                os.system('cls' if os.name == 'nt' else 'clear')
                game.visualize_board()
                print("\033[91m玩家 A 获胜!\033[0m")
                break
            elif result == 1:
                os.system('cls' if os.name == 'nt' else 'clear')
                game.visualize_board()
                print("\033[94m玩家 B 获胜!\033[0m")
                break
            elif result == 2:
                os.system('cls' if os.name == 'nt' else 'clear')
                game.visualize_board()
                print("平局!")
                break

        if exit_flag:
            break  # 完全退出游戏

        # 询问是否再来一局
        replay = input("\n再来一局? (y/n): ").strip().lower()
        if replay != 'y':
            break


if __name__ == "__main__":
    while True:
        os.system('cls' if os.name == 'nt' else 'clear')
        print("推推棋游戏")
        print("1. 开始游戏")
        print("2. 游戏规则")
        print("3. 退出")

        choice = input("\n请选择 (1-3): ").strip()

        if choice == '1':
            interactive_game()
        elif choice == '2':
            show_rules()
        elif choice == '3':
            print("退出程序")
            break
        else:
            print("无效选择,请重新输入")
            time.sleep(1)
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐