亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > HTML5 > 正文

使用數據結構給女朋友寫個Html5走迷宮游戲

2024-09-05 07:23:08
字體:
來源:轉載
供稿:網友

先看效果圖(在線電腦嘗試地址http://biggsai.com/maze.html):


在這里插入圖片描述

起因

在這里插入圖片描述
 

又到深夜了,我按照以往在公眾號寫著數據結構!這占用了我大量的時間!我的超越妹妹嚴重缺乏陪伴而 怨氣滿滿!


在這里插入圖片描述
 

超越妹妹時常埋怨,認為數據結構這么抽象難懂的東西沒啥作用,常會問道:天天寫這玩意,有啥作用。而我答道:能干事情多了,比如寫個小游戲啥的!


在這里插入圖片描述
 

當我碼完字準備睡覺時:寫不好別睡覺!


在這里插入圖片描述

分析

如果用數據結構與算法造出東西來呢?

什么東西簡單容易呢?我百度一下,我靠,這個鳥游戲原來不好搞啊,得接觸一堆不熟悉的東西,搞不來搞不來。

有了(靈光一閃),寫個猜數字游戲,問他加減乘除等于幾。

超越妹妹又不是小孩子,糊弄不過去。

經過一番折騰,終于在半夜12點確定寫迷宮小游戲了。大概弄清楚其中的幾個步驟。

大概是:

畫線—>畫迷宮(擦線)—>方塊移動、移動約束(不出界不穿墻)—>完成游戲。畫線(棋盤)

對于html+js(canvas)畫的東西,之前學過javaswing應該有點映像。在html中有個canvas 的畫布,可以在上面畫一些東西和聲明一些監聽(鍵盤監聽)。

對于迷宮來說,那些線條是沒有屬性的,只有位置x,y,你操作這個畫布時候,可能和我們習慣的面相對象思維不一樣。所以,在你設計的線或者點的時候,記得那個點、線在什么位置,在后續劃線還是擦線還是移動的時候根據這個位置進行操作。

 

<!DOCTYPE html><html>  <head>    <title>MyHtml.html</title>	  </head>   <body>  <canvas id="mycanvas" width="600px" height="600px"></canvas>      </body>  <script type="text/javascript">var aa=14;    var chess = document.getElementById("mycanvas");    var context = chess.getContext('2d');    //  var context2 = chess.getContext('2d');    //      context.strokeStyle = 'yellow';    var tree = [];//存放是否聯通    var isling=[];//判斷是否相連    for(var i=0;i<aa;i++){        tree[i]=[];        for(var j=0;j<aa;j++){            tree[i][j]=-1;//初始值為0        }    }  for(var i=0;i<aa*aa;i++){        isling[i]=[];        for(var j=0;j<aa*aa;j++){            isling[i][j]=-1;//初始值為0        }    }        function drawChessBoard(){//繪畫        for(var i=0;i<aa+1;i++){            context.strokeStyle='gray';//可選區域            context.moveTo(15+i*30,15);//垂直方向畫15根線,相距30px;            context.lineTo(15+i*30,15+30*aa);            context.stroke();            context.moveTo(15,15+i*30);//水平方向畫15根線,相距30px;棋盤為14*14;            context.lineTo(15+30*aa,15+i*30);            context.stroke();        }    }    drawChessBoard();//繪制棋盤       //      var mymap=new Array(36);    //      for(var i=0;i<36;i++)    //     {mymap[i]=-1;}  </script></html>

實現效果


在這里插入圖片描述

畫迷宮

隨機迷宮怎么生成?怎么搞?一臉懵逼。

因為我們想要迷宮,那么就需要這個迷宮出口和入口有連通路徑,你可能壓根不知道迷宮改怎么生成,用的什么算法。小聲BB:用并查集(不相交集合)。

迷宮和不相交集合有什么聯系呢?(規則)

之前筆者在前面數據結構與算法系列中曾經介紹過并查集(不相交集合),它的主要功能是森林的合并,不聯通的通過并查集能夠快速將兩個森林合并,并且能夠快速查詢兩個節點是否在同一個森林中!

我們的隨機迷宮:在每個方格都不聯通的情況下,是一個棋盤方格,這也是它的初始狀態。而這個節點可以跟鄰居可能相連,也可能不相連。我們可以通過并查集實現。

具體思路為:(主要理解并查集)

1:定義好不想交集合的基本類和方法(search,union等)
2:數組初始化,每一個數組元素都是一個集合,值為-1
3:隨機查找一個格子(一維數據要轉換成二維,有點麻煩),在隨機找一面墻(也就是找這個格子的上下左右),還要判斷找的格子出沒出界。
具體在格子中找個隨機數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 neihbour=getnei(num);        if(search(num)==search(neihbour)){continue;}        else//不在一個上        {           isling[num][neihbour]=1;isling[neihbour][num]=1;            drawline(num,neihbour);//劃線            union(num,neihbour);                 }    }

那么在前面的代碼為

<!DOCTYPE html><html>  <head>    <title>MyHtml.html</title>	  </head>   <body>  <canvas id="mycanvas" width="600px" height="600px"></canvas>      </body>  <script type="text/javascript">//自行添加上面代碼    //      var mymap=new Array(36);    //      for(var i=0;i<36;i++)    //     {mymap[i]=-1;}    function getnei(a)//獲得鄰居號  random    {        var x=parseInt(a/aa);//要精確成整數        var y=a%aa;        var mynei=new Array();//儲存鄰居        if(x-1>=0){mynei.push((x-1)*aa+y);}//上節點        if(x+1<14){mynei.push((x+1)*aa+y);}//下節點        if(y+1<14){mynei.push(x*aa+y+1);}//有節點        if(y-1>=0){mynei.push(x*aa+y-1);}//下節點        var ran=parseInt(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]);//不能壓縮路徑路徑壓縮        }        else            return 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]);//不能路徑壓縮        }        else            return -tree[parseInt(a/aa)][a%aa];    }    function union(a,b)//合并    {        var a1=search(a);//a根        var b1=search(b);//b根        if(a1==b1){}        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 x1=parseInt(a/aa);        var y1=a%aa;        var x2=parseInt(b/aa);        var y2=b%aa;                var x3=(x1+x2)/2;        var y3=(y1+y2)/2;        if(x1-x2==1||x1-x2==-1)//左右方向的點  需要上下劃線        {            //alert(x1);            //  context.beginPath();            context.strokeStyle = 'white';            //    context.moveTo(30+x3*30,y3*30+15);//            //   context.lineTo(30+x3*30,y3*30+45);            context.clearRect(29+x3*30, y3*30+16,2,28);            //    context.stroke();        }        else        {            //   context.beginPath();            context.strokeStyle = 'white';            //  context.moveTo(x3*30+15,30+y3*30);//            //    context.lineTo(45+x3*30,30+y3*30);            context.clearRect(x3*30+16, 29+y3*30,28,2);            //      context.stroke();        }    }         while(search(0)!=search(aa*aa-1))//主要思路    {        var num = parseInt(Math.random() * aa*aa );//產生一個小于196的隨機數        var neihbour=getnei(num);        if(search(num)==search(neihbour)){continue;}        else//不在一個上        {           isling[num][neihbour]=1;isling[neihbour][num]=1;            drawline(num,neihbour);//劃線            union(num,neihbour);                 }    }  </script></html>

實現效果:


在這里插入圖片描述
在這里插入圖片描述

方塊移動

這部分我采用的方法不是動態真的移動,而是一格一格的跳躍。也就是當走到下一個格子將當前格子的方塊擦掉,在移動的那個格子中再畫一個方塊。選擇方塊是因為方塊更方便擦除,可以根據像素大小精準擦除。

另外,再移動中要注意不能穿墻、越界。那么怎么判斷呢?很好辦,我們再前面會判斷兩個格子是否聯通,如果不連通我們將把這個墻拆開。再拆的時候把這個墻的時候記錄這兩點拆墻可走即可(數組)

另外,事件的監聽上下左右查一查就可以得到,添加按鈕對一些事件監聽,這些不是最主要的。

為了豐富游戲可玩性,將方法封裝,可以設置關卡(只需改變迷宮大小)。這樣就可以實現通關了。另外,如果寫成動態存庫那就更好了。


在這里插入圖片描述

結語

在線嘗試地址,代碼直接查看網頁源代碼即可!

以上所述是小編給大家介紹的使用數據結構給女朋友寫個Html5走迷宮游戲,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對武林網網站的支持!
如果你覺得本文對你有幫助,歡迎轉載,煩請注明出處,謝謝!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美伊久线香蕉线新在线| 欧美激情网友自拍| 国产精品揄拍一区二区| 亚洲xxxxx性| 亚洲一区二区中文| 久久精品国产69国产精品亚洲| 国产精品毛片a∨一区二区三区|国| 久久久国产视频91| 欧美丰满老妇厨房牲生活| 日韩电影中文 亚洲精品乱码| 久久躁日日躁aaaaxxxx| 欧美视频在线观看免费网址| 26uuu另类亚洲欧美日本老年| 色爱精品视频一区| 国产精品扒开腿做| 日韩av电影免费观看高清| 日本精品一区二区三区在线| 亚洲另类激情图| 国产97在线|日韩| 亚洲天堂视频在线观看| 国产视频在线观看一区二区| 日韩av一区二区在线| 91av在线视频观看| 精品性高朝久久久久久久| 亚洲第一页自拍| 国产在线拍揄自揄视频不卡99| 国外成人性视频| 日韩成人av网| 国产91精品视频在线观看| 精品久久久久久国产| 在线成人激情黄色| 在线播放精品一区二区三区| 国产欧美在线播放| 国内精品久久久久久久久| 久久综合亚洲社区| 久久久久国产精品www| 2019日本中文字幕| 日韩一区二区久久久| 亚洲福利视频久久| 97在线看福利| 亚洲国产一区二区三区在线观看| 日韩欧美中文免费| 91精品视频网站| 性欧美亚洲xxxx乳在线观看| 欧美精品videos| 成人国内精品久久久久一区| 中文字幕日本精品| 色视频www在线播放国产成人| 91免费版网站入口| 日韩在线观看免费高清完整版| 久久综合88中文色鬼| 欧美激情二区三区| 国产精品美女主播在线观看纯欲| 国产精品久久久久久久久久久不卡| 福利一区福利二区微拍刺激| 精品无人区乱码1区2区3区在线| 国产成人精品最新| 色综合久久精品亚洲国产| 国产精品自拍小视频| 精品国产拍在线观看| 国产精品美乳一区二区免费| 欧美激情女人20p| 中文字幕亚洲一区二区三区五十路| 日韩国产中文字幕| 国产精品久久久久久av福利| 国产美女久久精品| 欧美巨乳美女视频| 久青草国产97香蕉在线视频| 亚洲成人久久一区| 亚洲国产日韩欧美在线动漫| 日韩精品免费观看| 另类色图亚洲色图| 26uuu亚洲伊人春色| 成人乱色短篇合集| 欧美福利视频在线观看| 国产精品视频xxx| 亚洲国产另类 国产精品国产免费| 美女福利视频一区| 国模精品视频一区二区| 日韩国产一区三区| 亚洲精品日韩丝袜精品| 国产精品18久久久久久首页狼| 精品成人国产在线观看男人呻吟| 国外日韩电影在线观看| 热门国产精品亚洲第一区在线| 97精品伊人久久久大香线蕉| 91精品国产综合久久香蕉| 亚洲一区二区日本| 亚洲欧美精品在线| 亚洲欧洲自拍偷拍| 国产成人一区二区| 狠狠色狠狠色综合日日五| 久久久亚洲影院| 国产噜噜噜噜噜久久久久久久久| 这里精品视频免费| 国产精品都在这里| 亚洲精品aⅴ中文字幕乱码| 色婷婷av一区二区三区久久| 国产日韩欧美夫妻视频在线观看| 色噜噜狠狠狠综合曰曰曰88av| 国产99视频精品免视看7| 亚洲男人天堂2019| 欧美精品激情在线| 国产精品久久久久av免费| 日韩精品免费综合视频在线播放| 欧美性猛交xxxxx免费看| 亚洲精品国产品国语在线| 国产精品国内视频| 亚洲成年人在线播放| 黄色一区二区在线观看| 国产精品偷伦视频免费观看国产| 久久久综合免费视频| 九九九热精品免费视频观看网站| 亚洲人精选亚洲人成在线| 日本精品一区二区三区在线播放视频| 国产伦精品一区二区三区精品视频| 国产91在线播放| 久久成人av网站| 精品久久久中文| 91久久精品日日躁夜夜躁国产| 国产精品久久久久久久久久东京| 成人福利在线观看| 2019最新中文字幕| 黑人精品xxx一区一二区| 日韩精品在线观看一区二区| 蜜臀久久99精品久久久久久宅男| 亚洲最大成人网色| 97国产一区二区精品久久呦| 欧美日韩亚洲视频一区| 日韩有码在线播放| 国产精品久久久久久久久久东京| 在线观看日韩视频| 91精品国产777在线观看| 91美女片黄在线观| 亚洲 日韩 国产第一| 色无极亚洲影院| 久久久欧美精品| 国产一区二区三区在线免费观看| 久久福利视频网| 一区二区在线视频| 91精品国产91久久| 成人免费网视频| 蜜臀久久99精品久久久久久宅男| 日韩av观看网址| 91精品国产91久久| 久久久人成影片一区二区三区| 欧美一区二区三区四区在线| 亚洲国产精品免费| 91高清在线免费观看| 亚洲a∨日韩av高清在线观看| 最近2019中文字幕第三页视频| 91精品国产99久久久久久| 国产成人在线一区二区| 国产在线精品自拍| 久久久影视精品| 97久久精品在线| 久久久成人精品| 久久视频中文字幕| 97国产在线视频| 欧美精品手机在线| 精品亚洲国产成av人片传媒| 欧美午夜精品在线| 国产免费一区二区三区香蕉精| 欧美日韩福利视频|