import random import csv import os class MazeGenerator: def __init__(self, size, filename, name="Default Maze"): # 迷宫基础元素 self.ROUTE = '0' self.WALL = '1' # 特殊元素 self.BOSS = 'b' self.START = 's' self.END = 'e' self.TRAP = 't' self.MECHANISM = 'l' self.GOLD = 'g' self.size = size self.maze = [] self.filename = filename self.name = name # 迷宫名称 self.special_elements = [] # 存储特殊元素的位置和值 def initialize_maze(self): """初始化迷宫,四周设置为墙""" self.maze = [[self.ROUTE for _ in range(self.size)] for _ in range(self.size)] for i in range(self.size): self.maze[0][i] = self.WALL self.maze[i][0] = self.WALL self.maze[self.size - 1][i] = self.WALL self.maze[i][self.size - 1] = self.WALL def create_maze(self, x1, y1, x2, y2): """递归分割法生成迷宫""" if x2 - x1 < 2 or y2 - y1 < 2: return x = x1 + 1 + random.randint(0, (x2 - x1 - 2)) y = y1 + 1 + random.randint(0, (y2 - y1 - 2)) # 画墙 for i in range(x1, x2 + 1): self.maze[i][y] = self.WALL for i in range(y1, y2 + 1): self.maze[x][i] = self.WALL # 递归分割四个区域 self.create_maze(x1, y1, x - 1, y - 1) self.create_maze(x + 1, y + 1, x2, y2) self.create_maze(x + 1, y1, x2, y - 1) self.create_maze(x1, y + 1, x - 1, y2) # 随机打通三面墙 r = [0, 0, 0, 0] r[random.randint(0, 3)] = 1 for i in range(4): if r[i] == 0: rx, ry = x, y if i == 0: # 上方 while True: rx = x1 + random.randint(0, (x - x1 - 1)) wall_count = sum([ (int)(self.maze[rx - 1][ry]), (int)(self.maze[rx + 1][ry]), (int)(self.maze[rx][ry - 1]), (int)(self.maze[rx][ry + 1]) ]) if wall_count <= 2 * (int)(self.WALL): break elif i == 1: # 右侧 while True: ry = y + 1 + random.randint(0, (y2 - y - 1)) wall_count = sum([ (int)(self.maze[rx - 1][ry]), (int)(self.maze[rx + 1][ry]), (int)(self.maze[rx][ry - 1]), (int)(self.maze[rx][ry + 1]) ]) if wall_count <= 2 * (int)(self.WALL): break elif i == 2: # 下方 while True: rx = x + 1 + random.randint(0, (x2 - x - 1)) wall_count = sum([ (int)(self.maze[rx - 1][ry]), (int)(self.maze[rx + 1][ry]), (int)(self.maze[rx][ry - 1]), (int)(self.maze[rx][ry + 1]) ]) if wall_count <= 2 * (int)(self.WALL): break elif i == 3: # 左侧 while True: ry = y1 + random.randint(0, (y - y1 - 1)) wall_count = sum([ (int)(self.maze[rx - 1][ry]), (int)(self.maze[rx + 1][ry]), (int)(self.maze[rx][ry - 1]), (int)(self.maze[rx][ry + 1]) ]) if wall_count <= 2 * (int)(self.WALL): break self.maze[rx][ry] = self.ROUTE def set_random_exits(self): """随机设置迷宫入口和出口""" available = self.get_available_cells() if len(available) < 2: raise ValueError("迷宫空间不足,无法设置随机出入口") start, end = random.sample(available, 2) self.maze[start[0]][start[1]] = self.START self.maze[end[0]][end[1]] = self.END self.special_elements.extend([(start[0], start[1], self.START), (end[0], end[1], self.END)]) def get_available_cells(self): """获取所有可通行单元格""" cells = [] for i in range(1, self.size - 1): for j in range(1, self.size - 1): if self.maze[i][j] == self.ROUTE: cells.append((i, j)) return cells def place_special_elements(self, boss_count=1, traps_range=(3, 8), mechanisms_range=(2, 6), skill_traps=5,gold_range=(3,8)): """放置特殊元素(支持技能触发陷阱)""" available = self.get_available_cells() random.shuffle(available) # 计算所需单元格数量 required = 2 + boss_count + random.randint(*traps_range) + random.randint(*mechanisms_range) + skill_traps + random.randint(*gold_range) if len(available) < required: raise ValueError(f"空间不足,需要{required}个单元格,实际可用{len(available)}") # 放置出入口 start, end = available.pop(), available.pop() self.special_elements.extend([(start[0], start[1], self.START), (end[0], end[1], self.END)]) self.maze[start[0]][start[1]] = self.START self.maze[end[0]][end[1]] = self.END # 放置BOSS for _ in range(boss_count): pos = available.pop() val = random.randint(50, 100) self.special_elements.append((pos[0], pos[1], f"{self.BOSS}{val}")) self.maze[pos[0]][pos[1]] = f"{self.BOSS}{val}" # 放置普通陷阱 traps = random.randint(*traps_range) for _ in range(traps): pos = available.pop() val = random.randint(5, 20) self.special_elements.append((pos[0], pos[1], f"{self.TRAP}{val}")) self.maze[pos[0]][pos[1]] = f"{self.TRAP}{val}" # 放置机关 mechanisms = random.randint(*mechanisms_range) for _ in range(mechanisms): pos = available.pop() val = random.randint(10, 30) self.special_elements.append((pos[0], pos[1], f"{self.MECHANISM}{val}")) self.maze[pos[0]][pos[1]] = f"{self.MECHANISM}{val}" # 放置金币 mechanisms = random.randint(*gold_range) for _ in range(mechanisms): pos = available.pop() val = random.randint(10, 30) self.special_elements.append((pos[0], pos[1], f"{self.GOLD}{val}")) self.maze[pos[0]][pos[1]] = f"{self.GOLD}{val}" def generate(self, seed=None, boss_count=1, traps_range=(3, 8), mechanisms_range=(2, 6), skill_traps=5): """生成迷宫主方法""" random.seed(seed or random.randint(0, 1000)) self.initialize_maze() self.create_maze(1, 1, self.size - 2, self.size - 2) self.place_special_elements(boss_count, traps_range, mechanisms_range, skill_traps) print(f"成功生成迷宫: {self.name}") def export_to_csv(self, filename): """导出迷宫到CSV文件""" try: with open(filename, 'w', newline='') as f: writer = csv.writer(f) for row in self.maze: writer.writerow(row) print(f"迷宫已导出至: {os.path.abspath(filename)}") except Exception as e: print(f"导出失败: {str(e)}") def read_from_csv(self): """从CSV读取迷宫数据""" try: with open(self.filename, 'r', newline='') as f: reader = csv.reader(f) self.maze = [list(map(self._parse_element, row)) for row in reader] self.size = len(self.maze) print(f"成功从{os.path.abspath(self.filename)}读取迷宫") return True except Exception as e: print(f"读取失败: {str(e)}") return False def _parse_element(self, elem): """解析CSV中的元素类型""" if elem == 's': return self.START if elem == 'e': return self.END if elem.startswith('b'): return self.BOSS if elem.startswith('t'): return self.TRAP if elem.startswith('l'): return self.MECHANISM if elem.startswith('g'): return self.GOLD return int(elem) def print_maze(self): """打印迷宫到控制台(带元素标识)""" symbols = { self.WALL: '■', self.ROUTE: '·', self.START: 'S', self.END: 'E', self.BOSS: 'B', self.TRAP: 'T', self.GOLD: 'G','|':'|','-':'—', } for row in self.maze: display = [] for cell in row: symbol = symbols.get(((str)(cell))[0], ((str)(cell))[0]) display.append(str(symbol)) print(' '.join(display)) def read_csv(self): l = [] with open(f'{self.filename}', 'r', newline='') as f: reader = csv.reader(f) for row in reader: l.append(row) return l def main(): # 示例1: 生成带技能陷阱的迷宫 generator = MazeGenerator( size=20, filename="dungeon_maze.csv", name="龙脊峡谷迷宫" ) generator.generate( seed=666, boss_count=2, traps_range=(5, 10), mechanisms_range=(3, 7), skill_traps=8 ) generator.print_maze() generator.export_to_csv() reader = MazeGenerator(size=1, filename="dungeon_maze.csv") if reader.read_from_csv(): print("\n读取的迷宫:") reader.print_maze() if __name__ == "__main__": main()