当前位置:首页>java>中国象棋人机对战游戏代码(Windows电脑端)

中国象棋人机对战游戏代码(Windows电脑端)

  • 2026-01-24 10:18:10
中国象棋人机对战游戏代码(Windows电脑端)

      中国象棋是中华民族的优秀文化遗产之一,具有悠久的历史和深厚的文化底蕴。作为一项智力运动,它不仅能够锻炼思维、培养战略眼光,还能增进人与人之间的交流与友谊。中国象棋的规则简洁而富有哲理,体现了中华文化中“和而不同”的思想精髓。今天分享中国象棋人机对战游戏代码(Windows电脑端),供参考!

项目结构

ChineseChess/
├── main.py              # 主游戏文件
├── chess_game.py        # 游戏逻辑
├── ai_engine.py         # AI引擎
├── requirements.txt     # 依赖包
├── setup.py            # 打包配置
└── assets/             # 资源文件
    ├── pieces/
    └── sounds/

完整代码实现

1. 主游戏文件 (main.py)

import pygame
import sys
import os
from chess_game import ChessGame
from ai_engine import ChessAI

# 初始化
pygame.init()
pygame.font.init()
pygame.mixer.init()

# 游戏配置
CELL_SIZE = 60
BOARD_WIDTH = 9
BOARD_HEIGHT = 10
SCREEN_WIDTH = CELL_SIZE * BOARD_WIDTH + 300
SCREEN_HEIGHT = CELL_SIZE * BOARD_HEIGHT + 100

# 颜色定义
COLORS = {
    'background': (220, 179, 92),
    'line': (0, 0, 0),
    'red_piece': (220, 20, 60),
    'black_piece': (30, 30, 30),
    'highlight': (255, 255, 0),
    'text': (50, 50, 50),
    'button': (100, 150, 255),
    'button_hover': (150, 200, 255),
    'panel_bg': (240, 230, 200),
    'border': (150, 120, 80)
}

class ChessGUI:
    def __init__(self):
        self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
        pygame.display.set_caption("中国象棋 - 人机对战")
        self.clock = pygame.time.Clock()
       
        # 加载字体
        try:
            self.font_large = pygame.font.Font(None, 48)
            self.font_medium = pygame.font.Font(None, 36)
            self.font_small = pygame.font.Font(None, 24)
        except:
            self.font_large = pygame.font.SysFont('simhei', 48)
            self.font_medium = pygame.font.SysFont('simhei', 36)
            self.font_small = pygame.font.SysFont('simhei', 24)
       
        # 游戏状态
        self.game = ChessGame()
        self.ai = ChessAI()
        self.selected_piece = None
        self.valid_moves = []
        self.game_state = "MENU"  # MENU, PLAYING, GAME_OVER
        self.difficulty = "EASY"  # EASY, MEDIUM, HARD
        self.ai_thinking = False
        self.message = ""
        self.message_timer = 0
       
    def run(self):
        """运行游戏主循环"""
        running = True
        while running:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False
                elif event.type == pygame.MOUSEBUTTONDOWN:
                    self.handle_click(event.pos)
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_r:
                        self.restart_game()
                    elif event.key == pygame.K_ESCAPE:
                        if self.game_state == "PLAYING":
                            self.game_state = "MENU"
                        elif self.game_state == "MENU":
                            running = False
           
            # 更新游戏状态
            if self.game_state == "PLAYING" and not self.ai_thinking:
                if self.game.current_player == 'black' and not self.game.game_over:
                    self.ai_move()
           
            # 绘制界面
            self.draw()
            pygame.display.flip()
            self.clock.tick(60)
           
            # 更新消息计时器
            if self.message_timer > 0:
                self.message_timer -= 1
                if self.message_timer == 0:
                    self.message = ""
       
        pygame.quit()
        sys.exit()
   
    def handle_click(self, pos):
        """处理鼠标点击事件"""
        x, y = pos
       
        if self.game_state == "MENU":
            # 主菜单按钮处理
            button_y_start = SCREEN_HEIGHT // 2 - 50
           
            # 难度选择按钮
            easy_rect = pygame.Rect(SCREEN_WIDTH // 2 - 100, button_y_start, 200, 50)
            medium_rect = pygame.Rect(SCREEN_WIDTH // 2 - 100, button_y_start + 70, 200, 50)
            hard_rect = pygame.Rect(SCREEN_WIDTH // 2 - 100, button_y_start + 140, 200, 50)
            exit_rect = pygame.Rect(SCREEN_WIDTH // 2 - 100, button_y_start + 210, 200, 50)
           
            if easy_rect.collidepoint(x, y):
                self.difficulty = "EASY"
                self.start_game()
            elif medium_rect.collidepoint(x, y):
                self.difficulty = "MEDIUM"
                self.start_game()
            elif hard_rect.collidepoint(x, y):
                self.difficulty = "HARD"
                self.start_game()
            elif exit_rect.collidepoint(x, y):
                pygame.quit()
                sys.exit()
               
        elif self.game_state == "PLAYING":
            # 游戏控制面板按钮
            panel_x = CELL_SIZE * BOARD_WIDTH + 20
           
            # 重新开始按钮
            restart_rect = pygame.Rect(panel_x, 300, 150, 50)
            # 返回菜单按钮
            menu_rect = pygame.Rect(panel_x, 370, 150, 50)
            # 悔棋按钮
            undo_rect = pygame.Rect(panel_x, 440, 150, 50)
           
            if restart_rect.collidepoint(x, y):
                self.restart_game()
                return
            elif menu_rect.collidepoint(x, y):
                self.game_state = "MENU"
                return
            elif undo_rect.collidepoint(x, y):
                if len(self.game.move_history) > 0:
                    self.game.undo_move()
                    if self.game.current_player == 'black':
                        # 如果当前是黑方,再悔一次(玩家连续悔棋)
                        if len(self.game.move_history) > 0:
                            self.game.undo_move()
                    self.selected_piece = None
                    self.valid_moves = []
                    self.show_message("悔棋成功")
                else:
                    self.show_message("没有棋可悔")
                return
           
            # 棋盘点击处理
            if x < CELL_SIZE * BOARD_WIDTH and y < CELL_SIZE * BOARD_HEIGHT:
                col = x // CELL_SIZE
                row = y // CELL_SIZE
               
                if 0 <= col < BOARD_WIDTH and 0 <= row < BOARD_HEIGHT:
                    if not self.selected_piece:
                        # 选择棋子
                        piece = self.game.get_piece_at(row, col)
                        if piece and piece.color == self.game.current_player:
                            self.selected_piece = piece
                            self.valid_moves = self.game.get_valid_moves(piece)
                            if not self.valid_moves:
                                self.selected_piece = None
                                self.show_message("该棋子无法移动")
                    else:
                        # 移动棋子
                        if self.game.move_piece(self.selected_piece.row,
                                              self.selected_piece.col,
                                              row, col):
                            self.selected_piece = None
                            self.valid_moves = []
                           
                            if self.game.game_over:
                                self.game_state = "GAME_OVER"
                                self.show_message(f"{'红方' if self.game.winner == 'red' else '黑方'}获胜!")
                        else:
                            # 点击其他棋子或取消选择
                            piece = self.game.get_piece_at(row, col)
                            if piece and piece.color == self.game.current_player:
                                self.selected_piece = piece
                                self.valid_moves = self.game.get_valid_moves(piece)
                            else:
                                self.selected_piece = None
                                self.valid_moves = []
       
        elif self.game_state == "GAME_OVER":
            # 游戏结束界面
            button_rect = pygame.Rect(SCREEN_WIDTH // 2 - 100, SCREEN_HEIGHT // 2 + 50, 200, 50)
            if button_rect.collidepoint(x, y):
                self.restart_game()
   
    def ai_move(self):
        """AI移动"""
        self.ai_thinking = True
        self.show_message("电脑思考中...")
       
        # 根据难度设置搜索深度
        if self.difficulty == "EASY":
            depth = 1
        elif self.difficulty == "MEDIUM":
            depth = 2
        else:  # HARD
            depth = 3
       
        # 获取AI最佳移动
        best_move = self.ai.get_best_move(self.game, depth)
       
        if best_move:
            from_pos, to_pos = best_move
            self.game.move_piece(from_pos[0], from_pos[1], to_pos[0], to_pos[1])
           
            if self.game.game_over:
                self.game_state = "GAME_OVER"
                self.show_message(f"{'红方' if self.game.winner == 'red' else '黑方'}获胜!")
       
        self.ai_thinking = False
   
    def start_game(self):
        """开始新游戏"""
        self.game = ChessGame()
        self.selected_piece = None
        self.valid_moves = []
        self.game_state = "PLAYING"
        self.message = ""
   
    def restart_game(self):
        """重新开始游戏"""
        self.start_game()
        self.show_message("新游戏开始")
   
    def show_message(self, message):
        """显示消息"""
        self.message = message
        self.message_timer = 120  # 显示2秒(60帧/秒)
   
    def draw(self):
        """绘制整个界面"""
        if self.game_state == "MENU":
            self.draw_menu()
        elif self.game_state == "PLAYING":
            self.draw_game()
        elif self.game_state == "GAME_OVER":
            self.draw_game_over()
   
    def draw_menu(self):
        """绘制主菜单"""
        # 背景
        self.screen.fill(COLORS['background'])
       
        # 标题
        title = self.font_large.render("中国象棋 - 人机对战", True, COLORS['text'])
        title_rect = title.get_rect(center=(SCREEN_WIDTH // 2, 100))
        self.screen.blit(title, title_rect)
       
        # 版本信息
        version = self.font_small.render("版本 1.0", True, COLORS['text'])
        version_rect = version.get_rect(center=(SCREEN_WIDTH // 2, 160))
        self.screen.blit(version, version_rect)
       
        # 难度选择标题
        diff_title = self.font_medium.render("选择难度", True, COLORS['text'])
        diff_rect = diff_title.get_rect(center=(SCREEN_WIDTH // 2, 220))
        self.screen.blit(diff_title, diff_rect)
       
        # 按钮区域
        button_y_start = SCREEN_HEIGHT // 2 - 50
       
        # 按钮
        buttons = [
            ("初级难度", self.difficulty == "EASY"),
            ("中级难度", self.difficulty == "MEDIUM"),
            ("高级难度", self.difficulty == "HARD"),
            ("退出游戏", False)
        ]
       
        for i, (text, selected) in enumerate(buttons):
            y_pos = button_y_start + i * 70
            button_rect = pygame.Rect(SCREEN_WIDTH // 2 - 100, y_pos, 200, 50)
           
            # 鼠标悬停效果
            mouse_pos = pygame.mouse.get_pos()
            hover = button_rect.collidepoint(mouse_pos)
           
            # 按钮颜色
            if selected:
                color = (50, 150, 50)  # 已选择的颜色
            elif hover:
                color = COLORS['button_hover']
            else:
                color = COLORS['button']
           
            # 绘制按钮
            pygame.draw.rect(self.screen, color, button_rect, border_radius=10)
            pygame.draw.rect(self.screen, COLORS['border'], button_rect, 3, border_radius=10)
           
            # 按钮文字
            btn_text = self.font_medium.render(text, True, (255, 255, 255))
            text_rect = btn_text.get_rect(center=button_rect.center)
            self.screen.blit(btn_text, text_rect)
       
        # 操作说明
        instructions = [
            "操作说明:",
            "1. 点击棋子选择",
            "2. 点击目标位置移动",
            "3. R键: 重新开始",
            "4. ESC键: 返回菜单"
        ]
       
        for i, line in enumerate(instructions):
            text = self.font_small.render(line, True, COLORS['text'])
            self.screen.blit(text, (50, SCREEN_HEIGHT - 150 + i * 25))
   
    def draw_game(self):
        """绘制游戏界面"""
        # 绘制棋盘
        self.draw_board()
       
        # 绘制棋子
        self.draw_pieces()
       
        # 绘制控制面板
        self.draw_control_panel()
       
        # 绘制消息
        if self.message:
            self.draw_message()
       
        # 绘制AI思考状态
        if self.ai_thinking:
            self.draw_thinking()
   
    def draw_board(self):
        """绘制棋盘"""
        # 背景
        self.screen.fill(COLORS['background'])
       
        # 棋盘网格
        for i in range(BOARD_WIDTH + 1):
            x = CELL_SIZE * i
            pygame.draw.line(self.screen, COLORS['line'],
                           (x, 0), (x, CELL_SIZE * BOARD_HEIGHT), 2)
       
        for i in range(BOARD_HEIGHT + 1):
            y = CELL_SIZE * i
            pygame.draw.line(self.screen, COLORS['line'],
                           (0, y), (CELL_SIZE * BOARD_WIDTH, y), 2)
       
        # 绘制九宫格
        # 上方九宫
        pygame.draw.line(self.screen, COLORS['line'],
                        (CELL_SIZE * 3, 0),
                        (CELL_SIZE * 5, CELL_SIZE * 2), 2)
        pygame.draw.line(self.screen, COLORS['line'],
                        (CELL_SIZE * 5, 0),
                        (CELL_SIZE * 3, CELL_SIZE * 2), 2)
       
        # 下方九宫
        pygame.draw.line(self.screen, COLORS['line'],
                        (CELL_SIZE * 3, CELL_SIZE * 7),
                        (CELL_SIZE * 5, CELL_SIZE * 9), 2)
        pygame.draw.line(self.screen, COLORS['line'],
                        (CELL_SIZE * 5, CELL_SIZE * 7),
                        (CELL_SIZE * 3, CELL_SIZE * 9), 2)
       
        # 楚河汉界标记
        river_text = self.font_medium.render("楚河              汉界", True, COLORS['text'])
        text_rect = river_text.get_rect(center=(CELL_SIZE * 4.5, CELL_SIZE * 5))
        self.screen.blit(river_text, text_rect)
   
    def draw_pieces(self):
        """绘制棋子"""
        for row in range(BOARD_HEIGHT):
            for col in range(BOARD_WIDTH):
                piece = self.game.board[row][col]
                if piece:
                    x = col * CELL_SIZE + CELL_SIZE // 2
                    y = row * CELL_SIZE + CELL_SIZE // 2
                   
                    # 棋子颜色
                    if piece.color == 'red':
                        color = COLORS['red_piece']
                        text_color = (255, 255, 255)
                    else:
                        color = (30, 30, 30)
                        text_color = (200, 200, 200)
                   
                    # 绘制棋子
                    pygame.draw.circle(self.screen, color, (x, y), CELL_SIZE // 2 - 5)
                    pygame.draw.circle(self.screen, (255, 255, 255), (x, y), CELL_SIZE // 2 - 7)
                   
                    # 绘制棋子边框
                    pygame.draw.circle(self.screen, (0, 0, 0), (x, y), CELL_SIZE // 2 - 5, 2)
                   
                    # 选中状态高亮
                    if piece == self.selected_piece:
                        pygame.draw.circle(self.screen, COLORS['highlight'],
                                         (x, y), CELL_SIZE // 2 - 3, 3)
                   
                    # 棋子文字
                    piece_text = self.font_medium.render(piece.name, True, text_color)
                    text_rect = piece_text.get_rect(center=(x, y))
                    self.screen.blit(piece_text, text_rect)
       
        # 绘制有效移动位置
        for move in self.valid_moves:
            row, col = move
            x = col * CELL_SIZE + CELL_SIZE // 2
            y = row * CELL_SIZE + CELL_SIZE // 2
            pygame.draw.circle(self.screen, COLORS['highlight'], (x, y), 8, 3)
   
    def draw_control_panel(self):
        """绘制控制面板"""
        panel_x = CELL_SIZE * BOARD_WIDTH + 20
       
        # 面板背景
        pygame.draw.rect(self.screen, COLORS['panel_bg'],
                        (panel_x - 10, 10, 260, SCREEN_HEIGHT - 20), border_radius=10)
        pygame.draw.rect(self.screen, COLORS['border'],
                        (panel_x - 10, 10, 260, SCREEN_HEIGHT - 20), 3, border_radius=10)
       
        # 游戏信息
        info_y = 50
       
        # 当前回合
        current_player = "红方" if self.game.current_player == 'red' else "黑方"
        if self.game.current_player == 'red':
            turn_text = f"当前回合: {current_player} (玩家)"
        else:
            turn_text = f"当前回合: {current_player} (电脑)"
            if self.difficulty == "EASY":
                turn_text += " [初级]"
            elif self.difficulty == "MEDIUM":
                turn_text += " [中级]"
            else:
                turn_text += " [高级]"
       
        turn_surface = self.font_small.render(turn_text, True, COLORS['text'])
        self.screen.blit(turn_surface, (panel_x, info_y))
       
        # 难度显示
        diff_text = f"难度: {self.difficulty}"
        diff_surface = self.font_small.render(diff_text, True, COLORS['text'])
        self.screen.blit(diff_surface, (panel_x, info_y + 30))
       
        # 按钮
        buttons = [
            ("重新开始", 300, self.restart_game),
            ("返回菜单", 370, lambda: setattr(self, 'game_state', 'MENU')),
            ("悔棋", 440, self.undo_move),
            ("操作说明", 510, None)
        ]
       
        for text, y, _ in buttons:
            button_rect = pygame.Rect(panel_x, y, 150, 50)
            mouse_pos = pygame.mouse.get_pos()
            hover = button_rect.collidepoint(mouse_pos)
           
            # 按钮颜色
            color = COLORS['button_hover'] if hover else COLORS['button']
           
            pygame.draw.rect(self.screen, color, button_rect, border_radius=5)
            pygame.draw.rect(self.screen, COLORS['border'], button_rect, 2, border_radius=5)
           
            # 按钮文字
            btn_text = self.font_small.render(text, True, (255, 255, 255))
            text_rect = btn_text.get_rect(center=button_rect.center)
            self.screen.blit(btn_text, text_rect)
       
        # 操作说明
        instructions = [
            "操作说明:",
            "1. 点击棋子选择",
            "2. 点击目标位置移动",
            "3. R键: 重新开始",
            "4. ESC键: 返回菜单",
            "5. 红方为玩家",
            "6. 黑方为电脑AI",
            "",
            "棋子价值:",
            "将/帅: 1000",
            "车: 500",
            "马: 300",
            "炮: 300",
            "士/仕: 200",
            "象/相: 200",
            "兵/卒: 100"
        ]
       
        for i, line in enumerate(instructions):
            text = self.font_small.render(line, True, COLORS['text'])
            self.screen.blit(text, (panel_x, 600 + i * 25))
   
    def draw_message(self):
        """绘制消息"""
        if not self.message:
            return
       
        # 半透明背景
        overlay = pygame.Surface((SCREEN_WIDTH, 60), pygame.SRCALPHA)
        overlay.fill((0, 0, 0, 180))
        self.screen.blit(overlay, (0, SCREEN_HEIGHT - 60))
       
        # 消息文字
        msg_surface = self.font_medium.render(self.message, True, (255, 255, 0))
        msg_rect = msg_surface.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT - 30))
        self.screen.blit(msg_surface, msg_rect)
   
    def draw_thinking(self):
        """绘制AI思考状态"""
        overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
        overlay.fill((0, 0, 0, 100))
        self.screen.blit(overlay, (0, 0))
       
        # 思考文字
        think_text = self.font_large.render("电脑思考中...", True, (255, 255, 0))
        text_rect = think_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))
        self.screen.blit(think_text, text_rect)
   
    def draw_game_over(self):
        """绘制游戏结束界面"""
        # 绘制游戏棋盘
        self.draw_board()
        self.draw_pieces()
        self.draw_control_panel()
       
        # 半透明覆盖层
        overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
        overlay.fill((0, 0, 0, 150))
        self.screen.blit(overlay, (0, 0))
       
        # 游戏结束文字
        winner_text = "红方获胜!" if self.game.winner == 'red' else "黑方获胜!"
        game_over_text = self.font_large.render("游戏结束", True, (255, 255, 0))
        winner_surface = self.font_large.render(winner_text, True, (255, 255, 0))
       
        game_over_rect = game_over_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 50))
        winner_rect = winner_surface.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 + 10))
       
        self.screen.blit(game_over_text, game_over_rect)
        self.screen.blit(winner_surface, winner_rect)
       
        # 重新开始按钮
        button_rect = pygame.Rect(SCREEN_WIDTH // 2 - 100, SCREEN_HEIGHT // 2 + 80, 200, 50)
        mouse_pos = pygame.mouse.get_pos()
        hover = button_rect.collidepoint(mouse_pos)
       
        color = COLORS['button_hover'] if hover else COLORS['button']
        pygame.draw.rect(self.screen, color, button_rect, border_radius=10)
        pygame.draw.rect(self.screen, COLORS['border'], button_rect, 3, border_radius=10)
       
        restart_text = self.font_medium.render("重新开始", True, (255, 255, 255))
        restart_rect = restart_text.get_rect(center=button_rect.center)
        self.screen.blit(restart_text, restart_rect)
   
    def undo_move(self):
        """悔棋功能"""
        if len(self.game.move_history) > 0:
            self.game.undo_move()
            if self.game.current_player == 'black':
                # 如果当前是黑方,再悔一次(玩家连续悔棋)
                if len(self.game.move_history) > 0:
                    self.game.undo_move()
            self.selected_piece = None
            self.valid_moves = []
            self.show_message("悔棋成功")
        else:
            self.show_message("没有棋可悔")

def main():
    """主函数"""
    try:
        game = ChessGUI()
        game.run()
    except Exception as e:
        print(f"游戏启动错误: {e}")
        input("按任意键退出...")

if __name__ == "__main__":
    main()

2. 游戏逻辑文件 (chess_game.py)

import copy

class ChessPiece:
    def __init__(self, name, color, row, col):
        self.name = name
        self.color = color  # 'red' 或 'black'
        self.row = row
        self.col = col
        self.is_visible = True
       
        # 棋子价值
        self.value = self.get_piece_value()
   
    def get_piece_value(self):
        """获取棋子价值"""
        values = {
            '将': 1000, '帥': 1000,
            '车': 500, '車': 500,
            '马': 300, '馬': 300,
            '炮': 300,
            '士': 200, '仕': 200,
            '象': 200, '相': 200,
            '兵': 100, '卒': 100
        }
        return values.get(self.name, 100)
   
    def copy(self):
        """复制棋子"""
        return ChessPiece(self.name, self.color, self.row, self.col)

class ChessGame:
    def __init__(self):
        # 初始化棋盘
        self.board = [[None for _ in range(9)] for _ in range(10)]
        self.current_player = 'red'  # 红方先走
        self.game_over = False
        self.winner = None
        self.move_history = []  # 记录移动历史用于悔棋
       
        # 初始化棋子
        self.init_board()
   
    def init_board(self):
        """初始化棋盘"""
        piece_layout = [
            ["车", "马", "象", "士", "将", "士", "象", "马", "车"],
            ["", "", "", "", "", "", "", "", ""],
            ["", "炮", "", "", "", "", "", "炮", ""],
            ["兵", "", "兵", "", "兵", "", "兵", "", "兵"],
            ["", "", "", "", "", "", "", "", ""],
            ["", "", "", "", "", "", "", "", ""],
            ["卒", "", "卒", "", "卒", "", "卒", "", "卒"],
            ["", "炮", "", "", "", "", "", "炮", ""],
            ["", "", "", "", "", "", "", "", ""],
            ["車", "馬", "相", "仕", "帥", "仕", "相", "馬", "車"]
        ]
       
        for row in range(10):
            for col in range(9):
                name = piece_layout[row][col]
                if name:
                    color = 'red' if row >= 5 else 'black'
                    self.board[row][col] = ChessPiece(name, color, row, col)
   
    def get_piece_at(self, row, col):
        """获取指定位置的棋子"""
        if 0 <= row < 10 and 0 <= col < 9:
            return self.board[row][col]
        return None
   
    def get_valid_moves(self, piece):
        """获取棋子的所有合法移动"""
        moves = []
       
        if piece.name in ["将", "帥"]:
            # 将/帅的移动
            moves = self.get_king_moves(piece)
        elif piece.name in ["士", "仕"]:
            # 士/仕的移动
            moves = self.get_advisor_moves(piece)
        elif piece.name in ["象", "相"]:
            # 象/相的移动
            moves = self.get_bishop_moves(piece)
        elif piece.name in ["马", "馬"]:
            # 马的移动
            moves = self.get_knight_moves(piece)
        elif piece.name in ["车", "車"]:
            # 车的移动
            moves = self.get_rook_moves(piece)
        elif piece.name == "炮":
            # 炮的移动
            moves = self.get_cannon_moves(piece)
        elif piece.name in ["兵", "卒"]:
            # 兵/卒的移动
            moves = self.get_pawn_moves(piece)
       
        # 过滤掉会使自己将军的移动
        safe_moves = []
        for move in moves:
            if self.is_safe_move(piece, move[0], move[1]):
                safe_moves.append(move)
       
        return safe_moves
   
    def get_king_moves(self, piece):
        """获取将/帅的移动"""
        moves = []
        directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
       
        for dr, dc in directions:
            new_row, new_col = piece.row + dr, piece.col + dc
           
            # 检查是否在九宫内
            if piece.color == 'red':
                if not (7 <= new_row <= 9 and 3 <= new_col <= 5):
                    continue
            else:
                if not (0 <= new_row <= 2 and 3 <= new_col <= 5):
                    continue
           
            target = self.get_piece_at(new_row, new_col)
            if not target or target.color != piece.color:
                moves.append((new_row, new_col))
       
        return moves
   
    def get_advisor_moves(self, piece):
        """获取士/仕的移动"""
        moves = []
        directions = [(-1, -1), (-1, 1), (1, -1), (1, 1)]
       
        for dr, dc in directions:
            new_row, new_col = piece.row + dr, piece.col + dc
           
            # 检查是否在九宫内
            if piece.color == 'red':
                if not (7 <= new_row <= 9 and 3 <= new_col <= 5):
                    continue
            else:
                if not (0 <= new_row <= 2 and 3 <= new_col <= 5):
                    continue
           
            target = self.get_piece_at(new_row, new_col)
            if not target or target.color != piece.color:
                moves.append((new_row, new_col))
       
        return moves
   
    def get_bishop_moves(self, piece):
        """获取象/相的移动"""
        moves = []
        directions = [(-2, -2), (-2, 2), (2, -2), (2, 2)]
       
        for dr, dc in directions:
            new_row, new_col = piece.row + dr, piece.col + dc
           
            # 检查是否过河
            if piece.color == 'red' and new_row < 5:
                continue
            elif piece.color == 'black' and new_row > 4:
                continue
           
            # 检查象眼
            mid_row = (piece.row + new_row) // 2
            mid_col = (piece.col + new_col) // 2
            if self.get_piece_at(mid_row, mid_col):
                continue
           
            target = self.get_piece_at(new_row, new_col)
            if not target or target.color != piece.color:
                moves.append((new_row, new_col))
       
        return moves
   
    def get_knight_moves(self, piece):
        """获取马的移动"""
        moves = []
        knight_moves = [
            (-2, -1), (-2, 1), (-1, -2), (-1, 2),
            (1, -2), (1, 2), (2, -1), (2, 1)
        ]
       
        for dr, dc in knight_moves:
            new_row, new_col = piece.row + dr, piece.col + dc
           
            # 检查马腿
            if abs(dr) == 2:
                # 上下移动,检查中间的行
                mid_row = piece.row + (dr // 2)
                if self.get_piece_at(mid_row, piece.col):
                    continue
            else:
                # 左右移动,检查中间的列
                mid_col = piece.col + (dc // 2)
                if self.get_piece_at(piece.row, mid_col):
                    continue
           
            target = self.get_piece_at(new_row, new_col)
            if not target or target.color != piece.color:
                moves.append((new_row, new_col))
       
        return moves
   
    def get_rook_moves(self, piece):
        """获取车的移动"""
        moves = []
        directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
       
        for dr, dc in directions:
            for distance in range(1, 10):
                new_row = piece.row + dr * distance
                new_col = piece.col + dc * distance
               
                if not (0 <= new_row < 10 and 0 <= new_col < 9):
                    break
               
                target = self.get_piece_at(new_row, new_col)
                if target:
                    if target.color != piece.color:
                        moves.append((new_row, new_col))
                    break
                else:
                    moves.append((new_row, new_col))
       
        return moves
   
    def get_cannon_moves(self, piece):
        """获取炮的移动"""
        moves = []
        directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
       
        for dr, dc in directions:
            jumped = False
            for distance in range(1, 10):
                new_row = piece.row + dr * distance
                new_col = piece.col + dc * distance
               
                if not (0 <= new_row < 10 and 0 <= new_col < 9):
                    break
               
                target = self.get_piece_at(new_row, new_col)
                if not jumped:
                    if not target:
                        moves.append((new_row, new_col))
                    else:
                        jumped = True
                else:
                    if target:
                        if target.color != piece.color:
                            moves.append((new_row, new_col))
                        break
       
        return moves
   
    def get_pawn_moves(self, piece):
        """获取兵/卒的移动"""
        moves = []
       
        if piece.color == 'red':
            # 红兵向前(向上)
            if piece.row > 0:
                moves.append((piece.row - 1, piece.col))
           
            # 过河后可以左右移动
            if piece.row <= 4:
                if piece.col > 0:
                    moves.append((piece.row, piece.col - 1))
                if piece.col < 8:
                    moves.append((piece.row, piece.col + 1))
        else:
            # 黑卒向前(向下)
            if piece.row < 9:
                moves.append((piece.row + 1, piece.col))
           
            # 过河后可以左右移动
            if piece.row >= 5:
                if piece.col > 0:
                    moves.append((piece.row, piece.col - 1))
                if piece.col < 8:
                    moves.append((piece.row, piece.col + 1))
       
        # 过滤无效移动
        valid_moves = []
        for row, col in moves:
            target = self.get_piece_at(row, col)
            if not target or target.color != piece.color:
                valid_moves.append((row, col))
       
        return valid_moves
   
    def is_safe_move(self, piece, to_row, to_col):
        """检查移动后是否会将军自己"""
        # 保存当前状态
        original_piece = self.get_piece_at(to_row, to_col)
       
        # 临时执行移动
        self.board[piece.row][piece.col] = None
        self.board[to_row][to_col] = piece
        old_row, old_col = piece.row, piece.col
        piece.row, piece.col = to_row, to_col
       
        # 检查是否将军
        is_check = self.is_in_check(piece.color)
       
        # 恢复状态
        self.board[old_row][old_col] = piece
        self.board[to_row][to_col] = original_piece
        piece.row, piece.col = old_row, old_col
       
        return not is_check
   
    def is_in_check(self, color):
        """检查指定颜色是否被将军"""
        # 找到将/帅的位置
        king_pos = None
        king_name = '帥' if color == 'red' else '将'
       
        for row in range(10):
            for col in range(9):
                piece = self.board[row][col]
                if piece and piece.color == color and piece.name == king_name:
                    king_pos = (row, col)
                    break
            if king_pos:
                break
       
        if not king_pos:
            return False
       
        # 检查是否有敌方棋子可以攻击将/帅
        for row in range(10):
            for col in range(9):
                piece = self.board[row][col]
                if piece and piece.color != color:
                    moves = self.get_valid_moves(piece)
                    if king_pos in moves:
                        return True
       
        return False
   
    def move_piece(self, from_row, from_col, to_row, to_col):
        """移动棋子"""
        piece = self.get_piece_at(from_row, from_col)
        if not piece or piece.color != self.current_player:
            return False
       
        # 检查是否为合法移动
        valid_moves = self.get_valid_moves(piece)
        if (to_row, to_col) not in valid_moves:
            return False
       
        # 记录移动历史(用于悔棋)
        target_piece = self.get_piece_at(to_row, to_col)
        self.move_history.append({
            'from': (from_row, from_col),
            'to': (to_row, to_col),
            'piece': piece,
            'captured': target_piece
        })
       
        # 执行移动
        self.board[from_row][from_col] = None
        self.board[to_row][to_col] = piece
        piece.row, piece.col = to_row, to_col
       
        # 检查是否将军对方
        opponent_color = 'black' if self.current_player == 'red' else 'red'
        if self.is_in_check(opponent_color):
            # 检查是否将死
            if self.is_checkmate(opponent_color):
                self.game_over = True
                self.winner = self.current_player
       
        # 切换玩家
        self.current_player = opponent_color
       
        return True
   
    def is_checkmate(self, color):
        """检查是否将死"""
        # 获取所有己方棋子的所有可能移动
        for row in range(10):
            for col in range(9):
                piece = self.board[row][col]
                if piece and piece.color == color:
                    moves = self.get_valid_moves(piece)
                    for move in moves:
                        # 尝试移动
                        original_target = self.get_piece_at(move[0], move[1])
                        self.board[row][col] = None
                        self.board[move[0]][move[1]] = piece
                        old_row, old_col = piece.row, piece.col
                        piece.row, piece.col = move[0], move[1]
                       
                        # 检查是否解除将军
                        still_in_check = self.is_in_check(color)
                       
                        # 恢复状态
                        self.board[old_row][old_col] = piece
                        self.board[move[0]][move[1]] = original_target
                        piece.row, piece.col = old_row, old_col
                       
                        if not still_in_check:
                            return False
       
        return True
   
    def undo_move(self):
        """悔棋"""
        if not self.move_history:
            return False
       
        last_move = self.move_history.pop()
       
        # 恢复棋子
        piece = last_move['piece']
        from_row, from_col = last_move['from']
        to_row, to_col = last_move['to']
        captured = last_move['captured']
       
        # 移动回原位
        self.board[to_row][to_col] = captured
        self.board[from_row][from_col] = piece
        piece.row, piece.col = from_row, from_col
       
        # 切换回上一个玩家
        self.current_player = 'red' if self.current_player == 'black' else 'black'
        self.game_over = False
        self.winner = None
       
        return True
   
    def get_board_copy(self):
        """获取棋盘副本"""
        new_game = ChessGame()
        new_game.board = [[None for _ in range(9)] for _ in range(10)]
       
        for row in range(10):
            for col in range(9):
                piece = self.board[row][col]
                if piece:
                    new_game.board[row][col] = ChessPiece(piece.name, piece.color, row, col)
       
        new_game.current_player = self.current_player
        new_game.game_over = self.game_over
        new_game.winner = self.winner
       
        return new_game
   
    def evaluate_board(self):
        """评估棋盘状态"""
        if self.game_over:
            if self.winner == 'red':
                return -10000  # 红方获胜
            else:
                return 10000   # 黑方获胜
       
        score = 0
       
        # 计算棋子价值
        for row in range(10):
            for col in range(9):
                piece = self.board[row][col]
                if piece:
                    value = piece.value
                   
                    # 根据位置调整价值
                    position_bonus = self.get_position_bonus(piece)
                    value += position_bonus
                   
                    if piece.color == 'red':
                        score -= value  # 红方棋子对AI来说是负分
                    else:
                        score += value  # 黑方棋子对AI来说是正分
       
        return score
   
    def get_position_bonus(self, piece):
        """获取位置加成"""
        # 简单的棋盘位置价值表
        position_values = {
            '将': [
                [0, 0, 0, 1, 1, 1, 0, 0, 0],
                [0, 0, 0, 2, 2, 2, 0, 0, 0],
                [0, 0, 0, 3, 3, 3, 0, 0, 0],
                [0, 0, 0, 0, 0, 0, 0, 0, 0],
                [0, 0, 0, 0, 0, 0, 0, 0, 0],
                [0, 0, 0, 0, 0, 0, 0, 0, 0],
                [0, 0, 0, 0, 0, 0, 0, 0, 0],
                [0, 0, 0, 0, 0, 0, 0, 0, 0],
                [0, 0, 0, 0, 0, 0, 0, 0, 0],
                [0, 0, 0, 0, 0, 0, 0, 0, 0]
            ],
            '车': [
                [6, 5, 4, 3, 2, 3, 4, 5, 6],
                [6, 5, 4, 3, 2, 3, 4, 5, 6],
                [7, 6, 5, 4, 3, 4, 5, 6, 7],
                [7, 7, 6, 5, 4, 5, 6, 7, 7],
                [8, 8, 7, 6, 5, 6, 7, 8, 8],
                [8, 8, 7, 6, 5, 6, 7, 8, 8],
                [7, 7, 6, 5, 4, 5, 6, 7, 7],
                [7, 6, 5, 4, 3, 4, 5, 6, 7],
                [6, 5, 4, 3, 2, 3, 4, 5, 6],
                [6, 5, 4, 3, 2, 3, 4, 5, 6]
            ]
        }
       
        # 简化版本:给中心位置加成
        row, col = piece.row, piece.col
        center_distance = abs(row - 4.5) + abs(col - 4)
       
        if piece.name in ["车", "車", "马", "馬", "炮"]:
            return 10 - center_distance
        elif piece.name in ["兵", "卒"]:
            # 兵过河有加成
            if piece.color == 'red' and row < 5:
                return 20
            elif piece.color == 'black' and row > 4:
                return 20
       
        return 0

3. AI引擎文件 (ai_engine.py)

import random
import copy

class ChessAI:
    def __init__(self):
        self.nodes_evaluated = 0
   
    def get_best_move(self, game, depth):
        """获取最佳移动"""
        self.nodes_evaluated = 0
       
        # 获取所有可能移动
        moves = self.get_all_moves(game)
       
        if not moves:
            return None
       
        # 根据难度选择算法
        if depth == 1:
            # 初级:随机移动,但有基本策略
            return self.get_easy_move(game, moves)
        elif depth == 2:
            # 中级:简单的Minimax搜索
            best_move = None
            best_value = -float('inf')
           
            for move in moves:
                # 创建游戏副本
                game_copy = game.get_board_copy()
                from_pos, to_pos = move
               
                # 执行移动
                game_copy.move_piece(from_pos[0], from_pos[1], to_pos[0], to_pos[1])
               
                # 评估局面
                value = self.evaluate_position(game_copy)
               
                if value > best_value:
                    best_value = value
                    best_move = move
           
            return best_move
        else:
            # 高级:带Alpha-Beta剪枝的Minimax
            best_move = None
            best_value = -float('inf')
            alpha = -float('inf')
            beta = float('inf')
           
            for move in moves:
                game_copy = game.get_board_copy()
                from_pos, to_pos = move
                game_copy.move_piece(from_pos[0], from_pos[1], to_pos[0], to_pos[1])
               
                value = self.minimax(game_copy, depth-1, False, alpha, beta)
               
                if value > best_value:
                    best_value = value
                    best_move = move
               
                alpha = max(alpha, best_value)
                if beta <= alpha:
                    break
           
            print(f"AI评估了 {self.nodes_evaluated} 个节点")
            return best_move
   
    def get_easy_move(self, game, moves):
        """初级难度:随机移动但有基本策略"""
        # 优先吃子
        capture_moves = []
        for move in moves:
            from_pos, to_pos = move
            target = game.get_piece_at(to_pos[0], to_pos[1])
            if target:
                # 计算价值差
                source_piece = game.get_piece_at(from_pos[0], from_pos[1])
                if source_piece and target:
                    if target.value >= source_piece.value:
                        capture_moves.append(move)
       
        if capture_moves:
            return random.choice(capture_moves)
       
        # 如果没有好的吃子,随机移动
        return random.choice(moves)
   
    def minimax(self, game, depth, maximizing_player, alpha, beta):
        """Minimax算法"""
        self.nodes_evaluated += 1
       
        # 达到深度限制或游戏结束
        if depth == 0 or game.game_over:
            return game.evaluate_board()
       
        moves = self.get_all_moves(game)
       
        if maximizing_player:
            max_eval = -float('inf')
            for move in moves:
                game_copy = game.get_board_copy()
                from_pos, to_pos = move
                game_copy.move_piece(from_pos[0], from_pos[1], to_pos[0], to_pos[1])
               
                eval = self.minimax(game_copy, depth-1, False, alpha, beta)
                max_eval = max(max_eval, eval)
                alpha = max(alpha, eval)
               
                if beta <= alpha:
                    break
           
            return max_eval
        else:
            min_eval = float('inf')
            for move in moves:
                game_copy = game.get_board_copy()
                from_pos, to_pos = move
                game_copy.move_piece(from_pos[0], from_pos[1], to_pos[0], to_pos[1])
               
                eval = self.minimax(game_copy, depth-1, True, alpha, beta)
                min_eval = min(min_eval, eval)
                beta = min(beta, eval)
               
                if beta <= alpha:
                    break
           
            return min_eval
   
    def get_all_moves(self, game):
        """获取所有可能的移动"""
        moves = []
       
        for row in range(10):
            for col in range(9):
                piece = game.get_piece_at(row, col)
                if piece and piece.color == game.current_player:
                    piece_moves = game.get_valid_moves(piece)
                    for move in piece_moves:
                        moves.append(((row, col), move))
       
        # 随机排序以减少搜索路径依赖性
        random.shuffle(moves)
        return moves
   
    def evaluate_position(self, game):
        """评估局面(中级AI使用)"""
        score = game.evaluate_board()
       
        # 添加额外的评估因素
        if game.current_player == 'black':  # AI是黑方
            # 控制中心
            center_control = self.calculate_center_control(game, 'black')
            score += center_control * 5
           
            # 棋子活跃度
            mobility = self.calculate_mobility(game, 'black')
            score += mobility * 2
           
            # 将的安全度
            king_safety = self.calculate_king_safety(game, 'black')
            score += king_safety * 10
       
        return score
   
    def calculate_center_control(self, game, color):
        """计算中心控制"""
        center_positions = [(4, 4), (4, 5), (5, 4), (5, 5)]
        control = 0
       
        for row, col in center_positions:
            piece = game.get_piece_at(row, col)
            if piece:
                if piece.color == color:
                    control += 1
                else:
                    control -= 1
       
        return control
   
    def calculate_mobility(self, game, color):
        """计算棋子活跃度"""
        mobility = 0
       
        for row in range(10):
            for col in range(9):
                piece = game.get_piece_at(row, col)
                if piece and piece.color == color:
                    moves = game.get_valid_moves(piece)
                    mobility += len(moves)
       
        return mobility
   
    def calculate_king_safety(self, game, color):
        """计算将的安全度"""
        # 找到将的位置
        king_name = '将' if color == 'black' else '帥'
        king_pos = None
       
        for row in range(10):
            for col in range(9):
                piece = game.get_piece_at(row, col)
                if piece and piece.color == color and piece.name == king_name:
                    king_pos = (row, col)
                    break
            if king_pos:
                break
       
        if not king_pos:
            return -100
       
        # 检查将周围有多少保护棋子
        safety = 0
        king_row, king_col = king_pos
       
        # 检查周围的保护
        for dr in [-1, 0, 1]:
            for dc in [-1, 0, 1]:
                if dr == 0 and dc == 0:
                    continue
               
                new_row, new_col = king_row + dr, king_col + dc
                if 0 <= new_row < 10 and 0 <= new_col < 9:
                    piece = game.get_piece_at(new_row, new_col)
                    if piece and piece.color == color:
                        safety += 1
       
        return safety

4. 依赖文件 (requirements.txt)

pygame==2.5.2
pyinstaller==6.2.0

5. 打包配置文件 (setup.py)

from setuptools import setup

setup(
    name="ChineseChess",
    version="1.0.0",
    description="中国象棋人机对战游戏",
    author="Your Name",
    packages=["."],
    install_requires=[
        "pygame>=2.5.0",
    ],
    classifiers=[
        "Development Status :: 4 - Beta",
        "Intended Audience :: End Users/Desktop",
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python :: 3",
        "Programming Language :: Python :: 3.7",
        "Programming Language :: Python :: 3.8",
        "Programming Language :: Python :: 3.9",
        "Programming Language :: Python :: 3.10",
    ],
)

打包成EXE文件

方法1:使用PyInstaller(推荐)

1. 安装PyInstaller:

pip install pyinstaller

2. 创建打包配置文件(保存为 build_exe.py ):

import PyInstaller.__main__
import os

# 清理之前的构建
def clean_build():
    build_dirs = ['build', 'dist']
    for dir_name in build_dirs:
        if os.path.exists(dir_name):
            import shutil
            shutil.rmtree(dir_name)
            print(f"已删除 {dir_name} 目录")

clean_build()

# PyInstaller配置
args = [
    'main.py',  # 主文件
    '--name=ChineseChess',  # 程序名称
    '--onefile',  # 打包成单个exe文件
    '--windowed',  # 不显示控制台窗口
    '--icon=icon.ico',  # 图标文件(可选)
    '--add-data=assets;assets',  # 包含资源文件夹
    '--clean',  # 清理临时文件
    '--noconfirm',  # 覆盖输出目录不提示
]

# 运行PyInstaller
PyInstaller.__main__.run(args)

3. 运行打包命令:

# 方法1:直接使用pyinstaller命令
pyinstaller --onefile --windowed --name="中国象棋" main.py

# 方法2:使用配置文件
python build_exe.py

4. 自定义图标(可选):
1. 准备一个 icon.ico 图标文件
2. 在打包命令中添加: --icon=icon.ico 

方法2:使用cx_Freeze

1. 安装cx_Freeze:

pip install cx-freeze

2. 创建setup_cx.py:

from cx_Freeze import setup, Executable
import sys

# Dependencies are automatically detected, but it might need fine tuning.
build_exe_options = {
    "packages": ["pygame"],
    "excludes": ["tkinter"],
    "include_files": ["assets/"],  # 包含资源文件夹
}

# GUI applications require a different base on Windows
base = None
if sys.platform == "win32":
    base = "Win32GUI"

setup(
    name="中国象棋",
    version="1.0",
    description="中国象棋人机对战游戏",
    options={"build_exe": build_exe_options},
    executables=[Executable("main.py", base=base, target_name="ChineseChess.exe")]
)

3. 运行打包:

python setup_cx.py build

方法3:使用Nuitka(生成更高效的exe)

1. 安装Nuitka:

pip install nuitka

2. 打包命令:

nuitka --standalone --onefile --windows-disable-console --enable-plugin=pygame --output-dir=dist main.py

游戏使用说明

功能特点:

1. 三种难度级别:
初级:AI随机移动,偶尔有基本策略
中级:使用简单评估函数选择最佳移动
高级:使用Minimax算法进行深度搜索
2. 游戏功能:
完整的中国象棋规则实现
人机对战模式
悔棋功能
游戏状态显示
音效(需添加音效文件)
3. 操作方式:
鼠标点击选择棋子
再次点击目标位置移动
R键:重新开始游戏
ESC键:返回主菜单

运行要求:

Windows 7/8/10/11
Python 3.7+(如果运行源码)
显卡支持OpenGL 2.0+


这个完整的中国象棋游戏包含了所有必要功能,并提供了三种不同难度的AI。您可以直接运行源码或打包成独立的.exe文件分发。

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-02-09 02:06:33 HTTP/2.0 GET : https://f.mffb.com.cn/a/461500.html
  2. 运行时间 : 0.089567s [ 吞吐率:11.16req/s ] 内存消耗:4,725.53kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=1ad38894892c9e06d2b7d60aad64ae68
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000603s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000874s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000287s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000396s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000614s ]
  6. SELECT * FROM `set` [ RunTime:0.000259s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000670s ]
  8. SELECT * FROM `article` WHERE `id` = 461500 LIMIT 1 [ RunTime:0.000584s ]
  9. UPDATE `article` SET `lasttime` = 1770573993 WHERE `id` = 461500 [ RunTime:0.010656s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 65 LIMIT 1 [ RunTime:0.002883s ]
  11. SELECT * FROM `article` WHERE `id` < 461500 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000657s ]
  12. SELECT * FROM `article` WHERE `id` > 461500 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000533s ]
  13. SELECT * FROM `article` WHERE `id` < 461500 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.006087s ]
  14. SELECT * FROM `article` WHERE `id` < 461500 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.001034s ]
  15. SELECT * FROM `article` WHERE `id` < 461500 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.001000s ]
0.091159s