JavaScript实现贪吃蛇(两种方法)

前阵子无聊,试着用原生态JavaScript写了写贪吃蛇。一开始写的时候因为以前写的是C,所以想的就是面对过程,于是写了一坨翔出来。。。不过还是把代码贴上来吧:

<!--HTML CODE:-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Zombie Snake</title>
    <script type="text/javascript" src="ZombieSnake.js"></script>
    <link rel="stylesheet" type="text/css" href="ZombieSnake.css" />
</head>
<body>
    <div id="pannel"></div>
    <select name="" id="snakeSpeed">
        <option value="100">god damn</option>
        <option value="500" selected="selected">normal people</option>
        <option value="1000">just for baby</option>
    </select>
    <input type="button" id="snakeStart" value="start" />
</body>
</html>
/*CSS CODE:*/
#pannel table {
    border-collapse: collapse;
    margin-bottom: 10px;
}
#pannel td {
    width: 10px;
    height: 10px;
    border: 1px solid black;
}
.food {
    background: black;
}
.snake {
    background: green;
}
.wall {
    background: red;
}
//JavaScript CODE:
var gameSetting = {
    Speed : 500, //speed of snake
    Size : 20, //size of pannel
    Len : 3, //length of snake
    Func : null
};

var direction = {
    left : 37,
    up : 38,
    right : 39,
    down : 40
};

var Snake,
    direct,
    inside;

window.onload = function() {
    createTable("pannel");
    window.onkeydown = listen;
    document.getElementById("snakeSpeed").onchange = function() {
        gameSetting.Speed = this.value;
    }
    document.getElementById("snakeStart").onclick = function() {
        start();
        this.disabled = true;
    }
}

function start() {
    direct = direction.down;
    Snake = new Array();
    inside = cubeArray(gameSetting.Size);
    createSnake();
    createFood();
    move();
    createWall();
}

function cubeArray(m) {
    var arr = new Array(m);
    for (i = 0; i < m; i ++) {
        arr[i] = new Array(m);
    }
    return arr;
}

function addObj (x, y, name) {
    var obj = document.getElementById("box" + x + "_" + y);
    obj.className = name;
}

function restart() {
    for (var x = 0; x < gameSetting.Size; x ++)
        for (var y = 0; y < gameSetting.Size; y ++) {
            document.getElementById("box" + x + "_" + y).className = "";
            document.getElementById("snakeStart").removeAttribute("disabled");
        }
}

function createTable (pid) {
    var t = [];
    t.push("<table>");
    for (var j = 0; j < gameSetting.Size; j ++) {
        t.push("<tr id = row" + j +">");
        for (var i = 0; i < gameSetting.Size; i ++) {
            t.push("<td id = 'box" + i + "_" + j + "'x ='" + i + "' y ='" + j + "'></td>");
        };
        t.push("</tr>");
    };
    t.push("</table>");
    var p = document.getElementById(pid);
    p.innerHTML = t.join("");
};

function createWall() {
    for (var i = 0; i < 20; i ++)
        document.getElementById("box" + i + "_0").className = "wall";
    for (var i = 0; i < 20; i ++)
        document.getElementById("box" + i + "_19").className = "wall";
    for (var i = 0; i < 20; i ++)
        document.getElementById("box" + "0_" + i).className = "wall";
    for (var i = 0; i < 20; i ++)
        document.getElementById("box" + "19_" + i).className = "wall";
}

function createPoint(startX, startY, endX, endY) {
    var x = Math.floor(Math.random() * (endX - startX)) + startX;
    var y = Math.floor(Math.random() * (endY - startY)) + startY;
    var p = [];
    p[0] = x;
    p[1] = y;
    return p;
}

function createSnake() {
    var point = createPoint(gameSetting.Len, gameSetting.Len, gameSetting.Size / 2, gameSetting.Size / 2);
    for (var i = 0; i < gameSetting.Len; i ++) {
        var x = point[0];
        var y = point[1] - i;
        Snake.push([x, y]);
        addObj(x, y, "snake");
    }
}

function createFood() {
    var foodPoint = createPoint(1, 1, gameSetting.Size - 1, gameSetting.Size - 1);
    if(document.getElementById("box" + foodPoint[0] + "_" + foodPoint[1]).className == "snake") return createFood();
    addObj(foodPoint[0], foodPoint[1], "food");
    inside[foodPoint[0]][foodPoint[1]] = "food";
}

function listen(e) {
    e = e || event;
    direct = Math.abs(e.keyCode - direct) != 2 && e.keyCode > 36 && e.keyCode < 41 ? e.keyCode : direct;
}

function move() {
    if (gameSetting.Func) window.clearInterval(gameSetting.Func);
    gameSetting.Func = window.setInterval(step, gameSetting.Speed);
}

function step() {
    var headX = Snake[0][0],
        headY = Snake[0][1],
        lastX = Snake[Snake.length - 1][0],
        lastY = Snake[Snake.length - 1][1];
    addObj(lastX, lastY, "");
    for (var i = Snake.length - 1; i > 0; i --) {
        Snake[i][0] = Snake[i - 1][0];
        Snake[i][1] = Snake[i - 1][1];
    }
    switch (direct) {
        case direction.up: headY    -= 1; break;
        case direction.down: headY  += 1; break;
        case direction.left: headX  -= 1; break;
        case direction.right: headX += 1; break;
    }
    Snake[0][0] = headX;
    Snake[0][1] = headY;
    for (var i = 0; i < Snake.length; i ++) {
        addObj(Snake[i][0], Snake[i][1], "snake");
    }
    //eat food
    if (inside[headX][headY] == "food") {
        createFood();
        Snake.unshift([headX, headY]);
    }
    if (headX >= 19 || headX <= 0 || headY >= 19 || headY <=0 ) {
        window.clearInterval(gameSetting.Func);
        alert("game over! :D ");
        restart();
    }
}

如上所示,写的简直就是一坨翔,完全不堪入目。功能也没有怎么完善:比如说撞到自己的判断没有写,数组操作烂到了一种水平,写了一大堆函数看得头都晕了,还掺杂了一大堆的全局变量……于是看了点书后我又写了另一个版本,是面向对象的:

<!--HTML CODE:-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Snake</title>
    <link rel="stylesheet" type="text/css" href="snake.css" />
</head>
<body>
    <div id="game">
        <div id="pannel"></div>
    </div>
    <div id="button">
        <input type="button" id="start" value="start" />
    </div>
</body>
<script type="text/javascript" src="snake.js"></script>
</html>
/*CSS CODE:*/
#pannel table {
    border-collapse: collapse;
    margin-bottom: 10px;
}
#pannel td {
    width: 10px;
    height: 10px;
    border: 1px solid black;
}
.food {
    background: black;
}
.snake {
    background: green;
}
//JavaScript CODE:
(function () {
    /*全局变量*/
    var g = {
        //获得or设置盒子的attribute
        attr : function (x, y, att, name) {
            var d = document.getElementById("box_" + x + "_" + y);
            if (d && name)
                d.setAttribute(att, name);
            else if (d)
                return d.getAttribute(att);
        },
        //随机创建点
        create : function (start, end) {
            return Math.floor(Math.random() * (end - start) + start);
        },
        //运动方向
        direction : {
            left : 37,
            up : 38,
            right : 39,
            down : 40
        },
        //游戏设定
        setting : {
            size : 20,
            speed : 500,
            len : 3,
            func : null,
            direct : null
        }
    }
    /*Game构造器*/
    function Game () {
        /*创建格子*/
        this.pannel = function () {
            var t = [];
            t.push("<table>");
            for (var i = 0; i < g.setting.size; i ++) {
                t.push("<tr class = 'row' y = " + i + ">");
                for (var j = 0; j < g.setting.size; j ++) {
                    t.push("<td id = 'box_" + j + "_" + i + "'></td>");
                }
                t.push("</tr>");
            }
            t.push("</table>");
            document.getElementById("pannel").innerHTML = t.join("");
        };
        /*初始化游戏*/
        this.init = function () {
            if (g.setting.func)
                window.clearInterval(g.setting.func);
            var d = document.getElementById("start"); 
            if (d)
                d.disabled = false;
            for (var x = 0; x < g.setting.size; x ++)
                for (var y = 0; y < g.setting.size; y ++)
                    g.attr(x, y, "class", " ");
        }
        /*游戏开始*/
        this.start = function () {
            g.setting.direct = g.direction.down;
            var snake = new Snake(), food = new Food();
            food.create();
            snake.create();
            //蛇移动
            g.setting.func = window.setInterval(snake.move, g.setting.speed);
        }
        /*监听键盘*/
        this.listen = function (e) {
            e = e || event;
            g.setting.direct = Math.abs(e.keyCode - g.setting.direct) != 2 && e.keyCode > 36 && e.keyCode < 41 ? e.keyCode : g.setting.direct;
        }
        /*游戏结束*/
        this.over = function () {
            alert("game over XD!");
            game.init();
        };
    };
    /*Snake构造器*/
    function Snake () {
        var headX, headY, pos = [], that = this;
        /*创建蛇*/
        this.create = function () {
            var x = g.create(g.setting.len, g.setting.size / 2),
            y = g.create(g.setting.len, g.setting.size / 2);
            //获得蛇的坐标
            for (var i = 0; i < g.setting.len; i ++) {
                y --;
                pos.push([x, y]);
                g.attr(x, y, "class", "snake");
            }
        };
        /*移动*/
        this.move = function () {
            headX = pos[0][0];
            headY = pos[0][1];
            lastX = pos[pos.length - 1][0];
            lastY = pos[pos.length - 1][1];
            g.attr(lastX, lastY, "class", " ");
            for (var i = pos.length - 1; i > 0; i --) {
                pos[i][0] = pos[i - 1][0];
                pos[i][1] = pos[i - 1][1];
            }
            switch (g.setting.direct) {
                case g.direction.up : headY    -= 1; break;
                case g.direction.down : headY  += 1; break;
                case g.direction.left : headX  -= 1; break;
                case g.direction.right : headX += 1; break;
            }
            pos[0][0] = headX;
            pos[0][1] = headY;
            for (var i = 0; i < pos.length; i ++)
                g.attr(pos[i][0], pos[i][1], "class", "snake");
            var inside = g.attr(headX, headY, "inside");
            //吃食物
            if (inside == "food") {
                lastX = pos[pos.length - 1][0];
                lastY = pos[pos.length - 1][1];
                if (lastX == pos[pos.length - 2][0]) {
                    if (lastY - pos[pos.length - 2][1] == 1)
                        pos.push([lastX, lastY + 1]);
                    else if (pos[pos.length - 2][1] - lastY == 1)
                        pos.push([lastX, lastY - 1]);
                }
                else if (lastY == pos[pos.length - 2][1]) {
                    if (lastX - pos[pos.length - 2][0] == 1)
                        pos.push([lastX + 1, lastY])
                    else if (pos[pos.length - 2][0] - lastX == 1)
                        pos.push([lastX - 1, lastY]);
                }
                lastX = pos[pos.length - 1][0];
                lastY = pos[pos.length - 1][1];
                g.attr(lastX, lastY, "class", "snake");
                var food = new Food();
                food.create();
            };
            //撞到自己或者墙,游戏结束
            for (var i = 1; i < pos.length; i ++) {
                if (headX == pos[i][0] && headY == pos[i][1])
                    game.over();
                else
                    continue;
            }
            if (headX > 19 || headX < 0 || headY > 19 || headY < 0)
                game.over();
        };
    };
    /*Food构造器*/
    function Food () {
        var that = this;
        /*创建食物*/
        this.create = function () {
            var x = g.create(0, g.setting.size),
            y = g.create(0, g.setting.size);
            //检查是否与蛇的位置重合
            var c = g.attr(x, y, "class");
            if (c == "snake")
                return that.create();
            else {
                g.attr(x, y, "class", "food");
                g.attr(x, y, "inside", "food");
            }
        };
    };

    var game = new Game();
    game.pannel();
    game.init();
    document.getElementById("start").onclick = function () {
        this.disabled = true;
        game.start();
        window.onkeydown = game.listen;
    }

})()

这个版本因为写的太过匆忙,所以有些功能没有加:比如调整蛇的移动速度什么的……有空再说吧……
【END】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值