@[TOC]
说明
本文为2021 12 14 所著,实现语言为python。设计需求:
1.设计迷宫 2.让人物自动寻找迷宫出口 3.动态显示该过程 4.保存迷宫路径(这里只是简单的stdout)
功能说明
模块说明
函数接口参数说明
项目结构
算法实现
这个是重点,但还是比较基础的。至于具体实现原理,自行百度。
import copy
class ALgorithm:
@staticmethod
def DFSAutoFindingWay(maze_list_r,start,end_row,end_col):
def dfs(lst,maze_list_,row_,col_):
while lst:
now = lst[-1]
row, col = now
maze_list_[row][col] = 2
if (row == row_ and col == col_):
return lst
if (row + 1 < len(maze_list_) and maze_list_[row + 1][col] == 0):
lst.append((row + 1, col))
continue
elif (col + 1 < len(maze_list_[0]) and maze_list_[row][col + 1] == 0):
lst.append((row, col + 1))
continue
elif (row - 1 >= 0 and maze_list_[row - 1][col] == 0):
lst.append((row - 1, col))
continue
elif (col - 1 >= 0 and maze_list_[row][col - 1] == 0):
lst.append((row, col - 1))
continue
else:
lst.pop()
start = start
end_col = end_col
end_row = end_row
#一开始往下走
ways = [] #存储多条路径
has_way = len(end_row)
lst = [start]
for i in range(has_way):
maze_list_ = copy.deepcopy(maze_list_r)
zz = copy.deepcopy(lst)
res = dfs(zz,maze_list_,end_row[i],end_col[i])
ways.append(res)
if ways:
for i in range(has_way):
print("DFS搜索路径{}为{}".format(i,ways[i]))
return ways
else:
return []
@staticmethod
def BFSAutoFindingWay(maze_list,start,end_row,end_col):
pre_route = list() # 广度度搜索得到的节点
q = list() # 队列结构控制循环次数
xx = [0, 1, 0, -1] # 右移、下移、左移、上移
yy = [1, 0, -1, 0]
visited = list() # 记录节点是否已遍历
father = list() # 每一个pre_route节点的父节点
route = list()
maze_list = copy.deepcopy(maze_list)
def bfs(maze_list, x, y, m, n):
visited = [[0 for i in range(len(maze_list[0]))] for j in range(len(maze_list))]
visited[x][y] = 1 # 入口节点设置为已遍历
q.append([x, y])
while q: # 队列为空则结束循环
now = q.pop(0) # 移除队列头结点
maze_list[now[0]][now[1]] = 2
for i in range(4):
point = [now[0] + xx[i], now[1] + yy[i]] # 当前节点
if point[0] >= 0 and point[1] >= 0 and point[0] < len(maze_list) and point[1] < len(maze_list[0]) and visited[point[0]][point[1]] != 1 and maze_list[point[0]][point[1]]==0:
father.append(now)
visited[point[0]][point[1]] = 1
q.append(point)
pre_route.append(point)
if point[0] in m and point[1] in n:
return 1
return 0
def get_route(father, pre_route): # 输出最短迷宫路径
route = [pre_route[-1], father[-1]]
for i in range(len(pre_route) - 1, -1, -1): # 从后往前拿
if pre_route[i] == route[-1]:
route.append(father[i])
route.reverse()
return route
if bfs(maze_list,start[0],start[1],end_row,end_col)==1:
route=get_route(father,pre_route)
print("BFS最佳路径:",route)
return route
else:
return []
if __name__ == "__main__":
maze_list = [
[1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
[1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1],
[1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1],
[1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1],
[1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1],
[1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1],
[1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1]
]
# result = algorithm.DFSAutoFindingWay((0,5),[12],[7,9])
# print(result)
res = ALgorithm.BFSAutoFindingWay(maze_list,(0,5),[12,12],[9,7])
控制代码
from turtle import Turtle
import turtle
import time
from ALgorithm import ALgorithm
class Controller(Turtle):
def __init__(self,playper):
# 父类初始化
Turtle.__init__(self)
# 初始值设置
self.go_up = playper.go_up
self.go_down = playper.go_down
self.go_left = playper.go_left
self.go_right = playper.go_right
self.move = playper.move
self.maze_list = playper.maze_list
self.start = (playper.m,playper.n)
self.end_row = playper.end_m
self.end_col = playper.end_n
self.ALgorithm = ALgorithm
# 绘制控制器
self.hideturtle()
self.speed(0)
self.draw_btn('上', -15, 165)
self.draw_btn('下', -15, -135)
self.draw_btn('左', -165, 15)
self.draw_btn('右', 135, 15)
self.draw_btn("自动寻路DFS",-150,250)
self.draw_btn("自动寻路BFS", 60, 250)
self.draw_btn("重置",200,-220)
# 绑定点击事件
screen = self.getscreen()
screen.onclick(self.handlescreenclick)
def draw_btn(self, name, x, y):
self.penup()
self.goto(x, y)
self.begin_fill()
self.fillcolor('#ffffff')
for i in range(4):
self.forward(30)
self.right(90)
self.end_fill()
self.color('#000000')
self.goto(x + 7, y - 20)
self.write(name, font = ('SimHei', 12, 'bold'))
def autopathfindingB(self):
#自动寻路功能,也就是走迷宫功能
print("自动寻路BFS")
res = self.ALgorithm.BFSAutoFindingWay(self.maze_list,self.start,self.end_row,self.end_col)
for path in res:
m,n=path
time.sleep(0.5)
self.move(m,n)
pass
def autopathfindingD(self):
#自动寻路功能,也就是走迷宫功能
print("自动寻路DFS")
res2 = self.ALgorithm.DFSAutoFindingWay(self.maze_list,self.start,self.end_row,self.end_col)
for paths in res2:
for path in paths:
m,n=path
time.sleep(0.5)
self.move(m,n)
pass
def RestPlayes(self):
self.move(self.start[0],self.start[1])
#当点击事件发生时利用abs函数进行比较判断
def handlescreenclick(self, x, y):
if ( 220 < abs(y) < 250 ):
if(x>=-150 and x<-40 ):
self.autopathfindingD()
if(x>60 and x<160):
self.autopathfindingB()
if(x>200 and x<240):
self.RestPlayes()
else:
if y > 0 and abs(x) < y:
self.go_up()
if y < 0 and abs(x) < -y:
self.go_down()
if x < 0 and abs(y) < -x:
self.go_left()
if x > 0 and abs(y) < x:
self.go_right()
玩家代码
from turtle import Turtle
import turtle
import time
class Player(Turtle):
def __init__(self, maze_list, start_m, start_n, end_m, end_n):
# 父类初始化
Turtle.__init__(self)
# 初始的横纵坐标
self.m = start_m
self.n = start_n
# 终点的横纵坐标
self.end_m = end_m
self.end_n = end_n
# 迷宫地图
self.maze_list = maze_list
self.hideturtle()
self.speed(0)
self.penup()
# 玩家移到对应的位置
self.goto(self.n * 20 - 120, 120 - self.m * 20)
# 生成玩家
self.shape('turtle')
self.color('yellow')
# 玩家初始方向
self.setheading(270)
self.showturtle()
# 当抵达时
def reach_exit(self, m, n):
if m in self.end_m and n in self.end_n:
# 走出迷宫,显示'Pass it!'
text = turtle.Turtle()
text.hideturtle()
text.penup()
text.goto(-125, -10)
text.color('blue')
text.write('Pass it!', font=('SimHei', 48, 'bold'))
time.sleep(2)
text.clear()
# 定义玩家可移动的位置,即只允许在迷宫内的通道里移动
def canmove(self, m, n):
# 遇到0允许移动
return self.maze_list[m][n] == 0
# 玩家移动时位置发生的变化
def move(self, m, n):
self.m = m
self.n = n
self.goto(self.n * 20 - 120, 120 - self.m * 20)
self.reach_exit(m, n)
# 向上移动
def go_up(self):
if self.canmove(self.m - 1, self.n):
self.setheading(90)
self.move(self.m - 1, self.n)
# 向下移动
def go_down(self):
if self.canmove(self.m + 1, self.n):
self.setheading(270)
self.move(self.m + 1, self.n)
# 向左移动
def go_left(self):
if self.canmove(self.m, self.n - 1):
self.setheading(180)
self.move(self.m, self.n - 1)
# 向右移动
def go_right(self):
if self.canmove(self.m, self.n + 1):
self.setheading(0)
self.move(self.m, self.n + 1)
绘制迷宫
from turtle import Turtle
import turtle
# 设置游戏的窗口大小和背景颜色
turtle.screensize(800, 600, "white")
class Maze(Turtle):
size = 20 # 迷宫内一格墙的长宽
def __init__(self, maze_list):
# 需要先调用父类的初始化方法才能在初始化方法中调用父类的方法
Turtle.__init__(self)
self.maze_list = maze_list
# 为了加快绘图速度隐藏海龟,速度设为最快
self.hideturtle()
self.speed(-10)
self.draw_walls()
# 绘制迷宫内一格墙的过程
def draw_wall(self):
self.pendown()
self.begin_fill()
# 绘制墙的颜色
self.fillcolor('red')
# 首先画一个距离为20的横线,再向右旋转90度,循环4次形成方形
for i in range(4):
self.forward(self.size)
self.right(90)
self.end_fill()
self.penup()
# 绘制整个迷宫的墙
def draw_walls(self):
self.penup()
# 从 (-130, 130) 开始
self.goto(-130, 130)
# 打印墙,横纵循环13次(整个迷宫的长和宽由13格墙组成)
for row in range(len(self.maze_list)):
for col in range(len(self.maze_list)):
# 主函数中的maze_list里面的1则打印出一格墙
if self.maze_list[row][col] == 1:
self.draw_wall()
# 右移一列
self.goto(self.size * (col + 1) - 130, 130 - self.size * row)
# 下移一行
self.goto(-130, 130 - self.size * (row + 1))
if __name__=="__main__":
maze_list = [
[1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
[1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1],
[1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1],
[1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1],
[1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1],
[1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1],
[1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1]
]
Maze(maze_list)
turtle.mainloop()
主控
from Maze import Maze
from Player import Player
from Controller import Controller
import turtle
maze_list = [
[1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
[1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1],
[1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1],
[1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1],
[1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1],
[1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1],
[1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1]
]
Maze(maze_list)
#0,5表示玩家起始的位置;12,7表示终点的位置
player = Player(maze_list, 0, 5, [12], [7,9])
Controller(player)
turtle.mainloop()