如何在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
相关产品推荐
相关产品推荐

