基于JS制作一個(gè)簡(jiǎn)易的2048游戲
效果圖
實(shí)現(xiàn)代碼
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> <title>2048</title> <style type="text/css"> .basic{ height:80px; width:80px; background-color:#DBDBDB; float:left; margin:2px; } .row{ height:80px; clear:both; } </style> </head> <body> <div id="pool"></div> <div id="sample" class="basic" style='opacity: 0;'></div> <div>score:<span id='score' style="font-size:200%;font-weight:bold;"></span></div> <script type="text/javascript" > //對(duì)象內(nèi)使用,要加this var container={ rowNum:4, colNum:4, score:0,//靠弄個(gè)Cookie記錄下游戲記錄 isMoved:false,//Block 有沒(méi)有移動(dòng)過(guò) content:[],//{x:col,y:row,v:value} colour:['#DBDBDB','#56A36C','#EFCEE8', '#81C2D6','#8192D6','#D9B3E6', '#DCF7A1','#83FCD8','#E8F2FF', '#91C6FF','#B8F788','#58D2E8', '#F2B6B6','#E8ED51','#FFE3FB', '#E8FF8C','#FFDEC9','#F5A433', '#E6109B','#96C4E6','#E560CD'], colourObject:{}, //初始化 背景 loadBackground:function(){ var pool = document.getElementById("pool"); var sample = document.getElementById("sample") var margin = 2; var dotWidth = parseFloat(sample.offsetWidth) + margin;//基本方塊寬度 + margin for(var i = 0; i != this.rowNum; i++){ //創(chuàng)建行 var rDiv = document.createElement("div"); rDiv.setAttribute('id','r' + i); rDiv.setAttribute('class','row'); for(var j = 0; j != this.colNum; j++){ var cDiv = document.createElement("div"); cDiv.setAttribute('id','c'+j + '_r' + i); cDiv.setAttribute('class','basic'); rDiv.appendChild(cDiv); } rDiv.setAttribute('width',(this.colNum * (dotWidth + margin)) + 'px') pool.appendChild(rDiv); } }, findBlock:function(colx, rowy){ return this.content.find(function(value){ return value.x == colx && value.y == rowy; }); }, addBlockToMine:function(){//開(kāi)局或移動(dòng)后,添加新塊 var zeroBlockArray = this.content.filter(function(value){ return value.v == 0; }); if(zeroBlockArray.length != 0){ zeroBlockArray[this.makeRandomInteger(zeroBlockArray.length)].v = (this.makeRandomInteger(2) + 1) * 2; } }, makeRandomInteger:function(scope){ return Math.floor(Math.random() * scope); }, checkDeath:function(){ if(this.content.filter(function(value){ return value.v == 0; }).length != 0){ return false;//有零塊就表示沒(méi)有死 }else{ //滿格時(shí),檢測(cè)相鄰之間可合并的可能性//Jallen Kwong //再?zèng)]有合并的可能,沒(méi)有的話,游戲就結(jié)束 //窮舉法(不聰明的方法) for(var i = 0; i < this.rowNum; i++){ if(i != this.rowNum - 1){ for(var j = 0;j < this.colNum; j++){ var mainBlock = this.findBlock(j, i); var downBlock = this.findBlock(j, i + 1); if(j != this.colNum - 1){ var rightBlock = this.findBlock(j + 1,i); if(mainBlock.v == rightBlock.v || mainBlock.v == downBlock.v){ return false; } }else{ if(mainBlock.v == downBlock.v){ return false; } } } }else{ for(var j = 0;j < this.colNum - 1; j++){ var mainBlock = this.findBlock(j, i); var rightBlock = this.findBlock(j + 1, i); if(mainBlock.v == rightBlock.v){ return false; } } } } return true;//真的Game Over } }, refresh:function(){//刷新顯示頁(yè)面 for(var row = 0;row < this.rowNum;row++){ for(var col = 0;col < this.colNum;col++){ var value = this.findBlock(col,row).v; var elem = document.getElementById('c'+col+'_r'+row); elem.style.backgroundColor = this.colourObject[value] == undefined?this.colourObject[0]:this.colourObject[value]; elem.innerHTML = (value == 0 ? "" : "<span style='font-size:200%;font-weight:bold;'>"+value+"</span>"); } } document.getElementById('score').innerHTML = this.score; }, addKeyListener:function(event){ var keycode = event.keyCode; if(keycode >= 37 && keycode <= 40){ //alert(keycode); event.preventDefault(); var changeCount = 0;//記住塊有沒(méi)真正得移動(dòng)過(guò) switch(keycode){ case 37://左 //console.log(keycode); for(var i = 0; i < this.rowNum; i++){ var queue = []; var flag = false; //入棧 for(var j = 0 ; j < this.colNum; j++){ var block = this.findBlock(j, i); if(block.v == 0){ continue; } flag = this.coreCalculate(block, queue, flag); } //出隊(duì)列 for(var k = 0 ;k < this.colNum; k++){ changeCount += this.outOfQueue(k, i, queue, k); } } break; case 38://上 for(var i = 0; i < this.colNum; i++){ var queue = []; var flag = false; for(var j = 0 ;j < this.rowNum; j++){ var block = this.findBlock(i, j); if(block.v == 0){ continue; } flag = this.coreCalculate(block, queue, flag); } //出隊(duì)列 for(var k = 0 ;k < this.rowNum; k++){ changeCount += this.outOfQueue(i, k, queue, k); } } break; case 39://右 for(var i = 0; i < this.rowNum; i++){ var queue = []; var flag = false; //入棧 for(var j = this.colNum - 1 ; j >= 0; j--){ var block = this.findBlock(j, i); if(block.v == 0){ continue; } flag = this.coreCalculate(block, queue, flag); } //console.log(queue); //出隊(duì)列 for(var k = this.colNum - 1 ,l = 0;k >= 0; k--,l++){ changeCount += this.outOfQueue(k, i, queue, l); } } break; case 40://下 for(var i = 0; i < this.colNum; i++){ var queue = []; var flag = false; for(var j = this.rowNum - 1 ;j >= 0; j--){ var block = this.findBlock(i, j); if(block.v == 0){ continue; } flag = this.coreCalculate(block, queue, flag); } //出隊(duì)列 for(var k = this.rowNum - 1 ,l = 0;k >= 0; k--,l++){ changeCount += this.outOfQueue(i, k, queue, l); } } break; default:break; } //要檢查content的v們有沒(méi)有改變過(guò) //1.入棧操作前,要來(lái)個(gè)數(shù)組拷貝,然后在做比對(duì),這做法并不聰明 //2.出隊(duì)列的時(shí)候,跟原來(lái)的值進(jìn)行比較,有改變 changCount++ //console.log('changeCount:' + changeCount); if(changeCount != 0){ this.addBlockToMine(); this.refresh();//刷新顯示頁(yè)面 if(this.checkDeath()){ alert("Game Over!"); document.onkeydown = function(event){ var keycode = event.keyCode; if(keycode >= 37 && keycode <= 40){ event.preventDefault(); alert("Game Over!"); } }; } } } }, init:function(){ for(var row = 0; row < this.rowNum; row++){ for(var col = 0; col < this.colNum; col++){ this.content[this.content.length] = {x:col,y:row,v:0}; } } for(var i = 0;i <= 20;i++){ if(i == 0){ this.colourObject[i] = this.colour[i]; continue; } this.colourObject[Math.pow(2,i)] = this.colour[i]; } //console.log(this.colourObject[7]); }, coreCalculate:function(block, queue, flag){ flag的作用,入棧方式有問(wèn)題,譬如2,2,4 應(yīng)得 4,4 但結(jié)果 得8 if(queue.length == 0 ){ queue[queue.length] = block.v; return flag; }else{ var tailOfQueue = queue[queue.length - 1]; if((tailOfQueue == block.v) && !flag){ this.score += (queue[queue.length - 1] = tailOfQueue * 2); return true; }else{ queue[queue.length] = block.v; return false; } } }, outOfQueue:function(colx, rowy, queue, index){ var block = this.findBlock(colx, rowy); var oldValue = block.v; block.v = queue[index] == undefined ? 0 : queue[index]; return oldValue != block.v? 1 : 0; } }; //main window.onload = function(){ container.loadBackground(); container.init(); //alert(container.findBlock(1,1).v); container.addBlockToMine(); container.addBlockToMine(); container.refresh(); document.addEventListener('keydown', function(event){ container.addKeyListener(event); }); }; </script> </body> </html>
到此這篇關(guān)于基于JS制作一個(gè)簡(jiǎn)易的2048游戲的文章就介紹到這了,更多相關(guān)JS 2048游戲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解析ScrollPic在ie8下只滾動(dòng)一遍,然后變?yōu)榭瞻?ie6,ie7,chrome,firefox正常
解析ScrollPic在ie8下只滾動(dòng)一遍,然后變?yōu)榭瞻?ie6,ie7,chrome,firefox都正常)2013-06-06Bootstrap 模態(tài)對(duì)話框只加載一次 remote 數(shù)據(jù)的完美解決辦法
前端框架 Bootstrap 的模態(tài)對(duì)話框,可以使用 remote 選項(xiàng)指定一個(gè) URL,這樣對(duì)話框在第一次彈出的時(shí)候就會(huì)自動(dòng)從這個(gè)地址加載數(shù)據(jù)到 .modal-body 中,但是它只會(huì)加載一次,不過(guò)通過(guò)在事件中調(diào)用 removeData() 方法可以解決這個(gè)問(wèn)題,具體操作方法,大家通過(guò)本文了解下吧2017-07-07一文帶你掌握J(rèn)avaScript中Moment.js如何操作日期和時(shí)間
Moment.js是一個(gè)極其強(qiáng)大的JavaScript庫(kù),專門用于解析、驗(yàn)證、操作和顯示日期和時(shí)間,下面就跟隨小編一起學(xué)習(xí)一下Moment.js的具體使用吧2024-01-01在table中插入多行的js代碼(與insertAdjacentHTML相似的功能)
在table中插入多行,能使用與insertAdjacentHTML相似的功能2010-06-06