1、需要安装pygame
2、上下左右移动,空格实现物体所在位置到终点的路线,会有虚线绘制。
import pygame
import random
import math
# 迷宫单元格类
class Cell:
def __init__(self, x, y):
self.x = x
self.y = y
self.walls = {'top': True, 'right': True, 'bottom': True, 'left': True}
self.visited = False
self.is_obstacle = False
def draw(self, screen, cell_size):
x = self.x * cell_size
y = self.y * cell_size
if self.walls['top']:
pygame.draw.line(screen, (0, 0, 0), (x, y), (x + cell_size, y), 2)
if self.walls['right']:
pygame.draw.line(screen, (0, 0, 0), (x + cell_size, y), (x + cell_size, y + cell_size), 2)
if self.walls['bottom']:
pygame.draw.line(screen, (0, 0, 0), (x + cell_size, y + cell_size), (x, y + cell_size), 2)
if self.walls['left']:
pygame.draw.line(screen, (0, 0, 0), (x, y + cell_size), (x, y), 2)
if self.is_obstacle:
pygame.draw.rect(screen, (128, 128, 128), (x, y, cell_size, cell_size))
def check_neighbors(self, grid, cols, rows):
neighbors = []
if self.x > 0:
left = grid[self.y][self.x - 1]
if not left.visited:
neighbors.append(left)
if self.x < cols - 1:
right = grid[self.y][self.x + 1]
if not right.visited:
neighbors.append(right)
if self.y > 0:
top = grid[self.y - 1][self.x]
if not top.visited:
neighbors.append(top)
if self.y < rows - 1:
bottom = grid[self.y + 1][self.x]
if not bottom.visited:
neighbors.append(bottom)
if neighbors:
return random.choice(neighbors)
else:
return None
# 移除两个单元格之间的墙
def remove_walls(current, next_cell):
dx = current.x - next_cell.x
if dx == 1:
current.walls['left'] = False
next_cell.walls['right'] = False
elif dx == -1:
current.walls['right'] = False
next_cell.walls['left'] = False
dy = current.y - next_cell.y
if dy == 1:
current.walls['top'] = False
next_cell.walls['bottom'] = False
elif dy == -1:
current.walls['bottom'] = False
next_cell.walls['top'] = False
# 生成迷宫
def generate_maze(grid, cols, rows):
stack = []
current = grid[0][0]
current.visited = True
stack.append(current)
while stack:
current = stack[-1]
next_cell = current.check_neighbors(grid, cols, rows)
if next_cell:
next_cell.visited = True
stack.append(next_cell)
remove_walls(current, next_cell)
else:
stack.pop()
# 随机添加障碍物
def add_obstacles(grid, cols, rows, obstacle_ratio=0.3):
obstacle_cells = []
num_obstacles = int(cols * rows * obstacle_ratio)
while len(obstacle_cells) < num_obstacles:
x = random.randint(0, cols - 1)
y = random.randint(0, rows - 1)
if (x, y) not in [(0, 0), (cols - 1, rows - 1)] and not grid[y][x].is_obstacle:
grid[y][x].is_obstacle = True
obstacle_cells.append((x, y))
return obstacle_cells
# 检查从起点到终点是否有路径
def has_path(grid, start, end):
path = find_path(grid, start, end)
return bool(path)
# 移除障碍物直到有路径
def ensure_path_exists(grid, start, end, obstacle_cells):
random.shuffle(obstacle_cells)
while not has_path(grid, start, end) and obstacle_cells:
x, y = obstacle_cells.pop()
grid[y][x].is_obstacle = False
# 绘制迷宫
def draw_maze(screen, grid, cell_size, cols, rows):
for i in range(rows):
for j in range(cols):
grid[i][j].draw(screen, cell_size)
# 绘制起点和终点
def draw_start_end(screen, cell_size, start, end):
start_x = start[0] * cell_size + cell_size // 2
start_y = start[1] * cell_size + cell_size // 2
end_x = end[0] * cell_size + cell_size // 2
end_y = end[1] * cell_size + cell_size // 2
pygame.draw.circle(screen, (0, 255, 0), (start_x, start_y), cell_size // 3)
pygame.draw.circle(screen, (255, 0, 0), (end_x, end_y), cell_size // 3)
# 绘制移动的物体
def draw_player(screen, cell_size, player_pos):
player_x = player_pos[0] * cell_size + cell_size // 2
player_y = player_pos[1] * cell_size + cell_size // 2
pygame.draw.circle(screen, (0, 0, 255), (player_x, player_y), cell_size // 3)
# 检查是否可以移动
def can_move(grid, player_pos, direction):
x, y = player_pos
if direction == 'up':
return y > 0 and not grid[y][x].walls['top'] and not grid[y - 1][x].is_obstacle
elif direction == 'down':
return y < len(grid) - 1 and not grid[y][x].walls['bottom'] and not grid[y + 1][x].is_obstacle
elif direction == 'left':
return x > 0 and not grid[y][x].walls['left'] and not grid[y][x - 1].is_obstacle
elif direction == 'right':
return x < len(grid[0]) - 1 and not grid[y][x].walls['right'] and not grid[y][x + 1].is_obstacle
# 广度优先搜索找到最优路径
def find_path(grid, start, end):
queue = [(start, [start])]
visited = set()
while queue:
(x, y), path = queue.pop(0)
if (x, y) == end:
return path
if (x, y) not in visited:
visited.add((x, y))
if can_move(grid, (x, y), 'up'):
new_path = list(path)
new_path.append((x, y - 1))
queue.append(((x, y - 1), new_path))
if can_move(grid, (x, y), 'down'):
new_path = list(path)
new_path.append((x, y + 1))
queue.append(((x, y + 1), new_path))
if can_move(grid, (x, y), 'left'):
new_path = list(path)
new_path.append((x - 1, y))
queue.append(((x - 1, y), new_path))
if can_move(grid, (x, y), 'right'):
new_path = list(path)
new_path.append((x + 1, y))
queue.append(((x + 1, y), new_path))
return []
# 绘制虚线
def draw_dashed_line(screen, color, start_pos, end_pos, dash_length=5):
dx = end_pos[0] - start_pos[0]
dy = end_pos[1] - start_pos[1]
distance = math.sqrt(dx ** 2 + dy ** 2)
num_dashes = int(distance / dash_length)
for i in range(num_dashes):
if i % 2 == 0:
start = (start_pos[0] + dx * i / num_dashes, start_pos[1] + dy * i / num_dashes)
end = (start_pos[0] + dx * (i + 1) / num_dashes, start_pos[1] + dy * (i + 1) / num_dashes)
pygame.draw.line(screen, color, start, end, 2)
# 显示提示信息
def show_message(screen, message, font, color, position):
text = font.render(message, True, color)
screen.blit(text, position)
# 主函数
def main():
pygame.init()
cols = 35
rows = 35
cell_size = 20
width = cols * cell_size
height = rows * cell_size
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("Random Maze")
# 创建迷宫网格
grid = [[Cell(j, i) for j in range(cols)] for i in range(rows)]
# 生成迷宫
generate_maze(grid, cols, rows)
# 定义起点和终点
start = (0, 0)
end = (cols - 1, rows - 1)
# 随机添加障碍物
obstacle_cells = add_obstacles(grid, cols, rows)
# 确保有路径
ensure_path_exists(grid, start, end, obstacle_cells)
# 初始化玩家位置
player_pos = start
font = pygame.font.Font(None, 36)
success_text = font.render("Successfully!!!", True, (0, 255, 0))
help_text = font.render("", True, (0, 0, 0))
success = False
auto_move = False
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN and not success:
if event.key == pygame.K_UP:
if can_move(grid, player_pos, 'up'):
player_pos = (player_pos[0], player_pos[1] - 1)
elif event.key == pygame.K_DOWN:
if can_move(grid, player_pos, 'down'):
player_pos = (player_pos[0], player_pos[1] + 1)
elif event.key == pygame.K_LEFT:
if can_move(grid, player_pos, 'left'):
player_pos = (player_pos[0] - 1, player_pos[1])
elif event.key == pygame.K_RIGHT:
if can_move(grid, player_pos, 'right'):
player_pos = (player_pos[0] + 1, player_pos[1])
elif event.key == pygame.K_SPACE:
auto_move = True
path = find_path(grid, player_pos, end)
path_index = 0
screen.fill((255, 255, 255))
draw_maze(screen, grid, cell_size, cols, rows)
draw_start_end(screen, cell_size, start, end)
# 绘制路径
if 'path' in locals() and path:
for i in range(len(path) - 1):
start_point = (path[i][0] * cell_size + cell_size // 2, path[i][1] * cell_size + cell_size // 2)
end_point = (path[i + 1][0] * cell_size + cell_size // 2, path[i + 1][1] * cell_size + cell_size // 2)
draw_dashed_line(screen, (255, 0, 0), start_point, end_point)
draw_player(screen, cell_size, player_pos)
# 显示提示信息
show_message(screen, "", font, (0, 0, 0), (10, 10))
if auto_move and 'path' in locals() and path_index < len(path):
player_pos = path[path_index]
path_index += 1
if player_pos == end:
auto_move = False
if player_pos == end:
success = True
screen.blit(success_text,
(width // 2 - success_text.get_width() // 2, height // 2 - success_text.get_height() // 2))
pygame.display.flip()
pygame.time.delay(100)
pygame.quit()
if __name__ == "__main__":
main()