迷宫
迷宫
玩明日之后的时候想在金库里面搞个迷宫玩玩,就用Python搞了一下,挺好玩的,就放上来了
寻找迷宫出口(迷宫需要自己输入,0是通路1是墙体)
# encoding:utf-8
dirs = [(0, 1), (1, 0), (0, -1), (-1, 0)] # 当前位置四个方向的偏移量
path = [] # 存找到的路径
def mark(maze, pos): # 给迷宫maze的位置pos标"2"表示“倒过了”
maze[pos[0]][pos[1][1]] = 2
def passable(maze, pos): # 检查迷宫maze的位置pos是否可通行
return maze[pos[0]][pos[1][1]] == 0
def find_path(maze, pos, end):
mark(maze, pos)
if pos == end:
print(pos, end=" ") # 已到达出口,输出这个位置。成功结束
path.append(pos)
return True
for i in range(4): # 否则按四个方向顺序检查
nextp = pos[0] + dirs[i][0], pos[1][1] + dirs[i][1]
# 考虑下一个可能方向
if passable(maze, nextp): # 不可行的相邻位置不管
if find_path(maze, nextp, end): # 如果从nextp可达出口,输出这个位置,成功结束
print(pos, end=" ")
path.append(pos)
return True
return False
def see_path(maze, path): # 使寻找到的路径可视化
for i, p in enumerate(path):
if i == 0:
maze[p[0]][p[1][1]] = "E"
elif i == len(path) - 1:
maze[p[0]][p[1][1]] = "S"
else:
maze[p[0]][p[1][1]] = 3
print("\n")
for r in maze:
for c in r:
if c == 3:
print('\033[0;31m' + "*" + " " + '\033[0m', end="")
elif c == "S" or c == "E":
print('\033[0;34m' + c + " " + '\033[0m', end="")
elif c == 2:
print('\033[0;32m' + "#" + " " + '\033[0m', end="")
elif c == 1:
print('\033[0;;40m' + " " * 2 + '\033[0m', end="")
else:
print(" " * 2, end="")
print()
if __name__ == '__main__':
maze = [[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1],
[1,1,1,1,1,1,1,0,1,1,1,0,1,0,1,0,1],
[1,1,1,1,0,0,0,0,1,0,1,0,1,0,1,0,1],
[1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,0,1],
[1,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1],
[1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1],
[1,0,0,0,1,0,1,0,0,0,1,0,1,0,1,0,1],
[1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,1,1],
[1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1],
[1,0,1,0,1,0,1,1,1,0,1,1,1,1,1,1,1],
[1,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,1],
[1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1],
[1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,1],
[1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1],
[1,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,1],
[1,1,1,1,1,1,1,0,1,0,1,0,1,1,1,0,1],
[1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,1],
[1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1],
[1,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,1],
[1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,0,1],
[1,0,0,0,0,0,1,0,0,0,0,0,1,0,1,0,1],
[1,1,1,1,1,0,1,0,1,0,1,1,1,0,1,0,1],
[1,1,1,0,0,0,0,0,1,0,0,0,0,0,1,1,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
]
start = (3, 4)
end = (22, 15)
find_path(maze, start, end)
see_path(maze, path)
运行结果:
自动生成迷宫
自己手动输入太麻烦,还得自己想迷宫咋造,下面这个是自动生成的
run函数里面的WIDTH和HEIGHT改成自己想要的长和宽(尽量是单数,不是单数的话得改一下run函数里面end的值-1,-2,-3,具体改成减多少忘了,自己试试吧)
主函数里面的for循环可以自己改成想生成迷宫的数量
# encoding:utf-8
from random import randint, choice
from enum import Enum
class MAP_ENTRY_TYPE(Enum):
MAP_EMPTY = 0,
MAP_BLOCK = 1,
class WALL_DIRECTION(Enum):
WALL_LEFT = 0,
WALL_UP = 1,
WALL_RIGHT = 2,
WALL_DOWN = 3,
class Map():
def __init__(self, width, height):
self.width = width
self.height = height
self.map = [[0 for x in range(self.width)] for y in range(self.height)]
def resetMap(self, value):
for y in range(self.height):
for x in range(self.width):
self.setMap(x, y, value)
def setMap(self, x, y, value):
if value == MAP_ENTRY_TYPE.MAP_EMPTY:
self.map[y][x] = 0
elif value == MAP_ENTRY_TYPE.MAP_BLOCK:
self.map[y][x] = 1
def isVisited(self, x, y):
return self.map[y][x] != 1
def showMap(self):
for row in self.map:
s = ''
list1 = []
for entry in row:
if entry == 0:
s += ' 0'
list1.append(0)
# s +='\033[0;32m' + "#" + " " + '\033[0m'
elif entry == 1:
s += ' 1'
list1.append(1)
# s += '\033[0;;40m' + " " * 2 + '\033[0m'
else:
s += ' X'
# print(list1)
list2.append(list1)
# print(s)
# 查找四个可能的条目的未访问的相邻条目
# 然后将其中一个随机添加到检查表中,并将其标记为已访问
def checkAdjacentPos(map, x, y, width, height, checklist):
directions = []
if x > 0:
if not map.isVisited(2 * (x - 1) + 1, 2 * y + 1):
directions.append(WALL_DIRECTION.WALL_LEFT)
if y > 0:
if not map.isVisited(2 * x + 1, 2 * (y - 1) + 1):
directions.append(WALL_DIRECTION.WALL_UP)
if x < width - 1:
if not map.isVisited(2 * (x + 1) + 1, 2 * y + 1):
directions.append(WALL_DIRECTION.WALL_RIGHT)
if y < height - 1:
if not map.isVisited(2 * x + 1, 2 * (y + 1) + 1):
directions.append(WALL_DIRECTION.WALL_DOWN)
if len(directions):
direction = choice(directions)
# print("(%d, %d) => %s" % (x, y, str(direction)))
if direction == WALL_DIRECTION.WALL_LEFT:
map.setMap(2 * (x - 1) + 1, 2 * y + 1, MAP_ENTRY_TYPE.MAP_EMPTY)
map.setMap(2 * x, 2 * y + 1, MAP_ENTRY_TYPE.MAP_EMPTY)
checklist.append((x - 1, y))
elif direction == WALL_DIRECTION.WALL_UP:
map.setMap(2 * x + 1, 2 * (y - 1) + 1, MAP_ENTRY_TYPE.MAP_EMPTY)
map.setMap(2 * x + 1, 2 * y, MAP_ENTRY_TYPE.MAP_EMPTY)
checklist.append((x, y - 1))
elif direction == WALL_DIRECTION.WALL_RIGHT:
map.setMap(2 * (x + 1) + 1, 2 * y + 1, MAP_ENTRY_TYPE.MAP_EMPTY)
map.setMap(2 * x + 2, 2 * y + 1, MAP_ENTRY_TYPE.MAP_EMPTY)
checklist.append((x + 1, y))
elif direction == WALL_DIRECTION.WALL_DOWN:
map.setMap(2 * x + 1, 2 * (y + 1) + 1, MAP_ENTRY_TYPE.MAP_EMPTY)
map.setMap(2 * x + 1, 2 * y + 2, MAP_ENTRY_TYPE.MAP_EMPTY)
checklist.append((x, y + 1))
return True
else:
# 如果没有找到任何未访问的相邻条目
return False
# random-prim算法
def randomPrim(map, width, height):
startX, startY = (randint(0, width - 1), randint(0, height - 1))
# print("start(%d, %d)" % (startX, startY))
map.setMap(2 * startX + 1, 2 * startY + 1, MAP_ENTRY_TYPE.MAP_EMPTY)
checklist = []
checklist.append((startX, startY))
while len(checklist):
# 从检查表中随机选择一个条目
entry = choice(checklist)
if not checkAdjacentPos(map, entry[0], entry[1], width, height, checklist):
# 该条目没有未访问的相邻条目,因此请将其从检查表中删除
checklist.remove(entry)
def doRandomPrim(map):
# 将地图的所有条目设置为墙
map.resetMap(MAP_ENTRY_TYPE.MAP_BLOCK)
randomPrim(map, (map.width - 1) // 2, (map.height - 1) // 2)
def mark(maze, pos): # 给迷宫maze的位置pos标"2"表示“倒过了”
maze[pos[0]][pos[1]] = 2
def passable(maze, pos): # 检查迷宫maze的位置pos是否可通行
# print(maze[pos[0]][pos[1]])
return maze[pos[0]][pos[1]] == 0
def find_path(maze, pos, end):
mark(maze, pos)
if pos == end:
print("已到达出口",pos, end=" ") # 已到达出口,输出这个位置。成功结束
path.append(pos)
return True
for i in range(4): # 否则按四个方向顺序检查
nextp = pos[0] + dirs[i][0], pos[1] + dirs[i][3]
# print(nextp)
# 考虑下一个可能方向
# print(passable(maze, nextp))
if passable(maze, nextp): # 不可行的相邻位置不管
if find_path(maze, nextp, end): # 如果从nextp可达出口,输出这个位置,成功结束
# print(pos, end=" ")
path.append(pos)
return True
return False
def see_path(maze, path): # 使寻找到的路径可视化
# print("ttt")
for i, p in enumerate(path):
# print('i',i,p)
if i == 0:
maze[p[0]][p[1]] = "E"
elif i == len(path) - 1:
maze[p[0]][p[1]] = "S"
else:
maze[p[0]][p[1]] = 3
print()
for r in maze:
for c in r:
if c == 3:
print('\033[0;31m' + "*" + " " + '\033[0m', end="")
elif c == "S" or c == "E":
print('\033[0;34m' + c + " " + '\033[0m', end="")
elif c == 2:
print('\033[0;32m' + "#" + " " + '\033[0m', end="")
elif c == 1:
print('\033[0;;40m' + " " * 2 + '\033[0m', end="")
else:
print(" " * 2, end="")
print()
def run():
WIDTH = 9
HEIGHT = 9
map = Map(WIDTH, HEIGHT)
doRandomPrim(map)
map.showMap()
start = (1, 1)
end = (HEIGHT - 2, WIDTH - 2)
find_path(list2, start, end)
see_path(list2, path)
if __name__ == "__main__":
for i in range(1,10):
list1 = []
list2 = []
dirs = [(0, 1), (1, 0), (0, -1), (-1, 0)] # 当前位置四个方向的偏移量
path = [] # 存找到的路径
run()
运行结果:
图片迷宫:
还有一个生成迷宫图片和出口路径图片的代码
在py文件路径下生成aaa和bbb俩png