You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
6.0 KiB
170 lines
6.0 KiB
# -*- coding: utf-8 -*-
|
|
"""
|
|
Created on Sun May 11 10:32:04 2025
|
|
|
|
@author: Lenovo
|
|
"""
|
|
|
|
import numpy as np
|
|
import random
|
|
import tkinter as tk
|
|
from datetime import datetime
|
|
from tkinter import simpledialog, filedialog
|
|
from PIL import ImageGrab
|
|
|
|
|
|
class Maze:
|
|
def __init__(self, size=8, obstacle_prob=0.3):
|
|
self.size = size
|
|
self.obstacle_prob = obstacle_prob
|
|
self.maze = self.generate_maze()
|
|
self.path = []
|
|
|
|
def generate_maze(self):
|
|
maze = np.zeros((self.size, self.size), dtype=int)
|
|
for i in range(self.size):
|
|
for j in range(self.size):
|
|
if random.random() < self.obstacle_prob:
|
|
maze[i][j] = 1
|
|
maze[0][0] = 0
|
|
maze[self.size - 1][self.size - 1] = 0
|
|
return maze.tolist()
|
|
|
|
def is_valid_move(self, x, y):
|
|
return 0 <= x < self.size and 0 <= y < self.size and self.maze[x][y] == 0
|
|
|
|
def solve_maze(self, strategy):
|
|
self.path = []
|
|
solver = strategy(self)
|
|
return solver.solve()
|
|
|
|
|
|
class DepthFirstSearchSolver:
|
|
def __init__(self, maze):
|
|
self.maze = maze
|
|
self.path = []
|
|
|
|
def solve(self):
|
|
if self.dfs(0, 0):
|
|
return self.path
|
|
else:
|
|
return None
|
|
|
|
def dfs(self, x, y):
|
|
if (x, y) == (self.maze.size - 1, self.maze.size - 1):
|
|
self.path.append((x, y))
|
|
return True
|
|
|
|
directions = [(-1, 0), (1, 0), (0, -1), (0, 1), (-1, -1), (-1, 1), (1, -1), (1, 1)]
|
|
self.maze.maze[x][y] = 2 # Mark as visited (Previously path)
|
|
self.path.append((x, y))
|
|
|
|
for d in directions:
|
|
next_x, next_y = x + d[0], y + d[1]
|
|
if self.maze.is_valid_move(next_x, next_y) and self.maze.maze[next_x][next_y] == 0:
|
|
if self.dfs(next_x, next_y):
|
|
return True
|
|
|
|
self.path.pop()
|
|
return False
|
|
|
|
|
|
class MazeApp:
|
|
def __init__(self, root, maze_size=8, obstacle_prob=0.3):
|
|
self.root = root
|
|
self.maze_size = maze_size
|
|
self.obstacle_prob = obstacle_prob
|
|
self.maze = Maze(maze_size, obstacle_prob)
|
|
|
|
self.canvas = tk.Canvas(root, width=self.maze_size * 40, height=self.maze_size * 40)
|
|
self.canvas.pack()
|
|
self.button_frame = tk.Frame(root)
|
|
self.button_frame.pack()
|
|
|
|
self.solve_button = tk.Button(self.button_frame, text="寻找路径", command=self.solve_maze)
|
|
self.solve_button.grid(row=0, column=0)
|
|
|
|
self.new_maze_button = tk.Button(self.button_frame, text="生成新迷宫", command=self.generate_new_maze)
|
|
self.new_maze_button.grid(row=0, column=1)
|
|
|
|
self.custom_settings_button = tk.Button(self.button_frame, text="设置迷宫参数", command=self.custom_settings)
|
|
self.custom_settings_button.grid(row=0, column=2)
|
|
|
|
self.save_button = tk.Button(self.button_frame, text="保存迷宫", command=self.save_maze)
|
|
self.save_button.grid(row=0, column=3)
|
|
|
|
self.reset_path_button = tk.Button(self.button_frame, text="重新设置路径", command=self.reset_path)
|
|
self.reset_path_button.grid(row=0, column=4)
|
|
|
|
self.info_label = tk.Label(root, text="")
|
|
self.info_label.pack()
|
|
|
|
self.draw_maze()
|
|
|
|
def draw_maze(self, path=None):
|
|
self.canvas.delete("all")
|
|
self.canvas.config(width=self.maze_size * 40, height=self.maze_size * 40)
|
|
self.root.geometry(f"{self.maze_size * 40 + 40}x{self.maze_size * 40 + 80}") # Update window size
|
|
|
|
for i in range(self.maze_size):
|
|
for j in range(self.maze_size):
|
|
color = "white"
|
|
if self.maze.maze[i][j] == 1:
|
|
color = "grey"
|
|
elif self.maze.maze[i][j] == 2:
|
|
color = "light grey"
|
|
self.canvas.create_rectangle(j * 40, i * 40, (j + 1) * 40, (i + 1) * 40, fill=color)
|
|
|
|
if path:
|
|
for (x, y) in path:
|
|
self.canvas.create_rectangle(y * 40 + 10, x * 40 + 10, (y + 1) * 40 - 10, (x + 1) * 40 - 10,
|
|
fill="blue")
|
|
|
|
def solve_maze(self):
|
|
start_time = datetime.now()
|
|
solver = DepthFirstSearchSolver(self.maze)
|
|
path = self.maze.solve_maze(DepthFirstSearchSolver)
|
|
end_time = datetime.now()
|
|
time_taken = (end_time - start_time).total_seconds()
|
|
|
|
if path:
|
|
print("Path found:", path)
|
|
self.draw_maze(path)
|
|
self.info_label.config(text=f"Path found with length {len(path)} in {time_taken:.4f} seconds.")
|
|
else:
|
|
print("No path found")
|
|
self.info_label.config(text="No path found.")
|
|
|
|
def generate_new_maze(self):
|
|
self.maze = Maze(self.maze_size, self.obstacle_prob)
|
|
self.info_label.config(text="")
|
|
self.draw_maze()
|
|
|
|
def custom_settings(self):
|
|
new_size = simpledialog.askinteger("Maze Size", "Enter maze size:", minvalue=5, maxvalue=50)
|
|
new_prob = simpledialog.askfloat("Obstacle Probability", "Enter obstacle probability (0-1):", minvalue=0.0,
|
|
maxvalue=1.0)
|
|
if new_size and new_prob:
|
|
self.maze_size = new_size
|
|
self.obstacle_prob = new_prob
|
|
self.generate_new_maze()
|
|
|
|
def save_maze(self):
|
|
x = self.root.winfo_rootx() + self.canvas.winfo_x()
|
|
y = self.root.winfo_rooty() + self.canvas.winfo_y()
|
|
x1 = x + self.canvas.winfo_width()
|
|
y1 = y + self.canvas.winfo_height()
|
|
filename = filedialog.asksaveasfilename(defaultextension=".png",
|
|
filetypes=[("PNG files", "*.png"), ("All files", "*.*")])
|
|
if filename:
|
|
ImageGrab.grab().crop((x, y, x1, y1)).save(filename)
|
|
|
|
def reset_path(self):
|
|
self.info_label.config(text="")
|
|
self.draw_maze()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
root = tk.Tk()
|
|
app = MazeApp(root)
|
|
root.mainloop() |