maze_python/tanxin.py
2025-06-26 20:15:59 +08:00

211 lines
6.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import math
from maze import *
import math
import math
class GreedyPlayer:
def __init__(self, map_data, start=None, end=None):
"""初始化GreedyPlayer对象"""
self.map_data = map_data
self.rows = len(map_data)
self.cols = len(map_data[0]) if self.rows > 0 else 0
self.start = start
self.end = end
self.path = []
self.total_reward = 0
self.visited = set()
self.marked_map = []
# 如果未指定起点和终点,自动查找
if not self.start or not self.end:
self._find_start_end()
def _find_start_end(self):
"""自动查找地图中的起点(s)和终点(e)"""
for y in range(self.rows):
for x in range(self.cols):
if self.map_data[y][x] == 's' or self.map_data[y][x] == 'S':
self.start = (x, y)
elif self.map_data[y][x] == 'e' or self.map_data[y][x] == 'E':
self.end = (x, y)
print(f"起点: {self.start}, 终点: {self.end}")
def get_visible_cells(self, x, y, visibility=1):
"""获取以(x,y)为中心的上下左右四个方向的单元格信息"""
visible = {}
# 只考虑上下左右四个方向dx或dy为±1另一个为0
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
for dx, dy in directions:
nx, ny = x + dx, y + dy
if 0 <= nx < self.cols and 0 <= ny < self.rows:
cell = self.map_data[ny][nx]
distance = 1 # 上下左右移动距离为1
visible[(nx, ny)] = (cell, distance)
return visible
def evaluate_cell(self, cell, distance):
"""评估单元格的价值,返回奖励/路径的比值"""
if cell == 's' or cell == 'e':
return 0 # 起点和终点不参与资源评估
if cell.startswith('t'):
try:
value = -int(cell[1:]) # t表示损失转为负值
return value / distance
except ValueError:
return 0
elif cell.startswith('g'):
try:
value = int(cell[1:]) # g表示收益转为正值
return value / distance
except ValueError:
return 0
return 0 # 0、l、b等不产生资源价值
def find_path(self):
"""基于贪心策略的路径规划(只能上下左右移动)"""
if not self.start or not self.end:
raise ValueError("地图中未找到起点或终点")
current = self.start
self.path = [current]
self.visited = {current}
self.total_reward = 0
while current != self.end:
x, y = current
visible = self.get_visible_cells(x, y)
best_cell = None
best_value = -float('inf')
for (nx, ny), (cell, distance) in visible.items():
# 跳过已访问的位置
if (nx, ny) in self.visited:
continue
# 只允许在0、t、g、l、b上行走
if cell not in ['0'] and not cell.startswith(('t', 'g', 'l', 'b')):
continue
# 评估单元格价值
value = self.evaluate_cell(cell, distance)
# 终点具有最高优先级
if cell == 'e':
value = float('inf')
# 选择贪心值最大的单元格
if value > best_value:
best_value = value
best_cell = (nx, ny)
# 无法找到可行路径
if best_cell is None:
print("无法找到通往终点的路径!")
break
# 更新当前位置和路径
current = best_cell
self.path.append(current)
self.visited.add(current)
# 更新总收益(跳过起点和终点)
if len(self.path) > 1 and len(self.path) < len(self.path) + 1:
cell = self.map_data[current[1]][current[0]]
if cell.startswith('t'):
self.total_reward -= int(cell[1:])
elif cell.startswith('g'):
self.total_reward += int(cell[1:])
self.add_path_to_map()
return self.path
def add_path_to_map(self):
"""在地图上标记路径,上下移动用|,左右移动用-"""
if not self.path:
print("没有路径可标记")
return
# 创建地图副本,避免修改原始地图
marked_map = [row.copy() for row in self.map_data]
# 标记路径点
for i, (x, y) in enumerate(self.path):
if marked_map[y][x] == 's':
marked_map[y][x] = 'S' # 标记起点
elif marked_map[y][x] == 'e':
marked_map[y][x] = 'E' # 标记终点
else:
marked_map[y][x] = '*' # 标记路径点
# 标记路径线(上下左右)
for i in range(len(self.path) - 1):
x1, y1 = self.path[i]
x2, y2 = self.path[i + 1]
# 左右移动
if x1 != x2 and y1 == y2:
start, end = (x1, x2) if x1 < x2 else (x2, x1)
for x in range(start, end + 1):
if marked_map[y1][x] not in ['S', 'E']:
marked_map[y1][x] = '-'
# 上下移动
elif y1 != y2 and x1 == x2:
start, end = (y1, y2) if y1 < y2 else (y2, y1)
for y in range(start, end + 1):
if marked_map[y][x1] not in ['S', 'E']:
marked_map[y][x1] = '|'
# 保存标记后的地图
self.marked_map = marked_map
return marked_map
def get_path(self):
"""返回找到的路径"""
return self.path
def get_total_reward(self):
"""返回总收益"""
return self.total_reward
# 使用示例
def main():
obj = MazeGenerator(20,'demo.csv',name="龙脊峡谷迷宫")
obj.generate(
seed=123,
boss_count=2,
traps_range=(5, 10),
mechanisms_range=(3, 7),
skill_traps=8
)
obj.export_to_csv()
map_data = obj.read_csv()
see = MazeGenerator(1,filename ='demo.csv')
see.read_from_csv()
see.print_maze()
player = GreedyPlayer(map_data)
player.find_path()
see.maze = player.marked_map
see.print_maze()
if __name__ == "__main__":
main()