211 lines
6.7 KiB
Python
211 lines
6.7 KiB
Python
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()
|
||
|
||
|
||
|
||
|