EG/plugins/user/pathfinding_algorithms/utils/demo_scenarios.py
2025-12-12 16:16:15 +08:00

257 lines
7.3 KiB
Python

"""
演示场景工具
提供各种路径规划演示场景的创建功能
"""
from typing import List, Tuple
import random
def create_simple_grid(rows: int, cols: int) -> List[List[int]]:
"""
创建简单的空网格
Args:
rows: 行数
cols: 列数
Returns:
网格数据
"""
return [[0 for _ in range(cols)] for _ in range(rows)]
def create_maze_grid(rows: int, cols: int) -> List[List[int]]:
"""
创建迷宫网格(使用深度优先搜索算法生成)
Args:
rows: 行数
cols: 列数
Returns:
迷宫网格数据
"""
# 确保行列数为奇数
if rows % 2 == 0:
rows += 1
if cols % 2 == 0:
cols += 1
# 初始化网格(全部设为墙)
grid = [[1 for _ in range(cols)] for _ in range(rows)]
# 使用深度优先搜索生成迷宫
stack = []
# 起点
start_row, start_col = 1, 1
grid[start_row][start_col] = 0
stack.append((start_row, start_col))
# 方向:上、右、下、左
directions = [(-2, 0), (0, 2), (2, 0), (0, -2)]
while stack:
current_row, current_col = stack[-1]
# 获取未访问的邻居
neighbors = []
for dr, dc in directions:
new_row, new_col = current_row + dr, current_col + dc
if 1 <= new_row < rows - 1 and 1 <= new_col < cols - 1:
if grid[new_row][new_col] == 1:
neighbors.append((new_row, new_col, dr // 2, dc // 2))
if neighbors:
# 随机选择一个邻居
new_row, new_col, wall_row, wall_col = random.choice(neighbors)
# 打通当前单元格和选中邻居之间的墙
grid[new_row][new_col] = 0
grid[current_row + wall_row][current_col + wall_col] = 0
# 将选中的邻居加入栈
stack.append((new_row, new_col))
else:
# 回溯
stack.pop()
return grid
def create_room_grid(rows: int, cols: int) -> List[List[int]]:
"""
创建房间网格(包含多个房间和走廊)
Args:
rows: 行数
cols: 列数
Returns:
房间网格数据
"""
grid = [[0 for _ in range(cols)] for _ in range(rows)]
# 添加一些房间(用障碍物围起来的空心矩形)
rooms = [
(2, 2, 5, 5), # (row, col, height, width)
(2, 10, 5, 5),
(10, 2, 5, 5),
(10, 10, 5, 5)
]
for room_row, room_col, room_height, room_width in rooms:
# 创建房间的墙
for r in range(room_row, min(room_row + room_height, rows)):
for c in range(room_col, min(room_col + room_width, cols)):
if (r == room_row or r == room_row + room_height - 1 or
c == room_col or c == room_col + room_width - 1):
if 0 <= r < rows and 0 <= c < cols:
grid[r][c] = 1
# 添加走廊连接房间
# 水平走廊
for c in range(7, 10):
if 4 < rows:
grid[4][c] = 0
# 垂直走廊
for r in range(7, 10):
if 4 < cols:
grid[r][4] = 0
if 12 < cols:
grid[r][12] = 0
return grid
def create_random_grid(rows: int, cols: int, obstacle_probability: float = 0.3) -> List[List[int]]:
"""
创建随机网格
Args:
rows: 行数
cols: 列数
obstacle_probability: 障碍物概率
Returns:
随机网格数据
"""
grid = []
for r in range(rows):
row = []
for c in range(cols):
if random.random() < obstacle_probability:
row.append(1) # 障碍物
else:
row.append(0) # 空地
grid.append(row)
return grid
def create_tunnel_grid(rows: int, cols: int) -> List[List[int]]:
"""
创建隧道网格(多条曲折的隧道)
Args:
rows: 行数
cols: 列数
Returns:
隧道网格数据
"""
grid = [[1 for _ in range(cols)] for _ in range(rows)] # 全部初始化为墙
# 创建主要隧道
# 水平隧道
tunnel_row = rows // 2
for c in range(1, cols - 1):
grid[tunnel_row][c] = 0
# 垂直隧道
tunnel_col = cols // 2
for r in range(1, rows - 1):
grid[r][tunnel_col] = 0
# 添加一些分支隧道
branch_positions = [(tunnel_row, tunnel_col // 4),
(tunnel_row, 3 * tunnel_col // 4),
(tunnel_row // 4, tunnel_col),
(3 * tunnel_row // 4, tunnel_col)]
for br, bc in branch_positions:
# 水平分支
for c in range(max(1, bc - 3), min(cols - 1, bc + 4)):
grid[br][c] = 0
# 垂直分支
for r in range(max(1, br - 3), min(rows - 1, br + 4)):
grid[r][bc] = 0
return grid
def get_scenario_names() -> List[str]:
"""
获取可用场景名称
Returns:
场景名称列表
"""
return ["simple", "maze", "room", "random", "tunnel"]
def create_scenario(scenario_name: str, rows: int = 20, cols: int = 20) -> List[List[int]]:
"""
创建指定场景
Args:
scenario_name: 场景名称
rows: 行数
cols: 列数
Returns:
网格数据
"""
if scenario_name == "simple":
return create_simple_grid(rows, cols)
elif scenario_name == "maze":
return create_maze_grid(rows, cols)
elif scenario_name == "room":
return create_room_grid(rows, cols)
elif scenario_name == "random":
return create_random_grid(rows, cols)
elif scenario_name == "tunnel":
return create_tunnel_grid(rows, cols)
else:
return create_simple_grid(rows, cols)
def get_suggested_start_goal(scenario_name: str, grid: List[List[int]]) -> Tuple[Tuple[int, int], Tuple[int, int]]:
"""
获取场景建议的起点和终点
Args:
scenario_name: 场景名称
grid: 网格数据
Returns:
(起点, 终点) 元组
"""
rows = len(grid)
cols = len(grid[0]) if rows > 0 else 0
if scenario_name == "simple":
return (0, 0), (rows - 1, cols - 1)
elif scenario_name == "maze":
return (1, 1), (rows - 2, cols - 2)
elif scenario_name == "room":
return (0, 0), (rows - 1, cols - 1)
elif scenario_name == "random":
# 寻找空地作为起点和终点
start = None
goal = None
for r in range(rows):
for c in range(cols):
if grid[r][c] == 0:
if start is None:
start = (r, c)
else:
goal = (r, c)
return start or (0, 0), goal or (rows - 1, cols - 1)
elif scenario_name == "tunnel":
return (1, 1), (rows - 2, cols - 2)
else:
return (0, 0), (rows - 1, cols - 1)