原生js贪吃蛇
游戏的练习重点在于对javascript的基础知识的串联,以及对逻辑思路的提升。在遇到相对比较大的项目或者任务时,本着大化小的思路,从局部开始着手写代码。本次贪吃蛇分三大部分(地图,蛇,食物),在展示实际页面以后会分解讲解各个步骤。
思路分析:1、地图 2、蛇 3、食物
1、用表格table创建地图,样式渲染页面,js负责整个蛇和食物在地图上的渲染和运动。
2、蛇的身体可以看作是由表格的X,Y轴坐标点组成。X轴的第几排,Y轴的第几排。
3、上下左右键控制蛇移动的方向
css样式代码
<style>
*{
margin: 0;
padding: 0;
}
body{
background: -webkit-linear-gradient(left,pink,skyblue);
background: -moz-linear-gradient(left,pink,skyblue);
background: -o-linear-gradient(left,pink,skyblue);
}
table{
border-collapse: collapse;
margin: 40px auto;
}
td{
width: 28px;
height: 28px;
border: 1px solid white;
text-align: center;
line-height: 28px;
}
caption{
color: #282828;
font-size: 25px;
font-family: serif;
text-align: center;
}
</style>
html代码
<body>
<table>
tr*20>td*20 </*此处20后面手动按tab省略喽!!!*/>
</table>
</body>
script代码
<script>
var score = 0; // 创建分数
var direction = "right"; // 默认方向为右
var json = [ //将蛇身保存在json中
{"row":6,"col":8},
{"row":6,"col":7},
{"row":6,"col":6},
{"row":6,"col":5},
{"row":6,"col":4},
{"row":6,"col":3}
]
function snake(row,col,color){ // 获取蛇身体,横纵“十”坐标确认
document.getElementsByTagName("tr")[row].getElementsByTagName("td")[col].style.backgroundColor = color
}
function snakeArr(){
//蛇会在碰到自己身体也触发die死亡函数。
//循环需要从1开始循环,因为需要判断的是蛇头部和除蛇头以外的身体部分的坐标位置是否
//相等,如果判断相等说明接触了,那么执行die死亡函数。
for(let i=1; i<json.length; i++){
if(json[0].row == json[i].row && json[0].col == json[i].col){
die()
}
}
//调用蛇身体的函数,将json数据渲染给表格
for(let i=0; i<json.length; i++){
snake(json[i].row,json[i].col,"rgba(0,0,0,.3)")
}
}
snakeArr() //创建好蛇函数以后需要调用一次。
function clear(){ //每次清屏,蛇向前走是复制一份向前移动一格。然后清除前一次的那条蛇
for(var i=0; i<20; i++){
for(var j=0; j<20; j++){
snake(i,j,"") //让snake这个函数的tr,td为i,j,颜色为空串
}
}
}
function food(){ // 创建食物函数
for(var i=0; i<20; i++){
for(var j=0; j<20; j++){
document.getElementsByTagName("tr")[i].getElementsByTagName("td")[j].innerHTML = ""
}
}
do{
var randomRow = parseInt(Math.random() * 20);//随机食物的X轴位置
var randomCol = parseInt(Math.random() * 20);//随机食物的Y轴位置
var lock = false
//随机出来的食物不能和蛇的身体重合(不能随机出来在蛇身上)
// 遍历一遍当前的蛇,判断它的身体的每个位置的坐标是否和随机出来的XY有重合的
// 如果有重合,那么让lock为true。不退出do循环继续再循环一组XY出来进行判断
for(let i=0; i<json.length; i++){
if(json[i].row == randomRow && json[i].col == randomCol){
lock = true
}
}
}while(lock) // 设置一个lock让它正向循环。
document.getElementsByTagName("tr")[randomRow].getElementsByTagName("td")[randomCol].innerHTML = "?" //让随机出来的X和Y赋值给table.让它的innerHTML为小蘑菇(食物)
}
food() //创建好食物函数以后需要调用才执行
//Dom事件配合方向,控制蛇的运动方向
document.onkeydown = function(event){
switch(event.keyCode){
case(37):
//蛇在正向移动的时候是不能按反方向键让它后退的,所以进行键盘按键的判断。
//如果蛇正在向右走,再按左键就不会触发,直接return退出。下面同理。
if(direction == "right") return
direction = "left";
break;
case(38):
if(direction == "down") return
direction = "top";
break;
case(39):
if(direction == "left") return
direction = "right";
break;
case(40):
if(direction == "top") return
direction = "down";
break;
}
}
function die(){ // 蛇如果碰壁,死亡的函数。让定时器停止就好了。
alert("Game Over");
clearInterval(timer);
}
var timer = setInterval(function(){//调用定时器,让蛇开始动,头增尾删。pop和unshift
clear(); //每次渲染一个蛇,就调用这个删除前一个蛇的方法
switch(direction){ //判断蛇运动的方向
case("left"):
//如果蛇身体左边的值小于0,也就是到地图的尽头,让它执行死亡的函数。
if(json[0].col-1 < 0){
die();
return
}
//蛇向左移动的时候,行不变(row不变),纵坐标变化(col每次减少一格)。
//让蛇(数组)的前面添加一格。
json.unshift({"row":json[0].row,"col":json[0].col-1});
break;
case("top"):
//如果蛇身体上边的值小于0,也就是到地图的尽头,让它执行死亡的函数。同left。
if(json[0].row-1 < 0){
die();
return
}
//蛇向上移动的时候,行变化(row向上移动减少),纵坐标不变化。
json.unshift({"row":json[0].row-1,"col":json[0].col});
break;
case("right"):
//蛇向右边移动,行不变,如果纵轴大于19也意味碰壁。触发die死亡函数。
if(json[0].col+1 > 19){
die();
return
}
json.unshift({"row":json[0].row,"col":json[0].col+1});
break;
case("down"):
if(json[0].row+1 > 19){
die();
return
}
json.unshift({"row":json[0].row+1,"col":json[0].col});
break;
}
//判断蛇的头部坐标(json[0].row)(json[0].col)是否等于随机出来的食物。
// 如果不等于,说明没有接触到食物,那么让它继续删除后一部分。
if(document.getElementsByTagName("tr")[json[0].row].getElementsByTagName("td")[json[0].col].innerHTML != "?"){
json.pop();
}else{
//否则等于,那么让它不执行删除。反过来说就是增长了一格。然后继续随机食物。
food();
score++;//分数++;
document.getElementsByTagName("caption")[0].innerHTML = "当前分数是:" + score
}
//每次执行新的蛇会出来。
snakeArr();
},150)
</script>