实现效果
1、CSS文件
base.css文件
html ,body{/*逗号表示并集选择器*/
width: 100%;
}
.map{
width: 90px;
height: 90px;
margin: 50px auto;
background-color:#ccc;
}
.map ul{
height: 30px;
}
.map ul li{
width: 28px;
height: 28px;
border: 1px solid #af0;
float: left;
}
.map ul li.snake{
/*交集选择器*/
background-color: blue;
}
.map ul li.egg{
background-color: crimson;
}
reset.css文件
* {
/*去掉所有标签的内外边距*/
padding:0;
margin:0;
}
ul{
list-style: none;
}
2、JS文件
msk.js
// 1.0 获取相关元素
var box = document.querySelector(".msk");
var tips = document.querySelector(".tips");
var restartBtn = document.querySelector(".restart_btn");
var quxiaoBtn = document.querySelector(".quxiao_btn");
// 2.0 封装一个方法
function show(str , callback){
// 2.0.1 显示msk盒子
box.style.display = "block";
// 2.0.2 设置提示语
tips.innerHTML = str;
// 2.0.3 再玩一次
restartBtn.onclick = function(){
// 2.0.6 隐藏msk盒子
box.style.display = "none";
// 2.0.4
if(callback){ //判断是否存在回调函数
callback();//是 调用
}
}
// 2.0.5 隐藏msk盒子
quxiaoBtn.onclick = function(){
// 2.0.6 隐藏msk盒子
box.style.display = "none";
}
}
snake.js
/*
//console.log("text")
//定义变量
//获取.map这个标签
var ele = document.querySelector('.map');
var resultEle = document.querySelector(".result span")
//定义多少行多少列
var rowCount = 15;
var colCount = 15;
//定义列的大小
var space = 30;
//设置map的宽度和高度
ele.style.width = colCount * space + "px";
ele.style.height = rowCount * space + "px";
//定义一个 数组,记录所有的li标签
var ali = [];
//循环 创建ul标签,没循环一次,创建一个标签
for (var i = 0; i < rowCount; i++) {
var ulCreate = document.createElement("ul");
//定义小数组,记录每一行有多少个标签
var rowArr = [];
//循环创建li标签
for (var j = 0; j < colCount; j++) {
//没循环一次,创建一个li标签
var liCreate = document.createElement("li");
//往数组(小)里面,添加一个li
rowArr.push(liCreate);
ulCreate.appendChild(liCreate);
}
//往map标签(ele)添加ulCreate标签
ele.appendChild(ulCreate);
//把小数组添加到大数组里面去
ali.push(rowArr);
}
//绘制蛇(代表蛇的li标签,类名snake)
//定义数组
console.log(ali)
var snakeBody = [];
for (var k = 0; k < 3; k++) {
ali[0][k].className = "snake";
snakeBody.push(ali[0][k]);
}
//绘制食物
console.log(snakeBody)
var eggX = 0;
var eggY = 0;
//产生随机数的函数
function rd(max, min) {
//产生0-10之间的随机数,带小数点
//产生指定范围的随机数,带小数点
return Math.floor(Math.random() * (max - min) + min);
//Math.random()*10
}
//产生食物的坐标
function createFood() {
eggX = rd(colCount - 1, 0);
//创建行
eggY = rd(rowCount - 1, 0);
if (ali[eggY][eggX].className == "snake") {
createFood();
}
else {
ali[eggY][eggX].className = "egg";
}
}
createFood();
//分数的变量
//1、控制蛇的移动方向 蛇移动的坐标(默认)
var x = 2;
var y = 0;
//2、移动方向
var direction = "right";
//3、boolean
var isChange = false;
//4、定时器函数
var timer = setInterval(move, 200);
//5、编写移动的逻辑
function move() {
//控制流语句
switch (direction) {
//向右边
case "right":
x++;
break;
case "left":
x--;
break;
case "down":
y++;
break;
case "up":
y--;
break;
}
//判断蛇移动的范围
if (x < 0 || x > (colCount - 1) || y < 0 || y > (rowCount - 1)) {
//提示
alert("游戏结束!")
//停止定时器函数
clearInterval(timer)
return;
}
//判断蛇吃到食物的时候
if (eggX == x && eggY == y) {
//设置食物的背景色
ali[eggY][eggX].className = "snake";
//把食物的标签添加到snakebody
snakeBody.push(ali[eggY][eggX]);
createFood();
//加分
score = score + 1;
//显示分数
resultEle.innerHTML = score;
}
else {
//设置蛇数组的第一个元素的类名
snakeBody[0].className = "";
//删除蛇数组的第一个元素
snakeBody.shift();
//添加下一个元素
snakeBody.push(ali[y][x]);
//给下一个元素设置类名
ali[y][x].className = "snake";
}
//ali[y][x].className = "snake";
}
//通过键盘事件改变
document.onkeydown = function (evt) {
//防止连续快速按键
if (isChange) {
return;
}
//如果蛇正朝着,右边走,按左边键盘无效
var code = evt.keyCode;
if (direction == "right" && code == 37) {
return;
}
if (direction == "left" && code == 39) {
return;
}
if (direction == "down" && code == 38) {
return;
}
if (direction == "up" && code == 40) {
return;//终止代码
}
switch (code) {
case 40:
direction = "down";
isChange = true;
break;
case 38:
direction = "up";
isChange = true;
break;
case 39:
direction = "right";
isChange = true;
break;
case 37:
direction = "left";
isChange = true;
break;
}
//延迟200ms
setTimeout(function () {
isChange = false;
}, 200)
}
*/
//console.log("test")// 检查代码
// 1.0 定义变量
// 1.0.1 获取.map这个标签
var ele = document.querySelector('.map');
var resultEle = document.querySelector(".result span");
// 1.0.2 定义多少行
var rowCount = 15;
// 2.0.3 定义多少列
var colCount = 15;
// 2.0.4 定义列的大小
var space = 30;
// 2.0.5 设置map的宽度高度
ele.style.width = colCount * space + "px";
ele.style.height = rowCount * space + "px";
// 3.0 定义数组(大)记录所有的li标签
var aLi = [];
// 4.0 循环 创建ul标签(行)
for(var i = 0 ; i < rowCount; i++){
// 4.0.1每循环一次 创建一个ul标签
var ulCreate = document.createElement("ul")
// 4.0.2定义数组(小)记录每一行有多少个li标签
var rowArr = [];
// 4.0.3循环 创建li标签(列)
for(var j = 0 ; j < colCount ; j++){
//4.0.4 每循环一次 创建一个li标签
var liCreate = document.createElement("li");
//4.0.5往数组(小)添加li标签
rowArr.push(liCreate)
//4.0.6往ulCreate标签 添加li标签
ulCreate.appendChild(liCreate);
}
// 4.0.7往map标签(ele)添加ulCreate标签
ele.appendChild(ulCreate);
// 4.0.8 把小数组(rowArr) 添加到大数组(aLi)
aLi.push(rowArr);
}
console.log(aLi)
// 5.0 绘制蛇(代表蛇的li标签 类名 snake)
// 5.0.1 定义数组(蛇)
var snakeBody = [];
// 5.0.2 默认第一行前三个li标签为蛇
for(var k = 0 ; k < 3 ; k++){
// 5.0.3 设置第一行前三个li标签 添加类名 snake
aLi[0][k].className = "snake";
// 5.0.4 往蛇数组添加 第一行前三个li标签
snakeBody.push( aLi[0][k]);
}
console.log(snakeBody)
// 6.0 绘制食物
// 6.0.1 定义食物的x坐标
var eggX = 0;
var eggY = 0;
// 6.0.2 产生随机数的函数
function rd(max , min){
// 6.0.3 处理随机数的逻辑
// Math.random()*10 产生0-10之间随机数 带小数点
// Math.random()*10 + 10 产生10-20之间随机数 带小数点
// Math.random()*(max - min) + min ; 产生指定范围的随机数 带小数点
// Math.floor(); 向下取整 1.123123 => 1
return Math.floor(Math.random()*(max-min)+min);
}
// 6.0.3 产生食物的坐标
function createFood(){
// 6.0.4 创建 列 x colCount
eggX = rd(colCount-1,0);
// 6.0.5 创建 行 y rowCount
eggY = rd(rowCount-1,0);
// 6.0.6 判断创建的坐标对应的li标签 是否带有 snake 类名
if(aLi[eggY][eggX].className == "snake"){
// 6.0.7 重新创建食物
createFood();
}else {
// 6.0.7 设置食物的类名 egg
aLi[eggY][eggX].className = "egg";
}
}
// 6.0.8 调用创建食物的函数
createFood();
// 9.0 定义分数的变量
var score = 0;
// 7.0 控制蛇移动的方向
// 7.0.1 蛇移动的x坐标 和 y 坐标 (默认)
var x = 2;
var y = 0;
// 7.0.2 移动方向
var direction = "right";
// 7.0.3 布尔值
var isChange = false;
// 7.0.4 定时器函数
var timer = setInterval(move, 200);//1000毫秒 = 1秒
// 7.0.5 编写移动的逻辑
function move(){
// 7.0.6 控制流语句
switch(direction){
case "right": // 向右
x++;
break ;
case "left": // 向左
x--;
break ;
case "down": // 向下
y++;
break;
case "up": // 向上
y--;
break;
}
// 7.0.6.1 判断蛇移动的范围
if(x < 0 || x > (colCount-1) || y < 0 ||y > (rowCount-1)){
//alert("游戏结束! ");//提示
// 7.0.6.2 调用show方法
show("游戏结束! " ,function(){
// 7.0.6.3 分数重新计算
score = 0;
// 7.0.6.4 继续游戏(-)
// timer = setInterval(move,200);
// 刷新页面 继续游戏
window.location.reload();
})
clearInterval(timer)//停止定时器函数
return ; //终止代码
}
// 7.0.8 判断蛇吃到食物的时候
if(eggX == x && eggY == y){
// 7.0.9 设置食物的背景色
aLi[eggY][eggX].className = "snake";
// 7.0.10 把食物的标签添加到 snakeBody
snakeBody.push(aLi[eggY][eggX]);
// 7.0.11 重新创建食物
createFood();
// 7.0.12 记录分数
// score+=1;
score = score + 1;
// 7.0.17 显示分数
resultEle.innerHTML = score;
}else {
// 7.0.13 设置蛇数组的第一个元素类名
snakeBody[0].className = "";
// 7.0.14 删除蛇数组第一个元素
snakeBody.shift();
// 7.0.15 添加下一个元素
snakeBody.push(aLi[y][x]);
// 7.0.16 给下一个元素设置类名
aLi[y][x].className = "snake";
}
// 测试
// aLi[y][x].className = "snake";
}
// 8.0 通过键盘事件改变 direction 的值
document.onkeydown = function(evt){
// 8.0.4 防止连续快速按键
if(isChange){
return;//终止代码
}
// 8.0.1 键值码
var code = evt.keyCode;
// 8.0.3 移动的方向处理
// 如果蛇正朝着 右边走 ,按左边按键无效
if(direction == "right" && code == 37){
return ;//终止代码
}
if(direction == "left" && code == 39){
return ;//终止代码
}
if(direction == "down" && code == 38){
return ;//终止代码
}
if(direction == "up" && code == 40){
return ;//终止代码
}
// 8.0.2 根据keyCode 改变 direction
switch(code){
case 40 :
direction = "down";
isChange = true;
break;
case 38 :
direction = "up";
isChange = true;
break;
case 39 :
direction = "right";
isChange = true;
break;
case 37 :
direction = "left";
isChange = true;
break;
}
// 8.0.5 延迟200毫秒
setTimeout(function(){
isChange = false;
},200)
// 10. 拓展暂停(空格按键) 开始(S按键)
// 暂停(空格按键)32
console.log(code)
if(code == 32) {
// 停止执行定时器函数
clearInterval(timer);
return;
}
// 开始(S按键)
if(code == 83){
// 停止执行定时器函数(用定时器 , 先清除定时器)
clearInterval(timer);
// 继续执行定时器函数(继续游戏)
timer = setInterval(move , 200);
}
}
3、HTML文件
<!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>蛇和蛋蛋的故事</title>
<!-- 引入样式文件 -->
<link rel="stylesheet" href="css/reset.css">
<link rel="stylesheet" href="css/base.css">
<style>
.result {
width: 150px;
height: 40px;
background-color: #ccc;
line-height: 40px;
color: #fff;
position: fixed;
left: 0;
bottom: 50px;
z-index: 1000;
}
.result span {
color: red;
}
.msk {
width: 220px;
height: 120px;
background-color: #fff;
border: 1px solid #ccc;
/* 定位 */
position: absolute;
left: 50%;
top: 50%;
margin-left: -110px;
margin-top: -60px;
/* 内边距 */
padding: 0 10px;
/* 隐藏盒子 */
display: none;
}
.msk p {
width: 220px;
height: 50px;
line-height: 50px;
text-align: center;
}
.msk p span {
color: #666;
}
.msk .btn {
height: 36px;
line-height: 36px;
text-align: center;
cursor: pointer;
padding: 0 15px;
border-radius: 5px;
font-size: 13px;
margin-top: 20px;
}
.restart_btn {
float: left;
color: skyblue;
border: 1px solid skyblue;
}
.quxiao_btn {
float: left;
color: red;
border: 1px solid red;
margin-left: 10px;
}
</style>
</head>
<body>
<!-- 显示分数 -->
<div class="result">当前分数 : <span>0</span> </div>
<!-- 地图 -->
<div class="map">
<!-- 动态创建 -->
</div>
<!-- 弹窗 -->
<div class="msk">
<p><span class="tips"> xxx </span></p>
<div class="btn restart_btn">再玩一次</div>
<div class="btn quxiao_btn">取消</div>
</div>
</body>
</html>
<!-- 遮罩层 -->
<script src="js/msk.js"></script>
<!-- 贪吃蛇 -->
<script src="js/snake.js"></script>