JavaScript貪吃蛇的實(shí)現(xiàn)代碼
本文實(shí)例為大家分享了JavaScript實(shí)現(xiàn)貪吃蛇的具體代碼,供大家參考,具體內(nèi)容如下
首先我們要確定貪吃蛇應(yīng)有的功能
1.通過(guò)鍵盤(pán)的上下左右控制蛇的移動(dòng)方向
2.邊界判定,即蛇頭超出邊界則游戲結(jié)束
3.碰撞判定,即蛇頭和食物塊發(fā)生觸碰
4.吃到食物積分加1
具體實(shí)現(xiàn)
一.html代碼
<div class="container"> <!--小蛇移動(dòng)的操場(chǎng)--> <div id="playground"> <!--小蛇--> <div id="snake"></div> <!--食物--> <div id="food"></div> </div> <!--記錄得分--> <div id="menu"> <div>得分<span id="score"></span></div> </div> </div>
二.css代碼
<style> * { padding: 0; margin: 0; } .container { width: 800px; height: 600px; margin: 0 auto; } #playground { width: 650px; height: 100%; background-color: cadetblue; float: left; position: relative; } #menu { width: 150px; height: 100%; background-color: darkcyan; float: left; } #snake { width: 20px; height: 20px; background-color: #d3e0d7; position: absolute; left: 0; top: 0; } #food { width: 20px; height: 20px; background-color: #027766; position: absolute; } .body { width: 20px; height: 20px; background-color: #178b9a; position: absolute; ; top: 0; left: 0; } #score { font-size: 30px; font-weight: bold; color: black; } #menu div { font-size: 20px; font-weight: bold; margin-left: 20px; } #hqx { width: 100px; height: 50px; margin: 0 auto; } #inp { border: 0; width: 100px; height: 50px; background-color: coral; } </style>
三.開(kāi)始實(shí)現(xiàn)具體功能
1.先獲取節(jié)點(diǎn),設(shè)置全局變量
//獲取節(jié)點(diǎn) var snake = document.getElementById("snake"); var food = document.getElementById("food"); var playground = document.getElementById("playground"); var score = document.getElementById('score'); // var inp = document.getElementById('inp') /*設(shè)置全局變量*/ var timer; var arr = []; //存放蛇的位置的數(shù)組 var num = 0; //數(shù)組的長(zhǎng)度 var snakeBody; //每次吃調(diào)一個(gè)食物,增加的身體
2.設(shè)置按鍵事件,并判斷邊界碰撞,碰撞時(shí)游戲結(jié)束。這一塊代碼我遇到了一個(gè)問(wèn)題,就是當(dāng)我用if(){return}跳出事件,會(huì)結(jié)束所有代碼,后面的代碼就不會(huì)執(zhí)行了,然后我換成了switch(){ case: break;}就實(shí)現(xiàn)效果了
//設(shè)置按鍵事件 document.onkeydown = function (e) { var evt = window.evnet || e; switch (evt.keyCode) { case 37: //左 clearInterval(timer); timer = window.setInterval(runLeft, 10); //向左移動(dòng)的時(shí)間器 function runLeft() { if (snake.offsetLeft > 0) { snake.style.left = snake.offsetLeft - 1 + 'px'; //實(shí)現(xiàn)自己動(dòng) snake.style.top = snake.offsetTop + 'px'; //高度不變 arr.push([snake.offsetLeft, snake.offsetTop]); //每移動(dòng)1px,就將位置存進(jìn)數(shù)組中 num++; //相應(yīng)的數(shù)組長(zhǎng)度加1 } else { clearInterval(timer); //清除定時(shí)器 alert('you die') //彈出失敗信息 document.onkeydown = null //結(jié)束按鍵 } } break; //結(jié)束當(dāng)前按鍵 case 38: //上 clearInterval(timer); timer = window.setInterval(runTop, 10); function runTop() { if (snake.offsetTop > 0) { snake.style.top = snake.offsetTop - 1 + 'px'; snake.style.left = snake.offsetLeft + 'px'; arr.push([snake.offsetLeft, snake.offsetTop]); num++; } else { clearInterval(timer); alert('you die') document.onkeydown = null } } break; case 39: //右 clearInterval(timer); timer = window.setInterval(runRight, 10); function runRight() { if (snake.offsetLeft < 630) { snake.style.left = snake.offsetLeft + 1 + 'px'; snake.style.top = snake.offsetTop + 'px'; arr.push([snake.offsetLeft, snake.offsetTop]); num++; } else { clearInterval(timer); alert('you die') document.onkeydown = null } } break; case 40: //下 clearInterval(timer); timer = window.setInterval(runBottom, 10); function runBottom() { if (snake.offsetTop < 580) { snake.style.top = snake.offsetTop + 1 + 'px'; snake.style.left = snake.offsetLeft + 'px'; arr.push([snake.offsetLeft, snake.offsetTop]); num++; } else { clearInterval(timer); alert('you die') document.onkeydown = null } } break; }
3.封裝一個(gè)函數(shù),隨機(jī)生成食物位置,第一次粗心忘記加單位,看網(wǎng)頁(yè)沒(méi)效果,才知道忘記加單位了
function pos() { food.style.left = parseInt(Math.random() * 630) + 'px'; food.style.top = parseInt(Math.random() * 580) + 'px'; }
4.封裝一個(gè)碰撞判定函數(shù),使其碰撞時(shí),食物消失,蛇的身體增加一塊。這里遇到一個(gè)定時(shí)器問(wèn)題,第一次寫(xiě)的時(shí)候,我的定時(shí)器清除標(biāo)識(shí)和之前的定時(shí)器標(biāo)識(shí)一致,導(dǎo)致蛇會(huì)上下左右抖動(dòng),經(jīng)過(guò)后面不停的修改,最終找到錯(cuò)誤。
var timer1 = setInterval(eat, 10); //設(shè)置一個(gè)碰撞的時(shí)間器 function eat() { snakeCrashFood(snake, food); //傳入?yún)?shù) function snakeCrashFood(obj1, obj2) { var obj1Left = obj1.offsetLeft; var obj1Width = obj1.offsetWidth + obj1.offsetLeft; var obj1Top = obj1.offsetTop; var obj1Height = obj1.offsetHeight + obj1.offsetTop; var obj2Left = obj2.offsetLeft; var obj2Width = obj2.offsetWidth + obj2.offsetLeft; var obj2Top = obj2.offsetTop; var obj2Height = obj2.offsetHeight + obj2.offsetTop; if (!((obj1Width < obj2Left) || (obj2Width < obj1Left) || (obj1Height < obj2Top) || ( obj2Height < obj1Top))) { snakeBody = document.createElement("div"); //生成新的div snakeBody.setAttribute("class", "body"); //給新的div添加類名 playground.appendChild(snakeBody); //添加一節(jié)新的身體 pos(); //讓食物重新隨機(jī)出現(xiàn) setInterval(follow, 10); //動(dòng)態(tài)地改變新的身體的位置 } } }
5.設(shè)置蛇的身體跟隨,獲得蛇身體的數(shù)組,新的身體相對(duì)于上一個(gè)身體的第20個(gè)數(shù)組的位置。這里我遇到了一個(gè)數(shù)組越界問(wèn)題。最開(kāi)始初始num值為0,place=20,所以第一次身體的增加arr[num-place][0]前面的索引是從負(fù)數(shù)開(kāi)始,在通過(guò)老師的指導(dǎo),增加一個(gè)判定,解決了這個(gè)問(wèn)題。
function follow() { /*獲得增加的身體的數(shù)組*/ var bodyNum = document.getElementsByClassName("body"); score.innerHTML = bodyNum.length; var place = 0; /*數(shù)組每移動(dòng)1px,新的身體的位置就是相對(duì)于前一個(gè)身體的第20個(gè)數(shù)組的位置,后面依次加等*/ // console.log("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1") // console.log("arr : ==" + arr) // console.log("num : ==" + num) //2 for (var i = 0; i < bodyNum.length; i++) { // console.log("bodyNum.length : ==" + bodyNum.length) place += 20; // console.log("place : ==" + place)//20 // console.log("num - place : ==" + (num - place))//-18 // bodyNum[i].style.left = arr[num - place][0] + 'px'; // bodyNum[i].style.top = arr[num - place][1] + 'px'; if (num - place > 0) { bodyNum[i].style.left = arr[num - place][0] + 'px'; bodyNum[i].style.top = arr[num - place][1] + 'px'; } } // console.log("num555 : ==" + num) // console.log("===========================================") }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
springMVC + easyui + $.ajaxFileUpload實(shí)現(xiàn)文件上傳注意事項(xiàng)
在使用easyUI做前端樣式展示時(shí),遇到了文件上傳的問(wèn)題,而且是在彈出層中提交表單,想做到不刷新頁(yè)面,所以選擇了使用ajaxFileUpload插件。下面通過(guò)本文給大家分享springMVC + easyui + $.ajaxFileUpload實(shí)現(xiàn)文件上傳注意事項(xiàng),需要的朋友參考下吧2017-04-04Js判斷兩個(gè)數(shù)組是否相等的幾種常見(jiàn)場(chǎng)景
無(wú)論是在開(kāi)發(fā)中還是面試時(shí),在js中判斷變量是否相等,都是一個(gè)比較常見(jiàn)的問(wèn)題,這篇文章主要給大家介紹了關(guān)于Js判斷兩個(gè)數(shù)組是否相等的幾種常見(jiàn)場(chǎng)景,需要的朋友可以參考下2024-07-07前端使用crypto-js庫(kù)aes加解密詳細(xì)代碼示例
在前端開(kāi)發(fā)中數(shù)據(jù)的加密和解密是為了保障用戶隱私和數(shù)據(jù)的安全性而常見(jiàn)的任務(wù),這篇文章主要給大家介紹了關(guān)于前端使用crypto-js庫(kù)aes加解密的相關(guān)資料,需要的朋友可以參考下2024-03-03實(shí)例分析Array.from(arr)與[...arr]到底有何不同
這篇文章通過(guò)實(shí)例主要給大家分析介紹了關(guān)于Array.from(arr)與[...arr]到底有何不同的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用js具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04javascript自定義startWith()和endWith()的兩種方法
js中自定義startWith()和endWith()方法有兩種,在本文將為大家詳細(xì)介紹下,感興趣的朋友不要錯(cuò)過(guò)2013-11-11JavaScript實(shí)現(xiàn)區(qū)塊鏈
很多朋友都聽(tīng)說(shuō)過(guò)比特幣和以太幣這樣的加密貨幣,但是只有極少數(shù)人懂得隱藏在它們背后的技術(shù),接下來(lái)通過(guò)本文給大家介紹用JavaScript來(lái)創(chuàng)建一個(gè)簡(jiǎn)單的區(qū)塊鏈來(lái)演示它們的內(nèi)部究竟是如何工作的,感興趣的朋友一起看看吧2018-03-03基于javascript實(shí)現(xiàn)日歷功能原理及代碼實(shí)例
這篇文章主要介紹了基于javascript實(shí)現(xiàn)日歷效果原理及代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05js冒泡法和數(shù)組轉(zhuǎn)換成字符串示例代碼
將數(shù)組轉(zhuǎn)換成字符串的方法有很多,想必大家也不會(huì)陌生,下面為大家講解下js冒泡法的使用,感興趣的朋友可以參考下2013-08-08