当前位置:   article > 正文

【Python】生成二维迷宫的算法

【Python】生成二维迷宫的算法

前言

哈里最近因为一个小插曲打算写一个设计迷宫的算法。为了锻炼脑力,特地没有上网搜索而是自己摸索出一个迷宫设计算法。

概述

1、需求

哈里准备实现下图的迷宫。

2、分析

可以看到,图里凡是x和y坐标为单数时,总是白色。于是哈里得到下图:

我将白色区域定义为房间(room),每个房间有四个方向(上下左右)可以连接其它房间。

我将能从绿色(出发点)到达的房间设置其连通(alive)。上图就只有(1,1)的房间连通。

这里哈里思考,如果每个房间都与出发点连通,最后右下角的房间必然就可以和出发点连通。

实际尝试之后,确实获得了一个还不错的迷宫图像,但是会出现下图的问题:

x=1和y=1总是会有大片的空白。

对此,哈里尝试将房间迭代的顺序打乱,最终得到了可以接受的迷宫图。

3、结语

差不多就是这样了……脑子混沌的时候靠直觉直接猜的……不完美但够用就行。

源码

  1. import random
  2. import sys
  3. from PIL import Image
  4. from pygame import *
  5. import time
  6. import pygame
  7. # 方向向量,用于四个方向:上、右、下、左
  8. dirVector = [
  9. (0, 1), # 下
  10. (1, 0), # 右
  11. (-1, 0), # 左
  12. (0, -1), # 上
  13. ]
  14. # 房间类,定义房间的位置和是否激活
  15. class Room:
  16. def __init__(self, pos, alive=False):
  17. self.pos = pos # 房间位置
  18. self.alive = alive # 房间是否激活
  19. # 链接房间
  20. def Link(self):
  21. if self.alive:
  22. return # 如果房间已激活,则返回
  23. dirs = self.GetCanOpenDirs() # 获取可以打开的方向
  24. if not dirs:
  25. return # 如果没有可用方向,则返回
  26. dirs = random.sample(dirs, 1) # 随机选择一个方向
  27. for d in dirs:
  28. img.putpixel((self.pos[0] + d[0], self.pos[1] + d[1]), (255, 255, 255)) # 在图像上绘制房间
  29. self.alive = True # 激活房间
  30. # 获取可以打开的方向
  31. def GetCanOpenDirs(self):
  32. r = []
  33. for d in dirVector:
  34. _x, _y = self.pos[0] + d[0], self.pos[1] + d[1] # 计算方向上的位置
  35. # 检查是否在图像边界内
  36. if _x < 1 or _y < 1 or _x >= img.width - 1 or _y >= img.height - 1:
  37. continue
  38. p2 = (self.pos[0] + d[0] * 2, self.pos[1] + d[1] * 2) # 计算下一个位置
  39. if p2 not in allRoom or not allRoom[p2].alive:
  40. continue
  41. r.append(d) # 将有效方向添加到列表
  42. return r
  43. @property
  44. def isColse(self):
  45. for d in dirVector:
  46. x, y = self.pos[0] + d[0], self.pos[1] + d[1] # 计算相邻位置
  47. if img.getpixel((x, y)) != (0, 0, 0): # 检查相邻像素是否为黑色
  48. return False
  49. return True
  50. # 判断所有房间是否激活
  51. def JudgeAllAlive():
  52. for _room in allRoom.values():
  53. if not _room.alive:
  54. return False
  55. return True
  56. # 初始化pygame
  57. pygame.init()
  58. pygame.display.set_caption('预览') # 设置窗口标题
  59. size = (21, 21) # 图像大小
  60. # screen = pygame.display.set_mode(Vector2(size) * 10) # 缩放图像
  61. screen = pygame.display.set_mode(Vector2(size)) # 创建显示窗口
  62. img = Image.new('RGB', size, (255, 255, 255)) # 创建新图像,背景为白色
  63. endPos = (size[0] - 2, size[1] - 1) # 终点位置
  64. rooms = [] # 房间列表
  65. allRoom = {} # 所有房间字典
  66. # 初始化图像上的黑色网格
  67. for y in range(img.height):
  68. for x in range(0, img.width, 2):
  69. img.putpixel((x, y), (0, 0, 0))
  70. for x in range(img.width):
  71. for y in range(0, img.height, 2):
  72. img.putpixel((x, y), (0, 0, 0))
  73. # 添加房间到列表和字典
  74. for x in range(1, img.width, 2):
  75. for y in range(1, img.height, 2):
  76. rooms.append((x, y))
  77. allRoom[(x, y)] = Room((x, y))
  78. allRoom[(1, 1)].alive = True # 激活起点房间
  79. random.shuffle(rooms) # 打乱房间顺序
  80. for roomPos in rooms:
  81. allRoom[roomPos].Link() # 链接所有房间
  82. # 标记起点和终点
  83. img.putpixel((1, 0), (0, 255, 0)) # 起点标记为绿色
  84. img.putpixel(endPos, (255, 0, 0)) # 终点标记为红色
  85. tempImg = img.copy() # 复制图像用于更新显示
  86. # 游戏主循环
  87. while 1:
  88. for event in pygame.event.get(): # 从Pygame的事件队列中取出事件,并从队列中删除该事件
  89. if event.type == pygame.QUIT: # 检查退出事件
  90. sys.exit() # 退出程序
  91. screen.fill((255, 255, 255)) # 填充背景为白色
  92. tempImg = img.copy() # 复制图像用于更新显示
  93. if not JudgeAllAlive(): # 检查是否所有房间都激活
  94. random.shuffle(rooms) # 打乱房间顺序
  95. for roomPos in rooms:
  96. allRoom[roomPos].Link() # 链接房间
  97. if not allRoom[roomPos].alive:
  98. tempImg.putpixel(roomPos, (255, 125, 0)) # 未激活的房间标记为橙色
  99. else:
  100. break # 如果所有房间都激活,退出循环
  101. pygameImg = pygame.image.frombuffer(tempImg.tobytes(), size, 'RGB') # 将图像转换为Pygame格式
  102. # pygameImg = pygame.transform.scale(pygameImg, Vector2(size) * 10) # 缩放图像
  103. screen.blit(pygameImg, (0, 0)) # 绘制图像到屏幕
  104. # time.sleep(0.05) # 延时
  105. pygame.display.flip() # 更新显示
  106. img.save('mg.png') # 保存图像为文件
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/1014122
推荐阅读
相关标签
  

闽ICP备14008679号