You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Tkinter中将跳棋走法计算移至独立线程优化界面响应?

基于Tkinter的跳棋界面卡顿问题

我用Tkinter实现了跳棋游戏,尽管已经将电脑最优走法的计算逻辑移到独立线程中,但当电脑计算中等深度的最优走法时,界面仍会出现卡顿。如果不将计算移至独立线程,界面会直接无响应,但动画仍能播放。以下是关键实现代码:

def mouse_down(self, event: Event):
    '''鼠标按下事件'''
    x, y = (event.x - BOARD_BORDER) // CELL_SIZE, (event.y - BOARD_BORDER) // CELL_SIZE
    # 若点击点不在棋盘内
    if not (self.__field.is_within(x, y)): return
    if MULTIPLAYER:
        ...
    else:
        if not (self.__player_turn): return

        if (PLAYER_SIDE == SideType.WHITE):
            player_checkers = WHITE_CHECKERS
        elif (PLAYER_SIDE == SideType.BLACK):
            player_checkers = BLACK_CHECKERS
        else:
            return

        # 若点击玩家的棋子,则选中该棋子
        if (self.__field.type_at(x, y) in player_checkers):
            self.__selected_cell = Point(x, y)
            self.__draw()
        elif (self.__player_turn):
            move = Move(self.__selected_cell.x, self.__selected_cell.y, x, y)
            # 若点击可移动到的单元格
            if (move in self.__get_moves_list(PLAYER_SIDE)):
                self.__handle_player_turn(move)
                # 若当前非玩家回合,则切换至对手回合
                if not (self.__player_turn):
                    self.test_field = self.__field
                    self.handle_enemy_turn_async()
                ...

def handle_enemy_turn_async(game_instance):
    def run():
        game_instance.__handle_enemy_turn()

    threading.Thread(target=run).start()

def __handle_enemy_turn(self):
    '''处理对手(电脑)的走法'''
    self.__player_turn = False
    self.calc = True
    optimal_moves_list = self.__predict_optimal_moves(SideType.opposite(PLAYER_SIDE))
    self.calc = False
    for move in optimal_moves_list:
        self.__handle_move(self.__field, move)
    self.__player_turn = True
    self.__check_for_game_over()

def __predict_optimal_moves(self, side: SideType) -> list[Move]:
    '''预测最优走法'''
    best_result = 0
    optimal_moves = []
    self.test_field = Field.copy(self.__field)
    predicted_moves_list = self.__get_predicted_moves_list(side)
    if (predicted_moves_list):
        field_copy = Field.copy(self.__field)
        self.test_field = Field.copy(self.__field)
        field_copy_test = Field.copy(self.test_field)
        for moves in predicted_moves_list:
            for move in moves:
                self.__handle_move(self.test_field, move, draw=False)
            try:
                if (side == SideType.WHITE):
                    result = self.test_field.white_score / self.test_field.black_score
                elif (side == SideType.BLACK):
                    result = self.test_field.black_score / self.test_field.white_score
            except ZeroDivisionError:
                result = inf

            if (result > best_result):
                best_result = result
                optimal_moves.clear()
                optimal_moves.append(moves)
            elif (result == best_result):
                optimal_moves.append(moves)

            self.test_field = Field.copy(field_copy_test)

    optimal_move = []
    if (optimal_moves):
        # 过滤走法
        for move in choice(optimal_moves):
            if (side == SideType.WHITE and self.__field.type_at(move.from_x, move.from_y) in BLACK_CHECKERS):
                break
            elif (side == SideType.BLACK and self.__field.type_at(move.from_x, move.from_y) in WHITE_CHECKERS):
                break
            optimal_move.append(move)
    return optimal_move

def __get_predicted_moves_list(self, side: SideType, current_prediction_depth: int = 0,
                               all_moves_list: list[Move] = [], current_moves_list: list[Move] = [],
                               required_moves_list: list[Move] = []) -> list[Move]:
    '''预测所有可能的走法'''
    if (current_moves_list):
        all_moves_list.append(current_moves_list)
    else:
        all_moves_list.clear()

    if (required_moves_list):
        moves_list = required_moves_list
    else:
        now = False
        moves_list = self.__get_moves_list(side)

    if (moves_list and current_prediction_depth < MAX_DEPTH):
        field_copy = Field.copy(self.test_field)
        for move in moves_list:
            field_for_check = Field.copy(self.test_field)
            has_killed_checker = self.__handle_move(self.test_field, move, draw=False)
            required_moves_list = list(filter(
                lambda required_move: move.to_x == required_move.from_x and move.to_y == required_move.from_y,
                self.__get_required_moves_list(side, self.test_field)))
            # 若该棋子还有后续走法
            if (has_killed_checker and required_moves_list):
                self.__get_predicted_moves_list(side, current_prediction_depth, all_moves_list,
                                                current_moves_list + [move], required_moves_list)
            else:
                self.__get_predicted_moves_list(SideType.opposite(side), current_prediction_depth + 1,
                                                all_moves_list, current_moves_list + [move])

            self.test_field = Field.copy(field_copy)

    return all_moves_list

内容的提问来源于stack exchange,提问作者Poisk znaij

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 14:42:07