""" 3x3视野贪心资源收集算法 该模块实现了一个基于3x3视野的贪心算法,用于在迷宫中收集资源。 算法特点: 1. 每次移动时只考虑当前位置周围3x3范围内的资源 2. 优先选择正价值资源(金币),如果没有则选择损失最小的负价值资源(陷阱) 3. 只能进行上下左右四个方向的移动 4. 当视野内没有资源时,会进行探索性移动 5. 避免无限循环,当连续多步无法找到新资源时会自动停止 使用方法: ```python from greedy_3x3_algorithm import Greedy3x3Algorithm # 创建迷宫(二维数组,[y][x]格式) maze = [ ['s', '0', 'g5', '1', 't3'], ['0', '1', '0', '0', 'g2'], ['g3', '0', '1', 't2', '0'], ['0', 't1', '0', '0', 'g4'], ['1', '0', 'g1', '0', 'e'] ] # 创建算法实例并运行 algorithm = Greedy3x3Algorithm(maze) result = algorithm.run() # 获取结果 print(f"总价值: {result['total_value']}") print(f"路径: {result['path']}") ``` """ import copy from collections import deque class Greedy3x3Algorithm: """ 3x3视野贪心资源收集算法 该算法在每个位置只考虑周围3x3范围内的资源,选择价值最高的资源进行收集。 如果视野内没有资源,则进行探索性移动。 """ def __init__(self, maze, start_pos=None, end_pos=None, debug=False): """ 初始化算法 Args: maze: 二维列表,表示迷宫地图 ([y][x]格式) start_pos: 起始位置 (x, y),默认自动寻找's' end_pos: 目标位置 (x, y),默认自动寻找'e' debug: 是否输出调试信息 """ self.original_maze = copy.deepcopy(maze) self.maze = copy.deepcopy(maze) self.rows = len(maze) self.cols = len(maze[0]) if self.rows > 0 else 0 self.debug = debug # 寻找起始位置和目标位置 self.start_pos = start_pos or self._find_position('s') self.end_pos = end_pos or self._find_position('e') if not self.start_pos: raise ValueError("无法找到起始位置 's'") if not self.end_pos: raise ValueError("无法找到目标位置 'e'") # 初始化状态 self.current_pos = self.start_pos self.path = [self.start_pos] self.collected_resources = [] self.total_value = 0 self.visited_resources = set() self.explored_positions = set([self.start_pos]) if self.debug: print(f"3x3视野贪心算法初始化") print(f"迷宫大小: {self.rows}x{self.cols}") print(f"起始位置: {self.start_pos}") print(f"目标位置: {self.end_pos}") def _find_position(self, target): """寻找地图中指定字符的位置,返回(x, y)格式""" for y in range(self.rows): for x in range(self.cols): if self.maze[y][x].lower() == target.lower(): return (x, y) return None def get_3x3_vision(self, pos): """ 获取以pos为中心的3x3视野范围内的所有单元格 Args: pos: 当前位置 (x, y) Returns: dict: {(x, y): cell_value} 形式的字典 """ x, y = pos vision = {} # 遍历3x3范围 for dx in range(-1, 2): for dy in range(-1, 2): new_x, new_y = x + dx, y + dy # 检查边界 if 0 <= new_x < self.cols and 0 <= new_y < self.rows: vision[(new_x, new_y)] = self.maze[new_y][new_x] return vision def get_adjacent_positions(self, pos): """ 获取当前位置的上下左右四个相邻位置 Args: pos: 当前位置 (x, y) Returns: list: 可移动的相邻位置列表 """ x, y = pos adjacent = [] # 上下左右四个方向 directions = [(0, -1), (0, 1), (-1, 0), (1, 0)] # 上、下、左、右 for dx, dy in directions: new_x, new_y = x + dx, y + dy # 检查边界和可移动性 if (0 <= new_x < self.cols and 0 <= new_y < self.rows and self._can_move_to((new_x, new_y))): adjacent.append((new_x, new_y)) return adjacent def _can_move_to(self, pos): """检查是否可以移动到指定位置""" x, y = pos cell = self.maze[y][x] return cell != '1' # 不能移动到墙壁 def _evaluate_resource_value(self, cell): """评估资源的价值""" if cell.startswith('g'): try: return int(cell[1:]) except ValueError: return 0 elif cell.startswith('t'): try: return -int(cell[1:]) except ValueError: return 0 else: return 0 def _find_best_resource_in_vision(self): """ 在3x3视野范围内找到价值最高的可到达资源 Returns: tuple: (最佳资源位置, 资源价值) 或 (None, 0) """ vision = self.get_3x3_vision(self.current_pos) adjacent_positions = self.get_adjacent_positions(self.current_pos) best_pos = None best_value = float('-inf') # 只考虑相邻且在视野内的位置 for pos in adjacent_positions: if pos in vision and pos not in self.visited_resources: cell = vision[pos] value = self._evaluate_resource_value(cell) if value != 0 and value > best_value: best_value = value best_pos = pos return best_pos, best_value if best_pos else 0 def _find_exploration_target(self): """当视野内没有资源时,寻找探索目标""" adjacent = self.get_adjacent_positions(self.current_pos) # 优先选择未探索的位置 unexplored = [pos for pos in adjacent if pos not in self.explored_positions] if unexplored: return unexplored[0] # 如果所有相邻位置都探索过,选择任意一个 if adjacent: return adjacent[0] return None def _collect_resource(self, pos): """收集指定位置的资源""" x, y = pos cell = self.maze[y][x] value = self._evaluate_resource_value(cell) if value != 0: self.collected_resources.append({ 'position': pos, 'type': cell, 'value': value }) self.total_value += value self.visited_resources.add(pos) if self.debug: print(f"收集资源: 位置{pos}, 类型{cell}, 价值{value}, 总价值{self.total_value}") def run(self, max_moves=1000, max_stuck=20): """ 运行3x3视野贪心资源收集算法 Args: max_moves: 最大移动步数,防止无限循环 max_stuck: 连续无资源的最大步数 Returns: dict: 包含路径、收集的资源等信息的结果字典 """ if self.debug: print("\\n开始3x3视野贪心资源收集...") moves = 0 stuck_count = 0 while moves < max_moves and stuck_count < max_stuck: moves += 1 # 在3x3视野内寻找最佳资源 best_resource_pos, best_value = self._find_best_resource_in_vision() if best_resource_pos is not None: if self.debug: print(f"第{moves}步: 发现视野内资源 位置{best_resource_pos}, 价值{best_value}") # 移动到资源位置并收集 self.current_pos = best_resource_pos self.path.append(best_resource_pos) self.explored_positions.add(best_resource_pos) self._collect_resource(best_resource_pos) stuck_count = 0 # 重置无资源计数 else: # 视野内没有资源,进行探索性移动 exploration_target = self._find_exploration_target() if exploration_target: if self.debug: print(f"第{moves}步: 视野内无资源,探索移动到 {exploration_target}") self.current_pos = exploration_target self.path.append(exploration_target) self.explored_positions.add(exploration_target) stuck_count += 1 else: if self.debug: print(f"第{moves}步: 无法进行任何移动,结束收集") break if self.debug: if moves >= max_moves: print(f"达到最大移动步数 {max_moves},结束收集") elif stuck_count >= max_stuck: print(f"连续 {max_stuck} 步未找到资源,结束收集") print("3x3视野资源收集完成!") return self._get_result() def _get_result(self): """获取算法执行结果""" return { 'path': self.path.copy(), 'path_yx_format': [(y, x) for (x, y) in self.path], # 兼容现有代码的(y,x)格式 'collected_resources': self.collected_resources.copy(), 'total_value': self.total_value, 'total_moves': len(self.path) - 1, 'resources_count': len(self.collected_resources), 'start_pos': self.start_pos, 'end_pos': self.end_pos, 'final_pos': self.current_pos, 'explored_positions_count': len(self.explored_positions), 'algorithm_name': '3x3视野贪心算法' } def get_marked_maze(self): """ 获取标记了路径的迷宫 Returns: list: 标记后的迷宫,S=起点, E=终点, *=已收集资源, .=路径 """ marked_maze = copy.deepcopy(self.original_maze) # 标记路径点 for i, (x, y) in enumerate(self.path): if (x, y) == self.start_pos: marked_maze[y][x] = 'S' # 起点 elif (x, y) == self.end_pos: marked_maze[y][x] = 'E' # 终点 elif (x, y) in [r['position'] for r in self.collected_resources]: marked_maze[y][x] = '*' # 已收集资源 else: marked_maze[y][x] = '.' # 路径点 return marked_maze def print_result(self): """打印算法执行结果""" result = self._get_result() print("\\n=== 3x3视野贪心算法执行结果 ===") print(f"起始位置: {result['start_pos']}") print(f"最终位置: {result['final_pos']}") print(f"总移动步数: {result['total_moves']}") print(f"探索位置数: {result['explored_positions_count']}") print(f"收集资源数量: {result['resources_count']}") print(f"资源总价值: {result['total_value']}") if result['collected_resources']: print("\\n收集的资源详情:") for i, resource in enumerate(result['collected_resources'], 1): print(f" {i}. 位置{resource['position']}: {resource['type']} (价值: {resource['value']})") else: print("\\n未收集到任何资源") # 显示标记后的迷宫 marked_maze = self.get_marked_maze() print("\\n标记路径后的迷宫:") print("S: 起点, E: 终点, *: 已收集资源, .: 路径") for row in marked_maze: print(' '.join(f"{cell:>2}" for cell in row)) def demo(): """演示函数""" # 创建示例迷宫 demo_maze = [ ['s', '0', 'g5', '1', 't3'], ['0', '1', '0', '0', 'g2'], ['g3', '0', '1', 't2', '0'], ['0', 't1', '0', '0', 'g4'], ['1', '0', 'g1', '0', 'e'] ] print("=== 3x3视野贪心算法演示 ===") print("迷宫说明:") print(" s: 起点, e: 终点") print(" g数字: 金币资源 (正收益)") print(" t数字: 陷阱资源 (负收益)") print(" 0: 可通行路径, 1: 墙壁") print("\\n原始迷宫:") for row in demo_maze: print(' '.join(f"{cell:>2}" for cell in row)) # 运行算法 algorithm = Greedy3x3Algorithm(demo_maze, debug=True) result = algorithm.run() # 打印结果 algorithm.print_result() return algorithm, result if __name__ == "__main__": demo()