网站建设管理教程视频,广州哪里有做网站,网上书城 网站建设策划书,广西学校论坛网站建设戳蓝字“CSDN云计算”关注我们哦#xff01;作者 | bigsai(同公众号)转自#xff5c; CSDN博客责编 | 阿秃先看效果图(在线电脑尝试地址http://biggsai.com/maze.html)#xff1a;起因又到深夜了#xff0c;我按照以往在公众号写着数据结构#xff01;这占用了我大量的时间…戳蓝字“CSDN云计算”关注我们哦作者 | bigsai(同公众号)转自 CSDN博客责编 | 阿秃先看效果图(在线电脑尝试地址http://biggsai.com/maze.html)起因又到深夜了我按照以往在公众号写着数据结构这占用了我大量的时间我的超越妹妹严重缺乏陪伴而 怨气满满超越妹妹时常埋怨认为数据结构这么抽象难懂的东西没啥作用常会问道天天写这玩意有啥作用。而我答道能干事情多了比如写个小游戏啥的当我码完字准备睡觉时写不好别睡觉分析如果用数据结构与算法造出东西来呢什么东西简单容易呢我百度一下我靠这个鸟游戏原来不好搞啊得接触一堆不熟悉的东西搞不来搞不来。有了(灵光一闪)写个猜数字游戏问他加减乘除等于几。超越妹妹又不是小孩子糊弄不过去。经过一番折腾终于在半夜12点确定写迷宫小游戏了。大概弄清楚其中的几个步骤。大概是画线—画迷宫(擦线)—方块移动、移动约束(不出界不穿墙)—完成游戏。画线(棋盘)对于htmljs(canvas)画的东西之前学过javaswing应该有点映像。在html中有个canvas 的画布可以在上面画一些东西和声明一些监听(键盘监听)。对于迷宫来说那些线条是没有属性的只有位置x,y你操作这个画布时候可能和我们习惯的面相对象思维不一样。所以在你设计的线或者点的时候记得那个点、线在什么位置在后续划线还是擦线还是移动的时候根据这个位置进行操作。!DOCTYPE htmlhtmlheadtitleMyHtml.html/title/headbodycanvas idmycanvas width600px height600px/canvas/bodyscript typetext/javascriptvar aa14;var chess document.getElementById(mycanvas);var context chess.getContext(2d);// var context2 chess.getContext(2d);// context.strokeStyle yellow;var tree [];//存放是否联通var isling[];//判断是否相连for(var i0;iaa;i){ tree[i][];for(var j0;jaa;j){ tree[i][j]-1;//初始值为0 } } for(var i0;iaa*aa;i){ isling[i][];for(var j0;jaa*aa;j){ isling[i][j]-1;//初始值为0 } }function drawChessBoard(){//绘画for(var i0;iaa1;i){ context.strokeStylegray;//可选区域 context.moveTo(15i*30,15);//垂直方向画15根线相距30px; context.lineTo(15i*30,1530*aa); context.stroke(); context.moveTo(15,15i*30);//水平方向画15根线相距30px;棋盘为14*14context.lineTo(1530*aa,15i*30); context.stroke(); } } drawChessBoard();//绘制棋盘// var mymapnew Array(36);// for(var i0;i36;i)// {mymap[i]-1;}/script/html实现效果画迷宫随机迷宫怎么生成怎么搞一脸懵逼。因为我们想要迷宫那么就需要这个迷宫出口和入口有连通路径你可能压根不知道迷宫改怎么生成用的什么算法。小声BB用并查集(不相交集合)。迷宫和不相交集合有什么联系呢(规则)之前笔者在前面数据结构与算法系列中曾经介绍过并查集(不相交集合)它的主要功能是森林的合并不联通的通过并查集能够快速将两个森林合并并且能够快速查询两个节点是否在同一个森林中而我们的随机迷宫在每个方格都不联通的情况下是一个棋盘方格这也是它的初始状态。而这个节点可以跟邻居可能相连也可能不相连。我们可以通过并查集实现。具体思路为(主要理解并查集)1定义好不想交集合的基本类和方法search,union等2数组初始化每一个数组元素都是一个集合值为-13随机查找一个格子一维数据要转换成二维有点麻烦在随机找一面墙也就是找这个格子的上下左右还要判断找的格子出没出界。具体在格子中找个随机数m——随机数m在二维中的位置[m/长,m%长]——这个二维的上下左右随机找一个位置p[m/长1,m%长]或[m/长-1,m%长]或[m/长,m%长1]或[m/长,m%长-1]——判断是否越界4判断两个格子(一维数组编号)是否在一个集合(并查集查找)。如果在则重新找如果不在那么把墙挖去5把墙挖去有点繁琐需要考虑奇偶判断它那种墙(上下还是左右还要考虑位置)然后擦掉。根据数组转换成真实距离。具体为找一个节点根据位置关系找到一维数组的号位用并查集判断是否在一个集合中。6最终得到一个完整的迷宫。直到第一个(1,1)和(n,n)联通停止。虽然采用随机数找墙但是效果并不是特别差。其中要搞清一维二维数组的关系。一维是真实数据并查集操作。二维是位置。要搞懂转化注意避免混淆搞清数组的地址和逻辑矩阵位置。数组从0开始的逻辑上你自己判断。别搞混淆主要逻辑为while(search(0)!search(aa*aa-1))//主要思路 {var num parseInt(Math.random() * aa*aa );//产生一个小于196的随机数var neihbourgetnei(num);if(search(num)search(neihbour)){continue;}else//不在一个上 { isling[num][neihbour]1;isling[neihbour][num]1; drawline(num,neihbour);//划线 union(num,neihbour); } }那么在前面的代码为!DOCTYPE htmlhtmlheadtitleMyHtml.html/title/headbodycanvas idmycanvas width600px height600px/canvas/bodyscript typetext/javascript//自行添加上面代码// var mymapnew Array(36);// for(var i0;i36;i)// {mymap[i]-1;}function getnei(a)//获得邻居号 random{var xparseInt(a/aa);//要精确成整数var ya%aa;var myneinew Array();//储存邻居if(x-10){mynei.push((x-1)*aay);}//上节点if(x114){mynei.push((x1)*aay);}//下节点if(y114){mynei.push(x*aay1);}//有节点if(y-10){mynei.push(x*aay-1);}//下节点var ranparseInt(Math.random() * mynei.length );return mynei[ran]; }function search(a)//找到根节点{if(tree[parseInt(a/aa)][a%aa]0)//说明是子节点 {return search(tree[parseInt(a/aa)][a%aa]);//不能压缩路径路径压缩 }elsereturn a; }function value(a)//找到树的大小{if(tree[parseInt(a/aa)][a%aa]0)//说明是子节点 {return tree[parseInt(a/aa)][a%aa]value(tree[parseInt(a/aa)][a%aa]);//不能路径压缩 }elsereturn -tree[parseInt(a/aa)][a%aa]; }function union(a,b)//合并{var a1search(a);//a根var b1search(b);//b根if(a1b1){}else {if(tree[parseInt(a1/aa)][a1%aa]tree[parseInt(b1/aa)][b1%aa])//这个是负数()为了简单减少计算不在调用value函数 { tree[parseInt(a1/aa)][a1%aa]tree[parseInt(b1/aa)][b1%aa];//个数相加 注意是负数相加 tree[parseInt(b1/aa)][b1%aa]a1; //b树成为a树的子树b的根b1直接指向a}else { tree[parseInt(b1/aa)][b1%aa]tree[parseInt(a1/aa)][a1%aa]; tree[parseInt(a1/aa)][a1%aa]b1;//a所在树成为b所在树的子树 } } }function drawline(a,b)//划线要判断是上下还是左右{var x1parseInt(a/aa);var y1a%aa;var x2parseInt(b/aa);var y2b%aa; var x3(x1x2)/2;var y3(y1y2)/2;if(x1-x21||x1-x2-1)//左右方向的点 需要上下划线 {//alert(x1);// context.beginPath(); context.strokeStyle white;// context.moveTo(30x3*30,y3*3015); context.lineTo(30x3*30,y3*3045); context.clearRect(29x3*30, y3*3016,2,28);// context.stroke(); }else {// context.beginPath(); context.strokeStyle white;// context.moveTo(x3*3015,30y3*30); context.lineTo(45x3*30,30y3*30); context.clearRect(x3*3016, 29y3*30,28,2);// context.stroke(); } }while(search(0)!search(aa*aa-1))//主要思路 {var num parseInt(Math.random() * aa*aa );//产生一个小于196的随机数var neihbourgetnei(num);if(search(num)search(neihbour)){continue;}else//不在一个上 { isling[num][neihbour]1;isling[neihbour][num]1; drawline(num,neihbour);//划线 union(num,neihbour); } }/script/html实现效果方块移动这部分我采用的方法不是动态真的移动而是一格一格的跳跃。也就是当走到下一个格子将当前格子的方块擦掉在移动的那个格子中再画一个方块。选择方块是因为方块更方便擦除可以根据像素大小精准擦除。另外再移动中要注意不能穿墙、越界。那么怎么判断呢很好办我们再前面会判断两个格子是否联通如果不连通我们将把这个墙拆开。再拆的时候把这个墙的时候记录这两点拆墙可走即可(数组)另外事件的监听上下左右查一查就可以得到添加按钮对一些事件监听这些不是最主要的。为了丰富游戏可玩性将方法封装可以设置关卡(只需改变迷宫大小)。这样就可以实现通关了。另外如果写成动态存库那就更好了。结语
在线尝试地址代码直接查看网页源代码即可扫描下方二维码看作者大大原文福利扫描添加小编微信备注“姓名公司职位”入驻【CSDN博客】加入【云计算学习交流群】和志同道合的朋友们共同打卡学习推荐阅读