<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>maze 迷宫算法</title>
<style>
body { margin: 0; overflow: hidden;}
.center{text-align: center;}
.title{
margin: 0px;
color: #776e65;
text-shadow: 1px 2px 3px #8f7a66;
font-size: 60px;
display: inline-block;
}
#divTitle{
display: inline-block;
margin-bottom: 10px;
}
.button {
font-weight: bold;
letter-spacing: 3px;
display: inline-block;
padding: 10px 20px;
font-size: 17px;
cursor: pointer;
text-align: center;
text-decoration: none;
outline: none;
color: #fff;
background-color: #8f7a66;
border: none;
border-radius: 15px;
box-shadow: 0 9px #999;
}
.button:active {
background-color: #bbada0;
box-shadow: 0 5px #666;
transform: translateY(4px);
}
#game{
position: relative;
}
#mapCanvas{
/*position: relative;*/
}
#pointCanvas{
position: absolute;
z-index: 2;
}
.game {
display: none;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: rgba(238, 228, 218, 0.5);
z-index: 100;
text-align: center;
-webkit-animation: fade-in 800ms ease 1200ms;
-moz-animation: fade-in 800ms ease 1200ms;
animation: fade-in 800ms ease 1200ms;
-webkit-animation-fill-mode: both;
-moz-animation-fill-mode: both;
animation-fill-mode: both;
}
.game p{
color: #776e65;
font-size: 100px;
font-weight: bold;
height: 60px;
line-height: 60px;
margin-top: 222px;
}
</style>
</head>
<body>
<div class="center">
<div id="divTitle">
<h1 class="title">迷 - 宫</h1>
<button class="button" type="button" onclick="BtnGameStart()">重新开始</button>
</div>
</div>
<div id="game" class="center">
<canvas id="pointCanvas" width="400" height="400">
pointCanvas
</canvas>
<canvas id="mapCanvas" width="400" height="400">
mapCanvas
</canvas>
</div>
<div class="game" onclick="gameSuccess(1)">
<p class="game-p" style="float: left;margin-left: 5%">恭喜</p>
<p class="game-p" style="float: right;margin-right: 5%">过关</p>
</div>
<script type="text/javascript">
// 创建地图
function Create(){
this.i = 0;
this.div = ['divTitle','pointCanvas','mapCanvas']; // div 地图 点
this.entrance = [1,1]; // 入口
this.annal = []; // 记录
this.mapSize = ''; // 最大
this.num = ''; // 次数
this.exportEntrance = ''; // 出口 - 入口
this.width = ''; // 墙 - 路 宽度
this.taste = 0; // 趣味 -- 入口处 >= 2
this.position = []; // 当前位置
this.mapcanvas = ''; // mapcanvas 对象
this.pointCanvas = ''; // pointCanvas 对象
this.mapcanvasObj = {
shadowBlur : 1,
}
this.Init = function(e){
this.position = [];
// 设置 关卡数
if(sessionStorage.checkpoint){
let str = sessionStorage.checkpoint;
str = JSON.parse(str);
if(this.i < str.checkpoint){
e += 2;
}
this.i = str.checkpoint;
}else{
let checkpoint = {checkpoint:1};
sessionStorage.checkpoint = JSON.stringify(checkpoint);
this.i = 1;
}
if((e & 1) === 0){
// 确定是奇数
e++;
}
this.checkpoint = e;
this.num = Math.pow(e - 2,2) - (e >> 1);
// this.num = 2;
this.mapSize = e - 1;
this.map = new Array(e);
for(let i = 0; i < e; i++){
this.map[i] = new Array(e).fill(0);
}
this.annal.push(this.entrance);
this.OpenGrid(this.entrance);
this.Route();
this.Draw();
this.Position();
}
// 地图 路线 生成
this.Route = function(){
let list,i = 0,n = 2;
while(i < this.num){
list = this.annal[this.annal.length - 1];
if(!list){
i++;
n = 2;
this.annal.pop();
continue;
}
list = this.ConnectedGrid(list,2);
list = this.JudgeGrid(list);
if(list.length > 1){
list[0] = list[this.Random(0,list.length)];
}else if(list.length == 0){
this.annal.pop();
i++;
continue;
}
this.OpenGrid(list[0]);
this.annal.push(list[0]);
this.OpenConnectedGrid();
i++;
}
this.ExportEntrance();
}
// 相连的格子 偶数 - 奇数 默认 奇数
this.ConnectedGrid = function(arr,n = 2){
let list = [];
if(arr[0] > 1 * n){
list.push([arr[0] - n,arr[1]]);
}
if(arr[0] < this.mapSize - n){
list.push([arr[0] + n,arr[1]]);
}
if(arr[1] > 1 * n){
list.push([arr[0] ,arr[1] - n]);
}
if(arr[1] < this.mapSize - n){
list.push([arr[0] ,arr[1] + n]);
}
return list;
}
// 打通相连的格子
this.OpenConnectedGrid = function(){
if(this.annal.length > 1){
let arr = [];
arr[0] = this.annal[this.annal.length - 1];
arr[1] = this.annal[this.annal.length - 2];
let x = (arr[0][0] - arr[1][0]) > 0 ? arr[0][0] - 1 : (arr[0][0] - arr[1][0]) == 0 ? arr[0][0] : arr[0][0] + 1;
let y = (arr[0][1] - arr[1][1]) > 0 ? arr[0][1] - 1 : (arr[0][1] - arr[1][1]) == 0 ? arr[0][1] : arr[0][1] + 1;
this.OpenGrid([x,y]);
}
}
// 判断格子
this.JudgeGrid = function(arr,code = 0){
let list = [], that = this;
if(code !== 1){
arr.forEach(function(item){
if(that.map[item[0]][item[1]] !== 1 ){
list.push(item);
}
});
}else{
arr.forEach(function(item){
if(that.map[item[0]][item[1]] === 1 ){
list.push(item);
}
});
}
return list;
}
// 打通格子
this.OpenGrid = function(arr){
this.map[arr[0]][arr[1]] = 1;
this.i++;
}
// 出口 - 入口
this.ExportEntrance = function(){
let i,x,y,l,code = 1,list = [],n = Math.pow(this.mapSize - 1,2);
list[0] = [[1,0],[0,1]];
list[1] = [];
// 为了游戏的乐趣 还是不搞全随机的出口 先右边->下面->上面->左边
l = i = this.mapSize - 1;
while(i >= 1 && n > 0){
code ? (x = i,y = l) : (x = l,y = i);
if(this.map[x][y] == 1){
list[1].push([x,y]);
}
if(list[1].length > 2){
break;
}
--i;
n--;
if(i == 0){
i = l;
code = code ? 0 : l = 1;
}
}
for(i = 0; i < list.length; i++){
list[i] = list[i][this.Random(0,list[i].length)];
}
x = list[1][0];
y = list[1][1];
list[1] = l != 1 ? code ? [x,y + 1] : [x + 1,y] : code ? [x,y - 1] : [x - 1,y];
for(i = 0; i < list.length; i++){
this.OpenGrid(list[i]);
}
this.exportEntrance = list;
// 为了增加游戏的趣味性 出口 路线要 >= 2
if(this.taste == 1){
list = this.ConnectedGrid(this.entrance,1);
list = this.JudgeGrid(list);
this.OpenGrid(list[0]);
}
}
// 随机
/*
* m 最小值
* n 最大值
*/
this.Random = function(m,n){
return Math.floor(Math.random()*(m - n) + n);
}
// 绘制 地图
this.Draw = function(){
let w = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
// let h = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
let wh = (w >> 1) - (w >> 3);
this.div.forEach(function(item){
obj = document.getElementById(item);
obj.width = wh;
obj.height = obj.width;
});
w = wh / (this.mapSize + 1);
this.width = w;
let that = this;
this.mapcanvas = obj.getContext('2d');
this.map.forEach(function(item,x){
item.forEach(function(val,y){
if(val === 0){
that.mapcanvas.fillRect(y * w,x * w ,w,w);
}
});
});
}
// 绘制 位置
this.Position = function(code = 1,n = 1){
if(this.position.length > 0){
let list = [];
list[0] = code ? this.position[0] : this.position[0] + n;
list[1] = code ? this.position[1] + n : this.position[1];
if(list[0] == this.exportEntrance[0][0] && list[1] == this.exportEntrance[0][1]){
console.log('想越狱???');
return;
}
if(list[0] == this.exportEntrance[1][0] && list[1] == this.exportEntrance[1][1]){
gameSuccess();
return;
}
list = this.JudgeGrid([list],1);
if(list.length <= 0){
return;
}else{
this.pointCanvas.clearRect(this.position[1] * this.width-1,this.position[0] * this.width-1,this.width+2,this.width+2);
this.map[this.position[0]][this.position[1]] = 1;
this.pointCanvas.beginPath();
this.pointCanvas.arc(list[0][1]* this.width + this.width/2,list[0][0]* this.width + this.width/2,this.width - Math.round(this.width / 2),0,2*Math.PI);
this.pointCanvas.stroke();
this.pointCanvas.fill();
this.position = [list[0][0],list[0][1]];
this.map[this.position[0]][this.position[1]] = 2;
}
}else{
let obj = document.getElementById('pointCanvas');
this.pointCanvas = obj.getContext('2d');
this.pointCanvas.beginPath();
this.pointCanvas.arc(1* this.width + this.width/2,1* this.width + this.width/2,this.width - Math.round(this.width / 2),0,2*Math.PI);
this.pointCanvas.stroke();
this.pointCanvas.fillStyle = 'red';
this.pointCanvas.fill();
this.position = [1,1];
this.map[1][1] = 2;
}
}
};
var maze = new Create();
maze.Init(10);
function BtnGameStart(){
maze.Init(10);
let str = sessionStorage.checkpoint;
str = JSON.parse(str);
str.checkpoint = 1;
sessionStorage.checkpoint = JSON.stringify(str);
}
// game 过关成功
function gameSuccess(code = 0){
if(code){
document.getElementsByClassName("game")[0].style.display = "none";
maze.Init(maze.checkpoint);
}else{
document.getElementsByClassName("game")[0].style.display = "block";
console.log('越狱成功!!!');
let str = sessionStorage.checkpoint;
str = JSON.parse(str);
str.checkpoint++;
sessionStorage.checkpoint = JSON.stringify(str);
}
}
document.addEventListener("keydown", function (event) {
switch(event.keyCode){
case 37:
case 65:
//console.log('left');
maze.Position(1,-1);
break;
case 38:
case 87:
//console.log('top');
maze.Position(0,-1);
break;
case 39:
case 68:
//console.log('right');
maze.Position(1,1);
break;
case 40:
case 83:
//console.log('bottom');
maze.Position(0,1);
break;
default:
break;
}
});
</script>
</body>
</html>
地图不应该是一个个小格子来的,渲染地图的时候可以根据地图数据来把相连的几个点的数据一起记录,x-x1 或 y-y1的。渲染地图时就可以直接使用,就不是一个个的渲染了。
定位 由于我是固定一个出入点 坐标(1,1);所以我是从这开始打洞,在该点上再次确认一个点,点与点之间要相隔一个点位,确认第二个点就打通它们之间的点位,避免一些死路出现。只要两点之间打通即可。按照这个思路即可创建地图。但是执行时间
5353 的地图 – 43.139892578125ms
103103的地图 – 158.218994140625ms
153153的地图 – 176.302001953125ms
203203的地图 – 190.451171875ms
好像有点慢 要优化
本文介绍了一种迷宫生成算法,通过随机选择路径并打通墙壁的方式创建迷宫地图。文章详细解释了算法的实现过程,包括地图初始化、路径生成、出口设置等关键步骤,并展示了如何将算法应用于游戏开发中,实现迷宫游戏的动态生成。
889

被折叠的 条评论
为什么被折叠?



