import csv from collections import deque class TreeNode: def __init__(self): self.fa = None self.children = [] self.pos = None self.final_pos = None self.val = 0 self.id = 0 self.dp = 0 class SourceCollector: def __init__(self, filename=None, maze=None): self.filename = filename self.maze = maze self.start_pos = None self.end_pos = None self.path = [] self.node_path = [] self.boss_pos = None self.lock_pos = None # 添加资源收集统计 self.collected_resources = [] # 收集的资源详情 self.total_coins = 0 # 金币总价值 self.total_traps = 0 # 陷阱总损失 self.total_value = 0 # 总价值(金币-陷阱) if self.filename: self.maze = [] with open(f"{self.filename}",'r') as f: reader = csv.reader(f) for idx,row in enumerate(reader): t = [] for idy,i in enumerate(row): if i.startswith('b'): t.append('0') self.boss_pos = (idx,idy) elif i.startswith('l'): t.append('0') self.lock_pos = (idx,idy) else: t.append(i) self.maze.append(t) else: self.maze = maze self.rowNums = len(self.maze) self.colNums = len(self.maze[0]) for i in range(self.rowNums): for j in range(self.colNums): if self.maze[i][j] =='s': self.start_pos = (i,j) if self.maze[i][j] =='e': self.end_pos = (i,j) def dfs_show(self,u): if u.id != 0: print(f"id: {u.id} , fa:{u.fa.id} , val:{u.val} , pos:{u.pos}") else: print(f"id: {u.id} , val:{u.val} , pos:{u.pos}") for child in u.children: self.dfs_show(child) def build_a_tree(self): cnt = 0 root = TreeNode() root.pos = self.start_pos root.id = 0 root.val = 0 root.fa = None queue = deque([(self.start_pos[0], self.start_pos[1], root)]) st = [[False] * self.colNums for _ in range(self.rowNums)] st[self.start_pos[0]][self.start_pos[1]] = True dx = [-1, 0, 1, 0] dy = [0, -1, 0, 1] while queue: x, y, parent = queue.popleft() for i in range(4): nx, ny = x + dx[i], y + dy[i] if self.outofmap(nx, ny) or st[nx][ny]: continue if self.maze[nx][ny] != '1': st[nx][ny] = True new_node = TreeNode() new_node.pos = (nx, ny) new_node.fa = parent cnt+=1 new_node.id = cnt if self.maze[nx][ny].startswith('g'): new_node.val = int(self.maze[nx][ny][1:]) elif self.maze[nx][ny].startswith('t'): new_node.val =-1 *int(self.maze[nx][ny][1:]) parent.children.append(new_node) queue.append((nx, ny, new_node)) return root def outofmap(self,x,y): return x < 0 or y < 0 or x >= self.rowNums or y >= self.colNums def getlca(self,u, v): def get_path_to_root(node): path = [] while node: path.append(node) node = node.fa return path path_u = get_path_to_root(u) path_v = get_path_to_root(v) path_u.reverse() path_v.reverse() lca = None for i in range(min(len(path_u),len(path_v))): if path_u[i] == path_v[i]: lca = path_u[i] else: break if lca is None: return [] u_to_lca = [] node = u while node != lca: u_to_lca.append(node) node = node.fa lca_to_v = [] node_list = [] node = v while node != lca: node_list.append(node) node = node.fa node_list.append(lca) node_list.reverse() for node in node_list: lca_to_v.append(node) full_path = u_to_lca + lca_to_v[:-1] return full_path def dfs(self, sn): sn.dp = sn.val sn.final_pos = sn.pos sn.path = [sn] # 先对子节点全部深搜一遍,收集路径长度 children = sn.children[:] for child in children: self.dfs(child) children.sort(key=lambda c: len(c.path)) cur = None for idx, child in enumerate(children): if child.dp > 0: sn.dp += child.dp if cur is not None: sn.path.extend(self.getlca(sn.path[-1], child)) sn.path.extend(child.path) cur = child sn.final_pos = cur.final_pos def get_path(self): return self.path def bfs_path(self, start, end): """从start到end的最短路径(含首尾)""" from collections import deque n, m = self.rowNums, self.colNums visited = [[False]*m for _ in range(n)] prev = [[None]*m for _ in range(n)] q = deque([start]) visited[start[0]][start[1]] = True dx = [-1, 0, 1, 0] dy = [0, -1, 0, 1] while q: x, y = q.popleft() if (x, y) == end: break for i in range(4): nx, ny = x + dx[i], y + dy[i] if 0 <= nx < n and 0 <= ny < m and not visited[nx][ny]: if self.maze[nx][ny] != '1': visited[nx][ny] = True prev[nx][ny] = (x, y) q.append((nx, ny)) # 回溯路径 path = [] cur = end while cur and cur != start: path.append(cur) cur = prev[cur[0]][cur[1]] if cur == start: path.append(start) path.reverse() return path return [] def run(self): sn = self.build_a_tree() # self.dfs_show(sn) self.dfs(sn) self.path =[_.pos for _ in sn.path] for idx,item in enumerate(self.path): if idx > 0: if item == self.path[idx-1]: del self.path[idx] self.path.extend(self.bfs_path(self.path[-1],self.end_pos)) # 计算并打印资源总结 self.print_resource_summary() def output_list(self): copy_maze = self.maze for idx, (y, x) in enumerate(self.path): if copy_maze[y][x].startswith('s') | copy_maze[y][x].startswith('e'): continue if copy_maze[y][x].startswith('g') | copy_maze[y][x].startswith('t'): copy_maze[y][x] = f"{copy_maze[y][x]}p{idx}" continue copy_maze[y][x] = f"p{idx}" return copy_maze def calculate_resources(self): """计算路径上收集到的资源总量""" self.collected_resources = [] self.total_coins = 0 self.total_traps = 0 self.total_value = 0 visited_positions = set() # 避免重复计算同一位置的资源 for step, (y, x) in enumerate(self.path): if (y, x) in visited_positions: continue visited_positions.add((y, x)) cell = self.maze[y][x] if cell.startswith('g'): # 金币 try: coin_value = int(cell[1:]) self.total_coins += coin_value self.total_value += coin_value self.collected_resources.append({ 'type': 'coin', 'position': (y, x), 'value': coin_value, 'step': step }) except ValueError: # 如果没有数值,默认为1 self.total_coins += 1 self.total_value += 1 self.collected_resources.append({ 'type': 'coin', 'position': (y, x), 'value': 1, 'step': step }) elif cell.startswith('t'): # 陷阱 try: trap_value = int(cell[1:]) self.total_traps += trap_value self.total_value -= trap_value self.collected_resources.append({ 'type': 'trap', 'position': (y, x), 'value': -trap_value, 'step': step }) except ValueError: # 如果没有数值,默认为1 self.total_traps += 1 self.total_value -= 1 self.collected_resources.append({ 'type': 'trap', 'position': (y, x), 'value': -1, 'step': step }) elif cell.startswith('b'): # Boss (记录但不计入总价值) self.collected_resources.append({ 'type': 'boss', 'position': (y, x), 'value': 0, 'step': step }) elif cell.startswith('l'): # 机关 (记录但不计入总价值) self.collected_resources.append({ 'type': 'mechanism', 'position': (y, x), 'value': 0, 'step': step }) def print_resource_summary(self): """打印资源收集总结""" print("\n" + "="*50) print("SourceCollector 资源收集总结") print("="*50) if not self.path: print("没有生成路径,无法统计资源") return # 先计算资源 self.calculate_resources() print(f"路径总长度: {len(self.path)} 步") print(f"收集资源总数: {len(self.collected_resources)} 个") print() # 按类型分组统计 coins = [r for r in self.collected_resources if r['type'] == 'coin'] traps = [r for r in self.collected_resources if r['type'] == 'trap'] bosses = [r for r in self.collected_resources if r['type'] == 'boss'] mechanisms = [r for r in self.collected_resources if r['type'] == 'mechanism'] print(f"金币收集: {len(coins)} 个,总价值: +{self.total_coins}") if coins: for coin in coins: print(f" 步骤{coin['step']}: 位置{coin['position']}, 价值+{coin['value']}") print(f"\n陷阱触发: {len(traps)} 个,总损失: -{self.total_traps}") if traps: for trap in traps: print(f" 步骤{trap['step']}: 位置{trap['position']}, 损失{trap['value']}") if bosses: print(f"\nBoss遭遇: {len(bosses)} 个") for boss in bosses: print(f" 步骤{boss['step']}: 位置{boss['position']}") if mechanisms: print(f"\n机关触发: {len(mechanisms)} 个") for mech in mechanisms: print(f" 步骤{mech['step']}: 位置{mech['position']}") print() print("-"*30) print(f"最终总价值: {self.total_value} (金币: +{self.total_coins}, 陷阱: -{self.total_traps})") print("-"*30) print("="*50) def get_resource_summary(self): """获取资源收集摘要(用于其他模块调用)""" if not hasattr(self, 'collected_resources') or not self.collected_resources: self.calculate_resources() return { 'path_length': len(self.path), 'total_resources': len(self.collected_resources), 'total_coins': self.total_coins, 'total_traps': self.total_traps, 'total_value': self.total_value, 'collected_resources': self.collected_resources.copy() } if __name__ == '__main__': obj = SourceCollector(filename="maze.csv") obj.run() path = obj.get_path() print("\n路径坐标序列:") for i, pos in enumerate(path): print(f"步骤{i}: {pos}") # 获取资源总结 summary = obj.get_resource_summary() print(f"\n最终资源总价值: {summary['total_value']}") # print(sn.pos) # pre = sn.pos # for _ in sn.dp_path: # dx,dy = _[0] - pre[0],_[1]-pre[1] # if dx > 0: # print("down") # elif dx < 0: # print("up") # elif dy > 0: # print("right") # elif dy < 0: # print("left") # pre = _