HTML 5 + CSS 3 + JavaSript 实现贪吃蛇

HTML 5 + CSS 3 + JavaSript 实现贪吃蛇

在这里插入图片描述

参考代码:经典贪吃蛇源码(含注释)

源代码

<!DOCTYPE html>
<html>
<head>
<title>Retro Snake</title>
<link rel="icon" href="https://raw.githubusercontent.com/CourserLi/JavaScirpt-snake/master/head.ico" type="image/x-icon"/>
<style type="text/css">
    body {background-image:url(https://raw.githubusercontent.com/CourserLi/JavaScirpt-snake/master/pic.jpg);background-size:100%;}
    body {background-repeat:no-repeat;}
    body {margin:100px;text-align:center;}  
    h1 {font-size:210%;}
    h1 {font-family:Georgia,Serif;}
</style>
</head>
<body>
<!--设置id,宽400像素,高400像素,背景颜色设置为灰色-->
<canvas id="canv" width="400" height="400" style="background-color:gray"></canvas>
</canvas>
<h1>Courser Li</h1>

<script>
    //声明变量
    //设置canvas画布的绘图的环境,当前唯一支持的参数是2d
    var box=document.getElementById('canv').getContext('2d');  //用于绘制矩形的变量
    //声明一个变量表示蛇
    var snake;
    //声明键盘事件的变量,1表示向右,-1向左,20向下,-20向上
    var direction;
    //声明蛇头
    var n;
    //声明食物变量
    var food;
    //声明速度初始变量
    speed=100;

    //绘制地图
    function draw(point,color)
    {
        //fillStyle()方法为设置用于填充绘画的颜色
        box.fillStyle=color;
        //fillRect()方法用于绘制“被填充”的矩形
        box.fillRect(point%20*20+1,~~(point/20)*20+1,18,18);  //行 列 长 宽(长宽不能大于20,因为要在矩形直接留间隙)
    }
    
    //各种变量初始化,背景初始化
    function ready()
    {
        //循环绘制地图块
        for(var i=0;i<400;i++)
            draw(i,"#313131");
        //对蛇和食物进行静态赋值并绘制到地图上
        snake=[66,65,64];
        direction=1;  //起始方向向右
        food=344;
        draw(food,"yellow");
        draw(66,"#00b7ee");
        draw(65,"#00b7ee");
        draw(64,"#00b7ee");
    }
    //自动运行函数
    (function(){ready();}());

    //核心算法
    function run()
    {
        //在游戏开始以后“开始游戏”按钮变为不可点击状态
        document.getElementById("butn").setAttribute("disabled",true);
        //用unshift()方法向数组的开头添加一个新元素,新元素为蛇下一步所移动的坐标
        snake.unshift(n=snake[0]+direction);
        //边界判断,如果蛇头碰到上下左右四个边或者碰到自己的身子
        //游戏结束,初始化游戏,将“开始游戏”按钮设置为可以点击,点击开始按钮可以重新进行游戏
        if(snake.indexOf(n,1)>0||n<0||n>399||(direction==-1&&n%20==19)||(direction==1&&n%20==0))
        {
            ready();
            document.getElementById("butn").removeAttribute("disabled");
            return alert("游戏结束");
        }
        //如果蛇头没有碰到边界或蛇身,在地图上绘制蛇头
        draw(n,"#00b7ee");
        //如果蛇头吃到了食物(坐标相同)
        if(n==food)
        {
            //随机在地图上产生一个新食物,新事物不能于蛇身子重合
            //Math.random()是令系统随机选取大于等于 0.0 且小于 1.0 的伪随机 double 值
            while(snake.indexOf(food=~~(Math.random()*400))>=0);
            //绘制食物
            draw(food,"yellow");
        }
        //如果蛇头没有吃到食物
        else
        {
            //将蛇尾元素删除并且根据删除的坐标绘制为地图块的颜色
            draw(snake.pop(),"#313131");
        }
        //每100毫秒重复执行一次该函数
        setTimeout(arguments.callee,speed);
    }

    //添加键盘事件
    document.onkeydown=function(e)
    {
        //如果蛇当前横着走,当键盘输入up时,将蛇头方向改为向上,输入down时将蛇头方向改为向下
        if((direction==1||direction==-1)&&(snake[0]-snake[1]==1||snake[0]-snake[1]==-1))
        {
            if(e.keyCode==38)  //上
                direction=-20;
            if(e.keyCode==40)  //下
                direction=20;
        }
        //如果蛇当前竖着走,当键盘输入left时向左,right时向右
        if((direction==20||direction==-20)&&(snake[0]-snake[1]==20||snake[0]-snake[1]==-20))
        {
            if(e.keyCode==39)  //右
                direction=1;
            if(e.keyCode==37)  //左
                direction=-1;
        }
    }
</script>
<div>
    <button id="butn" type="button" onclick="run()">开始游戏</button>
</div>
</body>
</html>

相关属性与方法

<canvas id="canvas" width="300" height="300" style="background-color:write"> 
var box=document.getElementById('canv').getContext('2d'); //两种方法写在一起

box.fillStyle = 'green';  //绘制矩形的颜色
box.fillRect(10, 10, 150, 100);  //描绘矩形的位置及大小

canvas 元素
直接在 html 标签中设置 width 和 height 属性并使用 JavaScript 来指定画布背景为白色

.getElementById() 方法
获取 < canvas > 标签的引用

.getContext() 方法
渲染图像(目前只有 2d)

fillStyle 属性
让长方形变成绿色

.fillRect() 方法
将它的左上角放在(10, 10),把它的大小设置成宽150高100
在这里插入图片描述

补充

JavaScript中 ~~ 的使用方法

~~ 代表双非按位取反运算符
对于正数,它向下取整;对于负数,向上取整;对于非数字,取值为 0

~~0;         // => 0
~~null;      // => 0
~~{};        // => 0
~~false;     // => 0
~~true;      // => 1
~~1.9;       // => 1
~~-1.9;      // => -1

JavaScript中 .indexOf 方法
返回 某个指定的字符串值在字符串中首次出现的位置 或 元素在列表中首次出现的位置,若找不到则返回 -1

var str="Hello world!"
document.write(str.indexOf("Hello") + "<br/>")
document.write(str.indexOf("World") + "<br/>")
document.write(str.indexOf("world"))

output:
0
-1
6

解决bug

问题: 若 run 函数一轮循环接收多个键位会导致游戏强制结束
解决方法: 调整键盘事件仅当 snake 数组前两个元素相邻时(矩形紧挨时)才能执行,而只有 run 函数结束上一轮循环时,snake 数组才开始接收键位,也就是一轮循环,只能接收一个键位

:
if(direction==1||direction==-1)
if(direction==20||direction==-20):
if((direction==1||direction==-1)&&(snake[0]-snake[1]==1||snake[0]-snake[1]==-1))
if((direction==20||direction==-20)&&(snake[0]-snake[1]==20||snake[0]-snake[1]==-20))

原本我还想加入一些有趣的玩法,奈何实力不足,我想等我有能力了再重新加入这些玩法,想加入的玩法如下:

  • 随着时间贪吃蛇的速度会减少,但吃了一个食物速度会增加 一点,相当于竞速模式,获胜的条件即速度到达某个值 或 长度大于某个值(这个我本可以实现,但无法具体在网页上显示具体数值就,所以还是不加了)
  • 添加暂停按钮(最好加个快捷键)
  • 失败与胜利的弹出窗口改变样式
  • 贪吃蛇初始位置随机(本代码是静态生成,但食物是动态生成的)
  • 颜色随着位置的改变而改变(七彩蛇)

猜你喜欢

转载自blog.csdn.net/CourserLi/article/details/105048786