javascript面向对象编程练习------贪吃蛇

js面向对象编程之贪吃蛇

骚话不多说,ok直接开工~~

  • 首先:面向对象编程,我们要找到项目中具体的对象,此处为(食物(food),蛇(snake),游戏本身(game))也可不把游戏本身作为对象,逻辑体现出来即可。
  • 接着分析每个对象的具体的属性方法
    1)food 对象:属性有:位置,大小,颜色;方法有:渲染在页面,随机不同位置生成;
    2)snake对象:属性有:位置,大小,总节数(计分方便),颜色;方法有:渲染在页面,移动(移动过程中判断其它)。
    3)game对象:游戏逻辑的编写;
  • ok 开敲:
    1)简单的静态页面编写(地图)
    (1)html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="css/index.css">
    <script src="js/food.js"></script>
    <script src="js/snake.js"></script>
    <script src="js/game.js"></script>
    <script src="js/main.js"></script>
    <title>贪吃蛇</title>
</head>
<body>
    <div class="map"></div>
</body>
</html>

(2)css(如果用边框来作为限制的边界,那么box-sizing属性是必不可少的(以免食物和蛇头坐标之间存在误差))

* {
    margin: 0;
    padding: 0;
}

.map {
    position: relative;
    height: 600px;
    width: 800px;
    border: 1px solid #333;
    margin: 0 auto;
    /* 盒子模型去除边框 */
    box-sizing: border-box;
}

2)food对象编写(细节处含注释)

//cwen加载页面所有元素
window.addEventListener('load', function() {

    //cwen自调用函数,开启一个新的作用域,避免命名冲突
    (function() {

        //cwen定义全局变量
        //实物数组
        var elements = [];
        //cwen实物
        function Food(options) {
            options = options || {};
            this.x = options.x || 0;
            this.y = options.y || 0;
            this.width = options.width || 20;
            this.height = options.height || 20;
            this.color = options.color || 'yellow';
        }


        //cwen随机数函数
        function getRandom(min, max) {
            return Math.floor(Math.random() * (max - min + 1)) + min;
        }
        //cwen渲染
        Food.prototype.render = function(map) {
            //删除之前的食物
            remove();
            //todo动态创建div实物
            var div = document.createElement('div');
            map.appendChild(div);
            //把div添加给数组
            elements.push(div);
            //todo随机设置x,y的值(实物的位置)-----在map中生成随机位置
            // ! 值 = Math.floor(Math.random() * 可能值得总数 + 第一个可能的值)
            this.x = getRandom(0, map.offsetWidth / this.width - 1) * this.width;
            this.y = getRandom(0, map.offsetHeight / this.height - 1) * this.height;
            div.style.position = 'absolute';
            div.style.left = this.x + 'px';
            div.style.top = this.y + 'px';
            div.style.width = this.width + 'px';
            div.style.height = this.height + 'px';
            div.style.backgroundColor = this.color;
        }

        function remove() {
            //为了删除干净,从索引最大的开始循环删除
            for (var i = elements.length - 1; i >= 0; i--) {
                //删除遍历到的div
                elements[i].parentNode.removeChild(elements[i]);
                //删除数组中的元素1)第几个开始,2)要删除个数
                elements.splice(i, 1);
            }
        }

        //把Food开放出去
        window.Food = Food;
    })()
    
    //cwen测试
    // var map = document.querySelector('.map');
    // var options = { x: 20, y: 20, width: 30, height: 30, color: 'green' };
    // //todo不传值默认为自定义food
    // var food = new Food();
    // food.render(map);
})

3)snake对象编写()

window.addEventListener('load', function() {
    (function() {
        //记录蛇的每一节
        var elements = [];
        //cwen立即执行函数,开启新的作用于,避免命名冲突
        function Snake(options) {
            options = options || {};
            //对象(蛇)每节的大小
            this.width = options.width || 20;
            this.height = options.height || 20;
            //cwen蛇的总节数(计分)
            this.mark = options.mark || 0;
            //对象的移动方向
            this.direction = options.direction || 'right';
            //对象的身体(蛇节)
            this.kont = [{ x: 3, y: 2, color: 'red' }, { x: 2, y: 2, color: 'black' }, { x: 1, y: 2, color: 'black' }];
        }





        //cwen渲染对象
        Snake.prototype.render = function(map) {
            //移除之前的蛇
            remove();
            //循环输出对象的身体(蛇节)
            for (var i = 0, len = this.kont.length; i < len; i++) {
                var obj = this.kont[i];
                var div = document.createElement('div');
                map.appendChild(div);
                //将蛇节添加入数组
                elements.push(div);
                //添加样式
                div.style.position = 'absolute';
                div.style.width = this.width + 'px';
                div.style.height = this.height + 'px';
                div.style.left = obj.x * this.width + 'px';
                div.style.top = obj.y * this.height + 'px';
                div.style.backgroundColor = obj.color;
            }
        }

        //cwen控制蛇移动的方法
        //todo传参food,map  在game中调用move方法也要传入相应参数
        Snake.prototype.move = function(food, map) {
            //控制蛇节的移动(当前蛇节到下一个蛇节的位置)
            for (var i = this.kont.length - 1; i > 0; i--) {
                this.kont[i].x = this.kont[i - 1].x;
                this.kont[i].y = this.kont[i - 1].y;
            }

            //判断并控制蛇头移动,判断蛇头移动方向
            var head = this.kont[0];
            switch (this.direction) {
                case 'right':
                    head.x += 1;
                    break;
                case 'left':
                    head.x -= 1;
                    break;
                case 'top':
                    head.y -= 1;
                    break;
                case 'bottom':
                    head.y += 1;
                    break;
            }


            //蛇头碰到食物时处理
            // cwen判断蛇头是否和食物坐标重合
            var headX = head.x * this.width;
            var headY = head.y * this.height;
            if (headX == food.x && headY == food.y) {
                //1,增加蛇节(找到最后一根蛇节,然后添加给创建的蛇数组)
                var last = this.kont[this.kont.length - 1];
                this.kont.push({ x: last.x, y: last.y, color: last.color });
                //cwen求出蛇节的总个数(计分)
                var mark = this.mark++;
                //2,重新渲染食物
                food.render(map);
            }
        }



        //删除之前的蛇
        function remove() {
            for (var i = elements.length - 1; i >= 0; i--) {
                elements[i].parentNode.removeChild(elements[i]);
                elements.splice(i, 1);
            }
        }

        //把Snake构造函数暴露出去
        window.Snake = Snake;
    })()
    //测试
    // var map = document.querySelector('.map');
    // var snake = new Snake();
    // snake.render(map);
})

4)game对象编写,其中一个为无敌版(含细节注释)

window.addEventListener('load', function() {
    (function() {
        //改变计时器内this指向
        var that;

        function Game(map) {
            // var options = { x: 20, y: 20, width: 30, height: 30, color: 'green' };
            this.food = new Food();
            this.snake = new Snake();
            this.map = map;
            that = this;
        }
        //cwen渲染
        Game.prototype.start = function() {
            // 1.把食物和蛇渲染到页面
            this.food.render(this.map);
            this.snake.render(this.map);
            // 2.游戏逻辑编写
            //让蛇动起来
            //判断地图边界
            // runSnake();
            //todo判断玩法(两种模式,原理一样)
            goInput();
            //通过键盘控制蛇头方向
            //! keydown();
            //蛇头碰到食物时处理
            //在snake.js中判断
        }

        function goInput() {
            var it = prompt('try:\n 经典玩法请按1\n 无敌玩法请输入(博主最帅)\n')
            if (it == 1) {
                runSnake();
                keydown();
            } else if (it == '博主最帅') {
                runSnake1();
                keydown1();
            } else {
                alert('you input could not be found!!!');
                goInput();
            }
        }



        //让蛇动起来
        function runSnake() {
            var timeId = setInterval(function() {
                // var a = mark;
                that.snake.move(that.food, that.map);
                that.snake.render(that.map);

                //判断地图边界
                var maxX = (that.map.offsetWidth) / that.snake.width;
                var maxY = (that.map.offsetHeight) / that.snake.height;
                var headX = that.snake.kont[0].x;
                var headY = that.snake.kont[0].y;
                if (headX < 0 || headX >= maxX) {
                    alert('Game Over       ' + '得分为   ' + that.snake.mark);
                    clearInterval(timeId);
                } else if (headY < 0 || headY >= maxY) {
                    alert('Game Over       ' + '成绩为   ' + that.snake.mark);
                    clearInterval(timeId);
                }
            }, 150)
        }


        //无敌版本蛇运动
        function runSnake1() {
            var timeId1 = setInterval(function() {
                that.snake.move(that.food, that.map);
                that.snake.render(that.map);

                //判断地图边界
                var maxX = (that.map.offsetWidth - that.snake.width) / that.snake.width;
                var maxY = (that.map.offsetHeight - that.snake.height) / that.snake.height;
                var headX = that.snake.kont[0].x;
                var headY = that.snake.kont[0].y;

                if (headX < 0) {
                    that.snake.kont[0].x = (that.map.offsetWidth - that.snake.width) / that.snake.width;
                } else if (headX > maxX) {
                    that.snake.kont[0].x = 0;
                } else if (headY < 0) {
                    that.snake.kont[0].y = (that.map.offsetHeight - that.snake.height) / that.snake.height;
                } else if (headY > maxY) {
                    that.snake.kont[0].y = 0;
                }
            }, 50)
        }




        //通过键盘控制蛇头方向
        function keydown() {
            document.addEventListener('keydown', function(e) {
                //通过事件对象判断按了哪个键 37left,38top,39right,40bottom
                // console.log(e.keyCode);
                //其在走的同时按下反方向无用
                if (e.keyCode == 37 && that.snake.direction != 'right') {
                    that.snake.direction = 'left';
                } else if (e.keyCode == 38 && that.snake.direction != 'bottom') {
                    that.snake.direction = 'top';
                } else if (e.keyCode == 39 && that.snake.direction != 'left') {
                    that.snake.direction = 'right';
                } else if (e.keyCode == 40 && that.snake.direction != 'top') {
                    that.snake.direction = 'bottom';
                }
            });
        }


        function keydown1() {
            document.addEventListener('keydown', function(e) {
                //通过事件对象判断按了哪个键 37left,38top,39right,40bottom
                // console.log(e.keyCode);
                //无敌版本四面八方任你行
                if (e.keyCode == 37) {
                    that.snake.direction = 'left';
                } else if (e.keyCode == 38) {
                    that.snake.direction = 'top';
                } else if (e.keyCode == 39) {
                    that.snake.direction = 'right';
                } else if (e.keyCode == 40) {
                    that.snake.direction = 'bottom';
                }
            });
        }



        //把Game开放
        window.Game = Game;
    })()
})

5)main开启游戏

window.addEventListener('load', function() {
    (function(window, undefind) {
        //测试
        var map = document.querySelector('.map');
        var game = new Game(map);
        game.start();

    })(window, undefined)
})

last but not least
*建议把所有js文件写在同一个js文件中,可以大大提高加载速度。注意在每个立即执行函数前加上‘ ;’,以免出错。

发布了4 篇原创文章 · 获赞 4 · 访问量 95

猜你喜欢

转载自blog.csdn.net/cwq521o/article/details/105362545