JS實現貪喫蛇
1.結構
創建一個盒子box作爲蛇的身體,當前盒子中只有一個子元素,代表此時蛇的長度爲1.
在創建一個盒子food作爲貪喫蛇的食物。
<div id="box">
<div></div>
</div>
<div id="food"></div>
2.CSS
設置蛇和食物的樣式,這裏注意蛇和食物都是絕對定位。
<style>
*{
padding: 0px;
margin: 0px;
}
#box div{
width: 30px;
height: 30px;
box-sizing: border-box;
background: green;
border: 1px solid black;
position: absolute;
}
#food{
width: 30px;
height: 30px;
background: brown;
position: absolute;
}
</style>
3.腳本
獲取蛇的身體和每一個子元素
var box = document.getElementById("box");
var boxs = document.getElementById("box").children;
定義蛇頭的位置
var snackX = 0;
var snackY = 0;
獲取屏幕寬度和高度,以此來設定牆的邊界,以限制蛇的移動範圍。
var cw = document.documentElement.clientWidth;
var ch = document.documentElement.clientHeight;
var minsnackX = 0;
var maxsnackX = Math.floor(cw / boxs[0].offsetWidth)*boxs[0].offsetWidth;
var minsnackY = 0;
var maxsnackY = Math.floor(ch / boxs[0].offsetHeight)*boxs[0].offsetHeight;
定義初始的移動方向。
var turn = "right";
獲取食物元素,並設置食物的位置座標。
var foodele = document.getElementById("food");
var foodX,foodY;
蛇的初始化
for(var i = 0; i <6 ; i++){
box.appendChild(boxs[0].cloneNode(true));
}
刷新食物
function food(){
//此處的座標要先獲取頁面最大支持的蛇身體的塊數,然後在塊數中隨機,然後乘以塊數的大小,
//因爲蛇的移動每一步都是固定的,想要判定食物和蛇頭重合就必須座標是整塊的倍數。
foodX = parseInt( Math.random()*Math.floor(cw / boxs[0].offsetWidth))*boxs[0].offsetWidth;
foodY = parseInt( Math.random()*Math.floor(ch / boxs[0].offsetHeight))*boxs[0].offsetHeight;
//判定當食物的產生位置和蛇的任何一個位置重合時就重新生成食物。
for(var i = 0;i<boxs.length;i++){
if(foodX + "px" === boxs[i].style.left && foodY + "px" === boxs[i].style.top){
food();
}
}
foodele.style.left = foodX + "px";
foodele.style.top = foodY + "px";
}
調用food()方法 生成第一個食物
food();
設置定時器 每次執行一次蛇的運行方法
var timer = setInterval(function(){
snackMOve();
},150)
封裝一個蛇的運動方法
//移動和判定邊界
function snackMOve(){
//此處爲判定方向 根據判定的方向,向改方向前進一個方塊
switch(turn){
case "right":snackX +=30;break;
case "left":snackX -=30;break;
case "bottom":snackY +=30;break;
case "top":snackY -=30;break;
}
//如果蛇越過了牆就從另一端出現
if(snackX > maxsnackX){
snackX = 0;
}
if(snackX < minsnackX){
snackX = maxsnackX;
}
if(snackY > maxsnackY){
snackY = 0;
}
if(snackY < minsnackY){
snackY = maxsnackY;
}
//從最後一個開始,每個元素跟隨上一個元素的位置
for(var i = boxs.length-1; i >0 ; i--){
boxs[i].style.left = boxs[i-1].style.left;
boxs[i].style.top = boxs[i-1].style.top ;
}
//第一個也就是蛇頭的位置,永遠是根據方向獲取的位置
boxs[0].style.left = snackX + "px";
boxs[0].style.top = snackY + "px" ;
//判定喫到食物 就長大和刷新
//當蛇頭位置移動之後與食物重合 那麼刷新食物,並且在蛇的身體中插入一個克隆的元素,相當於長度+1
if(snackX === foodX && snackY === foodY){
food();
box.appendChild(boxs[0].cloneNode(true));
}else{
//判定撞死
//當蛇頭與身體中的任何一個元素重合,那麼判定結束遊戲,停止定時器
for(var i = 1;i<boxs.length;i++){
if(snackX + "px" === boxs[i].style.left && snackY + "px" === boxs[i].style.top){
clearInterval(timer);
alert("失敗");
}
}
}
}
蛇的運動方向
document.onkeydown = function(eve){
var e = eve||event;
var keyCode = e.keyCode||e.which;
switch(keyCode){
case 37:if(turn === "right"){break;}turn = "left";break;
case 38:if(turn === "bottom"){break;}turn = "top";break;
case 39:if(turn === "left"){break;}turn = "right";break;
case 40:if(turn === "top"){break;}turn = "bottom";break;
}
}
全部代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
*{
padding: 0px;
margin: 0px;
}
#box div{
width: 30px;
height: 30px;
box-sizing: border-box;
background: green;
border: 1px solid black;
position: absolute;
}
#food{
width: 30px;
height: 30px;
background: brown;
position: absolute;
}
</style>
</head>
<body>
<div id="box">
<div></div>
</div>
<div id="food"></div>
<script>
var box = document.getElementById("box");
var boxs = document.getElementById("box").children;
var snackX = 0;
var snackY = 0;
var cw = document.documentElement.clientWidth;
var ch = document.documentElement.clientHeight;
var minsnackX = 0;
var maxsnackX = Math.floor(cw / boxs[0].offsetWidth)*boxs[0].offsetWidth;
var minsnackY = 0;
var maxsnackY = Math.floor(ch / boxs[0].offsetHeight)*boxs[0].offsetHeight;
var turn = "right";
var foodele = document.getElementById("food");
var foodX,foodY;
for(var i = 0; i <6 ; i++){
box.appendChild(boxs[0].cloneNode(true));
}
//隨機食物
function food(){
foodX = parseInt( Math.random()*Math.floor(cw / boxs[0].offsetWidth))*boxs[0].offsetWidth;
foodY = parseInt( Math.random()*Math.floor(ch / boxs[0].offsetHeight))*boxs[0].offsetHeight;
for(var i = 0;i<boxs.length;i++){
if(foodX + "px" === boxs[i].style.left && foodY + "px" === boxs[i].style.top){
food();
}
}
foodele.style.left = foodX + "px";
foodele.style.top = foodY + "px";
}
food();
//設置定時器 移動
var timer = setInterval(function(){
snackMOve();
},150)
//移動和判定邊界
function snackMOve(){
switch(turn){
case "right":snackX +=30;break;
case "left":snackX -=30;break;
case "bottom":snackY +=30;break;
case "top":snackY -=30;break;
}
//根據邊界歸零
if(snackX > maxsnackX){
snackX = 0;
}
if(snackX < minsnackX){
snackX = maxsnackX;
}
if(snackY > maxsnackY){
snackY = 0;
}
if(snackY < minsnackY){
snackY = maxsnackY;
}
for(var i = boxs.length-1; i >0 ; i--){
boxs[i].style.left = boxs[i-1].style.left;
boxs[i].style.top = boxs[i-1].style.top ;
}
boxs[0].style.left = snackX + "px";
boxs[0].style.top = snackY + "px" ;
//判定喫到食物 就長大和刷新
if(snackX === foodX && snackY === foodY){
food();
box.appendChild(boxs[0].cloneNode(true));
}else{
//判定撞死 暫停計時器 刷新
for(var i = 1;i<boxs.length;i++){
// console.log(boxs[i].style.left);
if(snackX + "px" === boxs[i].style.left && snackY + "px" === boxs[i].style.top){
clearInterval(timer);
alert("失敗");
// console.log(1)
}
}
}
}
//方向
document.onkeydown = function(eve){
var e = eve||event;
var keyCode = e.keyCode||e.which;
switch(keyCode){
case 37:if(turn === "right"){break;}turn = "left";break;
case 38:if(turn === "bottom"){break;}turn = "top";break;
case 39:if(turn === "left"){break;}turn = "right";break;
case 40:if(turn === "top"){break;}turn = "bottom";break;
}
}
</script>
</body>
</html>
總結
貪喫蛇的思路主要是有以下幾個部分
1.食物的隨機出現(不能隨機在蛇身上)
2.定時器控制蛇的移動
3.牆的判定
4.蛇的運動邏輯
5.運動方向的判定
6.喫到食物的判定
7.蛇頭與身體的判定(即遊戲結束的判定)