当前位置: 首页 > news >正文

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

前言

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

概述

1、需求

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

2、分析

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

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

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

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

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

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

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

3、结语

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

源码

import random
import sysfrom PIL import Image
from pygame import *
import time
import pygame# 方向向量,用于四个方向:上、右、下、左
dirVector = [(0, 1),    # 下(1, 0),    # 右(-1, 0),   # 左(0, -1),   # 上
]# 房间类,定义房间的位置和是否激活
class Room:def __init__(self, pos, alive=False):self.pos = pos  # 房间位置self.alive = alive  # 房间是否激活# 链接房间def Link(self):if self.alive:return  # 如果房间已激活,则返回dirs = self.GetCanOpenDirs()  # 获取可以打开的方向if not dirs:return  # 如果没有可用方向,则返回dirs = random.sample(dirs, 1)  # 随机选择一个方向for d in dirs:img.putpixel((self.pos[0] + d[0], self.pos[1] + d[1]), (255, 255, 255))  # 在图像上绘制房间self.alive = True  # 激活房间# 获取可以打开的方向def GetCanOpenDirs(self):r = []for d in dirVector:_x, _y = self.pos[0] + d[0], self.pos[1] + d[1]  # 计算方向上的位置# 检查是否在图像边界内if _x < 1 or _y < 1 or _x >= img.width - 1 or _y >= img.height - 1:continuep2 = (self.pos[0] + d[0] * 2, self.pos[1] + d[1] * 2)  # 计算下一个位置if p2 not in allRoom or not allRoom[p2].alive:continuer.append(d)  # 将有效方向添加到列表return r@propertydef isColse(self):for d in dirVector:x, y = self.pos[0] + d[0], self.pos[1] + d[1]  # 计算相邻位置if img.getpixel((x, y)) != (0, 0, 0):  # 检查相邻像素是否为黑色return Falsereturn True# 判断所有房间是否激活
def JudgeAllAlive():for _room in allRoom.values():if not _room.alive:return Falsereturn True# 初始化pygame
pygame.init()
pygame.display.set_caption('预览')  # 设置窗口标题
size = (21, 21)  # 图像大小
# screen = pygame.display.set_mode(Vector2(size) * 10)  # 缩放图像
screen = pygame.display.set_mode(Vector2(size))  # 创建显示窗口
img = Image.new('RGB', size, (255, 255, 255))  # 创建新图像,背景为白色
endPos = (size[0] - 2, size[1] - 1)  # 终点位置
rooms = []  # 房间列表
allRoom = {}  # 所有房间字典# 初始化图像上的黑色网格
for y in range(img.height):for x in range(0, img.width, 2):img.putpixel((x, y), (0, 0, 0))for x in range(img.width):for y in range(0, img.height, 2):img.putpixel((x, y), (0, 0, 0))# 添加房间到列表和字典
for x in range(1, img.width, 2):for y in range(1, img.height, 2):rooms.append((x, y))allRoom[(x, y)] = Room((x, y))
allRoom[(1, 1)].alive = True  # 激活起点房间random.shuffle(rooms)  # 打乱房间顺序
for roomPos in rooms:allRoom[roomPos].Link()  # 链接所有房间# 标记起点和终点
img.putpixel((1, 0), (0, 255, 0))  # 起点标记为绿色
img.putpixel(endPos, (255, 0, 0))  # 终点标记为红色
tempImg = img.copy()  # 复制图像用于更新显示# 游戏主循环
while 1:for event in pygame.event.get():  # 从Pygame的事件队列中取出事件,并从队列中删除该事件if event.type == pygame.QUIT:  # 检查退出事件sys.exit()  # 退出程序screen.fill((255, 255, 255))  # 填充背景为白色tempImg = img.copy()  # 复制图像用于更新显示if not JudgeAllAlive():  # 检查是否所有房间都激活random.shuffle(rooms)  # 打乱房间顺序for roomPos in rooms:allRoom[roomPos].Link()  # 链接房间if not allRoom[roomPos].alive:tempImg.putpixel(roomPos, (255, 125, 0))  # 未激活的房间标记为橙色else:break  # 如果所有房间都激活,退出循环pygameImg = pygame.image.frombuffer(tempImg.tobytes(), size, 'RGB')  # 将图像转换为Pygame格式# pygameImg = pygame.transform.scale(pygameImg, Vector2(size) * 10)  # 缩放图像screen.blit(pygameImg, (0, 0))  # 绘制图像到屏幕# time.sleep(0.05)  # 延时pygame.display.flip()  # 更新显示img.save('mg.png')  # 保存图像为文件

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • C语言---栈
  • 【Unity基础】Unity中的Tag、Layer和Sorting Layer
  • 【Linux】1.Linux环境搭建
  • C语言 | Leetcode C语言题解之第354题俄罗斯套娃信封问题
  • 深入探讨 Nginx:安装、配置及优化指南
  • 2024.08.13 校招 实习 内推 面经
  • 插屏广告在游戏APP中广告变现的独特优势
  • Readiness Probe可以解决应用启动慢造成访问异常的问题。
  • 配置主从mysql服务器
  • AcWing848有向图的拓扑排序
  • ModuleNotFoundError: No module named ‘sentence_transformers.model_card‘
  • 蓝牙音视频远程控制协议(AVRCP) command跟response介绍
  • filezilla软件介绍
  • 【API网关】 使用Kong、Zuul等工具实现API网关
  • 【Python系列】执行 Shell 命令的六种方法
  • 【知识碎片】第三方登录弹窗效果
  • 2017-08-04 前端日报
  • android百种动画侧滑库、步骤视图、TextView效果、社交、搜房、K线图等源码
  • Bootstrap JS插件Alert源码分析
  • Java|序列化异常StreamCorruptedException的解决方法
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • macOS 中 shell 创建文件夹及文件并 VS Code 打开
  • mockjs让前端开发独立于后端
  • OSS Web直传 (文件图片)
  • React-redux的原理以及使用
  • SpringBoot 实战 (三) | 配置文件详解
  • SQL 难点解决:记录的引用
  • Vim Clutch | 面向脚踏板编程……
  • webpack4 一点通
  • 阿里云ubuntu14.04 Nginx反向代理Nodejs
  • 日剧·日综资源集合(建议收藏)
  • 我与Jetbrains的这些年
  • 用quicker-worker.js轻松跑一个大数据遍历
  • ​Distil-Whisper:比Whisper快6倍,体积小50%的语音识别模型
  • ​HTTP与HTTPS:网络通信的安全卫士
  • ​力扣解法汇总946-验证栈序列
  • # 手柄编程_北通阿修罗3动手评:一款兼具功能、操控性的电竞手柄
  • #{}和${}的区别是什么 -- java面试
  • #DBA杂记1
  • $.ajax()
  • $con= MySQL有关填空题_2015年计算机二级考试《MySQL》提高练习题(10)
  • (6)【Python/机器学习/深度学习】Machine-Learning模型与算法应用—使用Adaboost建模及工作环境下的数据分析整理
  • (Bean工厂的后处理器入门)学习Spring的第七天
  • (HAL库版)freeRTOS移植STMF103
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (仿QQ聊天消息列表加载)wp7 listbox 列表项逐一加载的一种实现方式,以及加入渐显动画...
  • (附源码)springboot 个人网页的网站 毕业设计031623
  • (附源码)ssm基于jsp的在线点餐系统 毕业设计 111016
  • (附源码)ssm基于jsp高校选课系统 毕业设计 291627
  • (附源码)计算机毕业设计ssm基于B_S的汽车售后服务管理系统
  • (全注解开发)学习Spring-MVC的第三天
  • (正则)提取页面里的img标签
  • (转)创业家杂志:UCWEB天使第一步
  • (转)四层和七层负载均衡的区别
  • (转载)VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)