Go Ebiten随机迷宫生成示例

引言
迷宫生成是计算机科学中一个经典的问题,常用于算法教学和游戏开发。本文将介绍如何使用 Go 语言和 Ebiten 游戏引擎实现一个基于深度优先搜索(DFS)的随机迷宫生成算法,并通过可视化的方式展示迷宫的生成过程。
技术栈
- Go 语言:一种高效、简洁的编程语言,适合实现算法和并发任务。
- Ebiten:一个轻量级的 2D 游戏引擎,适合快速开发简单的图形应用程序。
- 深度优先搜索(DFS):一种经典的图遍历算法,用于生成随机迷宫。
算法原理
深度优先搜索(DFS)
DFS 是一种用于遍历或搜索树或图的算法。在迷宫生成中,我们可以将迷宫看作一个图,每个块是一个节点,墙是节点之间的边。DFS 通过随机选择邻居节点并打破墙来生成迷宫。
栈回溯
为了确保迷宫生成的完整性,我们使用栈来记录访问路径。当当前块没有未访问的邻居时,通过栈回溯到上一个未完全探索的块,继续生成迷宫。
代码实现
package mainimport ("image/color""math/rand""os""time""github.com/hajimehoshi/ebiten/v2""github.com/hajimehoshi/ebiten/v2/vector"
)const (N int = 20 // 迷宫的行数和列数BlockSize int = 50 // 每个迷宫块的大小(像素)WindowWidth int = N*BlockSize + 2*int(WW) // 窗口宽度WindowHeight int = N*BlockSize + 2*int(WW) // 窗口高度WW float32 = 2 // 墙的宽度(像素)BS float32 = float32(BlockSize) // 块大小的浮点数表示
)// Pos 结构体表示一个二维坐标
type Pos struct {X, Y int
}// Dirs 数组表示四个可能的移动方向(上、左、右、下)
var Dirs [4]Pos = [4]Pos{Pos{0, -1}, Pos{-1, 0}, Pos{1, 0}, Pos{0, 1}}// Game 结构体表示游戏的状态
type Game struct {T int // 当前已访问的块数P Pos // 当前的位置Walls [N][N][4]bool // 记录每个块的四面墙是否存在IsVis [N][N]bool // 记录每个块是否被访问过Stack []Pos // 栈,用于记录访问路径
}// Update 是 Ebiten 游戏循环中的更新函数,每一帧调用一次
func (g *Game) Update() error {SystemFunction() // 处理系统功能(如退出)if g.T < N*N { // 如果还有未访问的块g.Next() // 生成下一个块}return nil
}// Draw 是 Ebiten 游戏循环中的绘制函数,每一帧调用一次
func (g *Game) Draw(screen *ebiten.Image) {g.DrawWalls(screen) // 绘制迷宫的墙
}// Layout 设置游戏窗口的布局
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {return outsideWidth, outsideHeight
}func main() {ebiten.SetWindowTitle("maze") // 设置窗口标题ebiten.SetWindowSize(WindowWidth, WindowHeight) // 设置窗口大小game := &Game{P: Pos{rand.Intn(N), rand.Intn(N)}, // 随机选择一个起始位置Stack: make([]Pos, 0), // 初始化栈}if err := ebiten.RunGame(game); err != nil { // 运行游戏panic(err)}
}// SystemFunction 处理系统功能,如退出游戏
func SystemFunction() {if ebiten.IsKeyPressed(ebiten.KeyEscape) { // 如果按下 ESC 键os.Exit(0) // 退出程序}
}// DrawWalls 绘制迷宫的墙
func (g *Game) DrawWalls(screen *ebiten.Image) {if g.T < N*N { // 如果还有未访问的块// 绘制当前块的位置(红色方块)vector.DrawFilledRect(screen, float32(g.P.X)*BS, float32(g.P.Y)*BS, BS, BS, color.RGBA{255, 0, 0, 255}, true)}// 遍历所有块,绘制墙for i := 0; i < N; i++ {for j := 0; j < N; j++ {if !g.Walls[i][j][0] { // 如果上墙存在vector.DrawFilledRect(screen, float32(i)*BS, float32(j)*BS, BS, WW, color.White, true)}if !g.Walls[i][j][1] { // 如果左墙存在vector.DrawFilledRect(screen, float32(i)*BS, float32(j)*BS, WW, BS, color.White, true)}if !g.Walls[i][j][2] { // 如果右墙存在vector.DrawFilledRect(screen, float32(i+1)*BS, float32(j)*BS, WW, BS, color.White, true)}if !g.Walls[i][j][3] { // 如果下墙存在vector.DrawFilledRect(screen, float32(i)*BS, float32(j+1)*BS, BS, WW, color.White, true)}}}
}// Next 生成迷宫的下一个块
func (g *Game) Next() {// check 函数检查给定的坐标是否在迷宫范围内且未被访问过check := func(x, y int) bool {return x >= 0 && x < N && y >= 0 && y < N && !g.IsVis[x][y]}// 标记当前块为已访问if !g.IsVis[g.P.X][g.P.Y] {g.IsVis[g.P.X][g.P.Y] = trueg.T++}// 查找当前块的所有未访问邻居var neighbors []intfor i := 0; i < 4; i++ {if check(g.P.X+Dirs[i].X, g.P.Y+Dirs[i].Y) {neighbors = append(neighbors, i)}}if len(neighbors) > 0 {// 如果有未访问的邻居,随机选择一个方向d := neighbors[rand.Intn(len(neighbors))]g.Stack = append(g.Stack, g.P) // 将当前位置压入栈g.Walls[g.P.X][g.P.Y][d] = true // 打破当前块的墙g.P.X += Dirs[d].X // 移动到邻居块g.P.Y += Dirs[d].Yg.Walls[g.P.X][g.P.Y][3-d] = true // 打破邻居块的对应墙} else if len(g.Stack) > 0 {// 如果没有未访问的邻居,回溯到上一个块g.P = g.Stack[len(g.Stack)-1] // 弹出栈顶元素g.Stack = g.Stack[:len(g.Stack)-1]}
}
相关文章:
Go Ebiten随机迷宫生成示例
引言 迷宫生成是计算机科学中一个经典的问题,常用于算法教学和游戏开发。本文将介绍如何使用 Go 语言和 Ebiten 游戏引擎实现一个基于深度优先搜索(DFS)的随机迷宫生成算法,并通过可视化的方式展示迷宫的生成过程。 技术栈 Go …...
前端学习DAY31(子元素溢出父元素)
.box1{width: 200px;height: 200px;background-color: chocolate;} 子元素是在父元素的内容区中排列的,如果子元素的大小超过了父元素,则子元素会从 父元素中溢出,使用overflow属性设置父元素如何处理溢出的子元素 可选值:visible…...
『SQLite』表的创建、修改和删除
本节摘要:主要讲述SQLite中创建、删除、修改表等操作。 创建表 CREATE TABLE 语句来创建表。 修改表 ALTER TABLE 语句来修改表名称、已有表字段,或者新增字段。 删除表 DROP TABLE 语句用来删除表. 注意: 上述内容详细讲解见文章&#…...
可持久化数据结构-线段树(主席树)
可持久化数据结构-线段树(主席树) (与可持久化字典树差不多) 概念:可持久化线段树是基本线段树的一个简单拓展, 是使用函数式编程思想的线段树; 作用: 可以存下来数据结构的所有历史版本 特点: 拓扑结构…...
如何利用PHP爬虫按关键字搜索淘宝商品
在当今的电商时代,获取淘宝商品信息对于市场研究、价格监控和竞争分析等方面具有重要意义。手动搜索和整理大量商品信息不仅耗时耗力,而且容易出错。幸运的是,PHP爬虫技术为我们提供了一种高效、自动化的方式来按关键字搜索淘宝商品。本文将详…...
GitHub - riscv-software-src/riscv-isa-sim: Spike, a RISC-V ISA Simulator
GitHub - riscv-software-src/riscv-isa-sim: Spike, a RISC-V ISA Simulator 操作手册 $ apt-get install device-tree-compiler libboost-regex-dev libboost-system-dev $ mkdir build $ cd build $ ../configure --prefix$RISCV $ make $ [sudo] make install 具体安装 …...
ubuntu开机启动服务
需求背景: 需要监控日志,每次都是手动启动 nohup ./prometheus >/dev/null & nohub ./node_exporter >/dev/null & 需求目标: 重启后系统自动启动服务...
电子电气架构 --- 设计车载充电机的关键考虑因素
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活,除了生存温饱问题之外,没有什么过多的欲望,表面看起来很高冷,内心热情,如果你身…...
2025_0105_生活记录
3号去内蒙看了流星雨。还记得上次看流星的时间是2018年,也是冬天,大家在雁栖湖校区的操场上仰望星空。那个时候幸运的看到了一颗流星,便迅速地在心里许愿。这次看到了三颗流星,我也许了愿,希望实现。 24年走过了十多个…...
电池管理系统(BMS)架构详细解析:原理与器件选型指南
BMS(电池管理系统)架构详细讲解 从你提供的BMS(Battery Management System)架构图来看,主要涉及到电池监控模块、通信模块、功率控制模块等部分。下面我将详细讲解该架构的各个功能模块及其工作原理。 1. 电池管理核…...
用JAVA编写一个简单的小游戏
用Java语言编写一个简单的小游戏。这里是一个非常基础的猜数字小游戏的代码示例。在这个游戏中,程序会随机选择一个1到100之间的整数,玩家需要猜测这个数字是什么。每次猜测后,程序会告诉玩家他们猜的数字是太高了、太低了还是正确。 impor…...
【SpringSecurity】二、自定义页面前后端分离
文章目录 1、用户认证流程AuthenticationSuccessHandler AuthenticationFailureHandlerSecurityFilterChain配置用户认证信息 2、会话并发处理2.1、实现处理器接口2.2、SecurityFilterChain配置 1、用户认证流程 AuthenticationSuccessHandler AuthenticationFailureHandler …...
小兔鲜儿:头部区域的logo,导航,搜索,购物车
头部:logo ,导航,搜索,购物车 头部总体布局: 设置好上下外边距以及总体高度, flex布局让总体一行排列 logo: logo考虑搜索引擎优化,所以要使用 h1中包裹 a 标签,a 里边写内容(到时候…...
什么是VLAN?
VLAN(Virtual Local Area Network,虚拟局域网)是一种将物理局域网划分成多个逻辑上独立的虚拟网络的技术。VLAN不依赖于设备的物理位置,而是通过逻辑划分,将局域网内的设备虚拟地组织到同一组。这种技术允许网络管理员…...
WPS计算机二级•数据查找分析
听说这里是目录哦 通配符🌌问号(?)星号(*)波形符(~) 排序🌠数字按大小排序以当前选定区域排序以扩展选定区域排序 文字按首字母排序 快速筛选分类数据☄️文字筛选数字筛选颜色筛选…...
计算机网络 (28)虚拟专用网VPN
前言 虚拟专用网络(VPN)是一种在公共网络上建立私有网络连接的技术,它允许远程用户通过加密通道访问内部网络资源,实现远程办公和安全通信。 一、基本概念 定义:VPN是一种通过公共网络(如互联网)…...
【Python学习(七)——序列、列表、元组、range、字符串、字典、集合、可变类型不可变类型】
Python学习(七)——序列、列表、元组、range、字符串、字典、集合、可变类型&不可变类型 本文介绍了序列、列表、元组、range、字符串、字典、集合、可变类型&不可变类型,仅作为本人学习时记录,感兴趣的初学者可以一起看…...
MATLAB常用建模方法——常用非参数检验
常用非参数检验 在用样本数据对正态总体参数作出统计判断(例如参数估计和假设检验)时,要求样本数据应服从正态分布,这种数据分布类型已知的总体参数的假设检验称为参数假设检验。 与参数假设检验相对应的还有非参数假设检验&#…...
【多线程初阶篇 ²】创建线程的方式
目录 二、多线程代码 1.继承Thread类 2.实现Runnable接口 3.匿名内部类 3.1 创建Thread⼦类对象 3.2 创建Runnable⼦类对象 4.lambda表达式(推荐) 小结: 🔥面试题:Java中创建线程都有哪些写法 二、多线程代码 …...
纵览!报表控件 Stimulsoft Reports、Dashboards 和 Forms 2025.1 新版本发布!
Stimulsoft 2025.1 新版发布,旨在增强您创建报告、仪表板和 PDF 表单的体验!此最新版本为您带来了许多改进和新功能,使数据处理更加高效和用户友好。亮点包括对 .NET 9 的支持、Microsoft Analysis Services 的新数据适配器、发布向导中适用于…...
Materials Studio8.0 Linux版安装避坑指南:JRE版本与libstdc++问题解决
Materials Studio 8.0 Linux版深度安装指南:从环境配置到疑难解析 在材料科学计算领域,BIOVIA Materials Studio作为一款集分子模拟与材料设计于一体的专业软件,其Linux版本安装常因系统环境差异导致各类兼容性问题。本文将系统梳理CentOS 7环…...
运算放大电路实战指南:从基础到典型应用
1. 运算放大电路基础入门 第一次接触运算放大电路时,我完全被那些复杂的公式和符号搞晕了。直到后来在实际项目中反复使用,才发现它就像电子世界的"瑞士军刀",功能强大又灵活多变。运算放大器(简称运放)本质…...
AI建站工具从入门到上线:零基础也能轻松搭建专业网站的全流程攻略
痛点共情:为什么你建站总是“想得美,做得累”?相信很多企业主、创业者或市场负责人都有过类似的经历:想为公司做一个专业网站,要么被建站公司报的高价吓退,要么自己尝试用传统建站工具,结果被模…...
16.5【保姆级教程】C11对齐特性详解:比位填充更自然,底层开发必学
📢 关注博主不迷路!CSDN最细C11对齐特性教程来袭🔥 继位字段之后,解锁C语言底层内存控制新技能——C11对齐特性,比传统位填充字节更自然、更规范,吃透它,轻松搞定硬件相关开发难点,刚…...
PVE虚拟化部署OpenWRT旁路由:从镜像转换到网络配置全解析
1. 为什么选择PVEOpenWRT旁路由方案 最近两年软路由越来越火,很多朋友都在问要不要把家里的硬路由换成软路由。其实完全没必要这么折腾,用PVE虚拟化跑OpenWRT做旁路由才是更优雅的解决方案。我去年给公司办公室部署了这个方案,到现在稳定运行…...
基于Gradle 7.6与Spring Boot 3.0构建现代化Java 17微服务架构
1. 为什么选择Gradle 7.6 Spring Boot 3.0 Java 17组合 最近两年Java生态发生了翻天覆地的变化。作为一个经历过多个微服务项目的老兵,我发现这套技术组合正在成为企业级开发的新标准。Gradle 7.6带来的构建速度提升,Spring Boot 3.0对云原生的深度支持…...
解锁QQ音乐加密音频:qmc-decoder全面解决方案指南
解锁QQ音乐加密音频:qmc-decoder全面解决方案指南 【免费下载链接】qmc-decoder Fastest & best convert qmc 2 mp3 | flac tools 项目地址: https://gitcode.com/gh_mirrors/qm/qmc-decoder 还在为QQ音乐下载的加密音频文件无法在其他播放器或设备上播放…...
错过SITS2026这场演讲=落后18个月?AIAgent自主决策的4个颠覆性范式转移正在加速商用
第一章:SITS2026演讲核心洞见与行业坐标重定义 2026奇点智能技术大会(https://ml-summit.org) 在SITS2026主会场,来自全球17个国家的43位系统架构师与AI基础设施负责人共同指出:传统“模型即服务”(MaaS)范式正被“环…...
【奇点2026权威发布】:AIAgent任务调度必须绕开的7个LLM原生缺陷(附可验证的调度补偿算法伪代码)
第一章:【奇点2026权威发布】:AIAgent任务调度必须绕开的7个LLM原生缺陷(附可验证的调度补偿算法伪代码) 2026奇点智能技术大会(https://ml-summit.org) 大型语言模型在AIAgent任务调度中并非“即插即用”的可靠执行引擎——其底…...
亚马逊品牌推广:破局只曝光不转化误区,解锁拿单新思路
亚马逊品牌推广:破局只曝光不转化误区,解锁拿单新思路 正文: 新品上线 6 个月仅投商品推广,核心词 CPC 一路走高,ACOS居高不下,冷启动慢、迟迟起不了量?不少亚马逊卖家都面临这样的困境…...
