美文网首页JS
JavaScript+HTML 实现贪吃蛇简陋版

JavaScript+HTML 实现贪吃蛇简陋版

作者: Lengff | 来源:发表于2019-04-13 00:22 被阅读60次

    有一天午睡突然突发奇想写个贪吃蛇玩一玩,一开始是想用c来写,然后弄一个8*8的点阵屏来玩的,但是又觉得太过于麻烦,所以就想着用最简单的方法来实现,所以就选择了JavaScript和HTML来实现,简述一下实现原理和提出代码

    示例demo

    snake-game
    建议用手机打开,当然电脑也做了上下左右键盘控制,但是显示效果是为了手机显示适应的

    效果图

    效果图

    实现原理

    我觉得弄这个需要一点点的面相对象的思维就能简简单单的实现,首先我们需要有一个地图,所以就需要在这个地图上建立坐标系,不让我们的贪吃蛇抛出我们的坐标系,所以我就选择了二维数组来建立我们的坐标系,然后给每个坐标都设定一个值(我设定的就是x轴左边加y轴坐标的字符串),然后我们还需要一条贪吃蛇,和砖块,这里其实可以看成一部分,其实砖块就是我们坐标里面对应的值,而我们的贪吃蛇就是这个砖块的数组,所以我们可以理解成以下样子

    地图:
    一个二维数组
    贪吃蛇
    一个包含在地图里面的一维数组 ==> 多个砖块的拼接组成的一个数组
    砖块
    一个地图里面对应的准确的值

    所以看到这里就很简单了,所谓的贪吃蛇其实就是在操作我们熟知的数组

    上述的是我们游戏里面涉及到的元素,接下来我们讲讲我们涉及到的一些动作

    蛇的行动范围

    这个其实很简单,主要就是对蛇头做判断(数组第一个),只要蛇头不大于地图数组,游戏便可以继续下去

    蛇的位移

    其实蛇移动比较容易理解,例如 向下移动的时候y轴坐标+1,x轴坐标不动 其他方向同理,这样就能实现蛇的整体位移


    示例

    看图比较容易看懂,就是蛇头以后得元素需要向之前的移动

    蛇的成长

    image.png

    这里我们有使用数据结构中比较高级的插入方式,使用了我比较喜欢的渣渣方式,就是直接在数组的后面添加一个元素,实现蛇吃砖块长大的方式

    砖块的随机生成
    这里需要确保不会和我门蛇的数组位置冲突,需要做一些判断

    蛇吃自己
    这里只需要判断蛇里面没有重复的元素便可以了

    视图渲染
    每次蛇的移动完成以后都生成一个0和1组成的二维数组,遍历数组为HTML添加颜色就可以了

    写在最后
    其实实现起来远比我说明的这些要容易的多,毕竟我是一个喜欢讲废话的人,我个人觉得看了代码就知道这个东西确实是挺简单的

    代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="user-scalable=0">
        <title>snake game</title>
        <style>
            * {
                width: 100%;
                height: 100%;
                margin: 0;
                padding: 0;
            }
    
            #score {
                font-size: 300%;
                display: flex;
                align-items: center;
                justify-content: center;
            }
    
            #handle {
                display: flex;
                flex-direction: column;
                overflow: hidden;
                font-size: 150%;
            }
    
            .game-row {
                display: flex;
                flex-direction: row;
            }
    
            .game-column {
                display: flex;
                flex-direction: column;
                align-items: center;
                justify-content: space-between;
                border: 1px #ce53d2 solid;
            }
    
            .game-column-snake {
                display: flex;
                flex-direction: column;
                align-items: center;
                justify-content: space-between;
                border: 1px #ce53d2 solid;
                background: black;
            }
    
            .game-column-block {
                display: flex;
                flex-direction: column;
                align-items: center;
                justify-content: space-between;
                border: 1px #ce53d2 solid;
                background: lightgreen;
            }
    
            .center {
                display: flex;
                align-items: center;
                justify-content: center;
            }
        </style>
    </head>
    <body id="body" style="display: flex;flex-direction: column">
    <div id="score">分数</div>
    <div id="game"></div>
    <div id="handle">
        <div class="center" style="height: 30%;" onclick="handle('up')">上</div>
        <div style="display: flex;flex-direction: row;height: 60%;">
            <div class="center" onclick="handle('left')">左</div>
            <div class="center" onclick="handle('start')">重新开始</div>
            <div class="center" onclick="handle('right')">右</div>
        </div>
        <div class="center" style="height: 30%;" onclick="handle('down')">
            下
        </div>
    </div>
    </body>
    <script>
        var w = 0,//页面的宽度
            h = 0,//页面的高度
            block = '00',//砖块
            snake = [],//蛇
            map = [], //实际坐标系
            xy = [],//渲染坐标系
            hanld = 'right', //走动方向
            mapSize = 10, //地图大小
            score = 0,//游戏积分
            level = 500,//游戏等级,默认是800毫秒走一次
            endflag = false,
            runStatus = 0;//自动运行标记
        main();
    
        /**
         * 主方法
         */
        function main() {
            initShow();
            initMap();
            genSnake();
            genBlock();
            gen01();
            next();
        }
    
        /**
         * 初始化页面信息
         */
        function initShow() {
            //获取body的高度和宽度
            var dom = document.getElementById("body");
            w = dom.offsetWidth, h = dom.offsetHeight;
            var h_w = h - w;
            //自适应分数显示区域的高度
            var score = document.getElementById('score');
            score.style.height = parseInt(h_w) * 0.2 + 'px';
            //自适应操作示区域的高度
            var handle = document.getElementById('handle');
            handle.style.height = parseInt(h_w) * 0.8 + 'px';
            //自适应游戏区域的高度和宽度
            var game = document.getElementById('game');
            game.style.width = parseInt(w) + 'px';
            game.style.height = parseInt(w) + 'px';
        }
    
        /**
         *初始化地图
         */
        function initMap() {
            for (var x = 0; x < mapSize; x++) {
                map[x] = [];
                for (var y = 0; y < mapSize; y++) {
                    map[x][y] = splitStr(y, x);
                }
            }
        }
    
        /**
         * 生成随机数
         * @param filter 需要过滤掉的数字
         * @returns {number}
         */
        function rand(filter) {
            var rand = parseInt(Math.random() * 10);
            if (rand == filter) {
                rand(filter);
            }
            return rand;
        }
    
        /**
         * 将坐标系转换成0/1的数组
         */
        function gen01() {
            var overflag = false;
            for (var i = 0; i < mapSize; i++) {
                xy[i] = [];
                for (var j = 0; j < mapSize; j++) {
                    xy[i][j] = 0;
                    for (var s = 0; s < snake.length; s++) {
                        if (snake[s] == map[i][j]) {
                            xy[i][j] = 1;
                            break;
                        }
                    }
                    if (block == map[i][j]) {
                        xy[i][j] = 2;
                    }
                    if (snake[0] == map[i][j]) {
                        overflag = true;
                    }
                }
            }
            if (!overflag) {
                //游戏结束
                showover();
            } else {
                if (!endflag) {
                    //生成进制以后就将数据渲染到HTML中去
                    show(xy);
                }
            }
        }
    
        /**
         * 生成小蛇
         */
        function genSnake() {
            snake.push(splitStr(rand(), rand()));
        }
    
        /**
         * 生成随机砖块
         */
        function genBlock() {
            block = splitStr(rand(), rand());
            //确保生成砖块不会生成到和蛇一样的,否则就重新生成
            for (var i in snake) {
                if (block == snake[i]) {
                    genBlock();
                }
            }
        }
    
        /**
         * 蛇向下一步移动
         */
        function next() {
            clearTimeout(runStatus);
            changeSnakeHead();
            eatself();
            eatblock();
            gen01();
            runStatus = setTimeout(function () {
                next();
            }, level);
        }
    
    
        /**
         * 判断蛇是否吃自己
         */
        function eatself() {
            for (var s = 0; s < snake.length; s++) {
                if (s > 0 && snake[s] == snake[0]) {
                    showover();
                    break
                }
            }
        }
    
        /**
         * 修改蛇的身体
         */
        function changeSnakeHead() {
            var tempa = snake[0];
            for (var i = 0; i < snake.length; i++) {
                var a = snake[i][0], b = snake[i][1];
                if (i == 0) {
                    switch (hanld) {
                        case 'up':
                            snake[i] = splitStr(a, parseInt(b) - 1);
                            break;
                        case 'down':
                            snake[i] = splitStr(a, parseInt(b) + 1);
                            break;
                        case 'left':
                            snake[i] = splitStr(parseInt(a) - 1, b);
                            break;
                        case 'right':
                            snake[i] = splitStr(parseInt(a) + 1, b);
                            break;
                    }
                } else {
                    var tempb = tempa;
                    tempa = snake[i];
                    snake[i] = tempb;
                }
            }
        }
    
        /**
         * 吃砖块
         */
        function eatblock() {
            if (snake[0] == block) {
                var tail = snake[snake.length - 1], temp = [], a = tail[0], b = tail[1];
                switch (hanld) {
                    case 'up':
                        temp = splitStr(a, parseInt(b) + 1);
                        break;
                    case 'down':
                        temp = splitStr(a, parseInt(b) - 1);
                        break;
                    case 'left':
                        temp = splitStr(parseInt(a) + 1, b);
                        break;
                    case 'right':
                        temp = splitStr(parseInt(a) - 1, b);
                        break;
                }
                snake.push(temp);
                addscore();
                genBlock();
            }
        }
    
        /**
         *  修改蛇的身体结构
         * @param x
         * @param y
         */
        function splitStr(x, y) {
            return x + '' + y;
        }
    
    
        /**
         * 键盘按下事件绑定
         */
        document.onkeydown = function (e) {
            var e = window.event || e;
            switch (e.keyCode) {
                case 37: //左
                    hanld = hanld != 'left' && hanld != 'right' ? 'left' : hanld;
                    break;
                case 38: //上
                    hanld = hanld != 'up' && hanld != 'down' ? 'up' : hanld;
                    break;
                case 39:  //右
                    hanld = hanld != 'left' && hanld != 'right' ? 'right' : hanld;
                    break;
                case 40:  //下
                    hanld = hanld != 'up' && hanld != 'down' ? 'down' : hanld;
                    break;
            }
        }
    
        /**
         * 按键事件处理
         */
        function handle(e) {
            if (e == 'start') {
                if (endflag) {
                    //只有输掉游戏才能重新开始游戏
                    window.location.reload();
                }
            } else {
                if ((hanld == 'left' || hanld == 'right')) {
                    if (e == 'up' || e == 'down') {
                        hanld = e;
                    }
                } else {
                    if (e == 'left' || e == 'right') {
                        hanld = e;
                    }
                }
            }
        }
    
        /**
         * 添加游戏积分,目前的积分就是蛇的长度
         */
        function addscore() {
            var score = parseInt(snake.length) - 1;
            //根据游戏得分修改游戏等级,一共分五个等级,
            if (score > 20) {
                level = 250;
            } else if (score > 15) {
                level = 300;
            } else if (score > 10) {
                level = 350;
            } else if (score > 5) {
                level = 400;
            } else if (score > 1) {
                level = 450;
            } else {
                level = level;
            }
            document.getElementById('score').innerHTML = '分数:' + score;
        }
    
        /**
         * 将数据渲染在页面上去
         * @param xy
         */
        function show(xy) {
            var html = '',
                height = parseInt(w) / mapSize;
            for (var i = 0; i < mapSize; i++) {
                html += '<div class="game-row" style="height:' + height + 'px;">'
                for (var j = 0; j < mapSize; j++) {
                    if (xy[i][j] == 1) {
                        html += '<div class="game-column-snake"></div>';
                    } else if (xy[i][j] == 2) {
                        html += '<div class="game-column-block"></div>';
                    } else {
                        html += '<div class="game-column"></div>';
                    }
    
                }
                html += '</div>';
            }
            document.getElementById('game').innerHTML = html;
        }
    
        /**
         * 游戏结束
         */
        function showover() {
            document.getElementById('game').innerHTML = '<h1 align="center" style="font-size: 500%;color:red;">game over!</h1>';
            endflag = true;
        }
    
    
    </script>
    </html>
    
    

    相关文章

      网友评论

        本文标题:JavaScript+HTML 实现贪吃蛇简陋版

        本文链接:https://www.haomeiwen.com/subject/vpskwqtx.html