此博客旨在帮助大家更好的了解图的遍历算法,通过Flutter移动端平台将图的遍历算法运用在迷宫生成和解迷宫上,让算法变成可视化且可以进行交互,最终做成一个可进行随机迷宫生成和解迷宫的APP小游戏。本人是应届毕业生,希望能与大家一起讨论和学习~
注:由于这是本人第一次写博客,难免排版或用词上有所欠缺,请大家多多包涵。
注:如需转载文章,请注明出处,谢谢。
一、项目介绍:
1.概述
项目名:方块迷宫
作者:沫小亮。
编程框架与语言:Flutter&Dart
开发环境:Android Studio 3.6.2
学习参考:慕课网-看得见的算法
项目完整源码地址:(待更新)
游戏截图:
2.迷宫生成原理
1.采用图的遍历进行迷宫生成,其本质就是生成一棵树,树中每个节点只能访问一次,且每个节点之间没有环路(迷宫的正确路径只有一条)。
2.初始化:设置起点和终点位置,并给所有行坐标为奇数且列坐标为奇数的位置设置为路。其余位置设置为墙。(坐标从0…开始算)
(如下图,蓝色位置为墙,橙色位置为路,橙色线条为可能即将打通的路,此图来源于慕课网-看得见的算法)
3.在遍历过程中,不断遍历每个位置,同时遍历过的位置设为已访问位置,结合迷宫生成算法(见迷宫特点第6点)让相邻某个墙变成路,使之路径联通。直至所有位置都遍历完成则迷宫生成结束(每个节点只能遍历一次)。
(如下图,蓝色位置为墙,橙色位置为路,橙色线条为可能即将打通的路,此图来源于慕课网-看得见的算法)
3.迷宫特点(可根据需求自行扩展)
1.迷宫只有一个起点、一个终点,且起点和终点的位置固定。
2.迷宫的正确路径只有一条。
3.迷宫的正确路径是连续的。
4.迷宫地图是正方形,且方块行数和列数都为奇数。
5.迷宫中每个方块占用一个单元格。
6.迷宫生成算法:图的深度优先遍历和广度优先遍历相结合 + 随机队列(入队和出队随机在队头或队尾)+ 随机方向遍历顺序(提高迷宫的随机性)。
7.迷宫自动求解算法:图的深度优先遍历(递归方法)。
4.玩法介绍(可根据需求自行扩展)
1.游戏共设置有10个关卡,到达终点可以进入下一关,随着关卡数的增加,迷宫地图大小(方块数)增加,但限定时间也会增加。
2.点击方向键可对玩家角色的位置进行控制。
2.每个关卡都有限定时间,超过限定时间仍未到达终点则闯关失败,可从本关继续挑战。
3.每个关卡都可以使用一次提示功能,可展示2秒的正确路径,便于小白玩家入门。
4. 颜色对应:
蓝灰色方块->墙(不可经过)
蓝色方块->玩家角色(可控制移动)
白色方块->路(可经过)
深橘色->终点(通关)
橙色->正确路径(提示功能)
二、项目源码(主要部分):
pubspec.yaml //flutter配置清单
dependencies:
flutter:
sdk: flutter
//toast库
fluttertoast: ^3.1.3
//Cupertino主题图标集
cupertino_icons: ^0.1.2
maze_game_model.dart //迷宫游戏数据层
class MazeGameModel {
int _rowSum; //迷宫行数
int _columnSum; //迷宫列数
int _startX, _startY; //迷宫入口坐标([startX,startY])
int _endX, _endY; //迷宫出口坐标([endX,endY])
static final int MAP_ROAD = 1; //1代表路
static final int MAP_WALL = 0; //0代表墙
List> mazeMap; //迷宫地形(1代表路,0代表墙)
List> visited; //是否已经访问过
List> path; //是否是正确解的路径
List> direction = [
[-1, 0],
[0, 1],
[1, 0],
[0, -1]
]; //迷宫遍历的方向顺序(迷宫趋势)
int spendStepSum = 0; //求解的总步数
int successStepLength = 0; //正确路径长度
int playerX, playerY; //当前玩家坐标
MazeGameModel(int rowSum, int columnSum) {
if (rowSum % 2 == 0 || columnSum % 2 == 0) {
throw "model_this->迷宫行数和列数不能为偶数";
}
this._rowSum = rowSum;
this._columnSum = columnSum;
mazeMap = new List>();
visited = new List>(