我用端午假期写了个贪吃蛇,学弟玩的不亦乐乎!附(思路注释+源码)

Posted 贪吃ღ大魔王

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我用端午假期写了个贪吃蛇,学弟玩的不亦乐乎!附(思路注释+源码)相关的知识,希望对你有一定的参考价值。

学弟玩法:(蚯蚓找妈)

在这里插入图片描述

我的玩法:(王母摇头)

在这里插入图片描述


模块化开发

为什么要用面向对象写,有三大特性:封装、继承、多态。

为什么要封装 : 实现模块化开发,封装为一个块一个块的,利于维护,有某个模块出现bug只用修改这个模块,其他模块不受影响。在工作中,开发速度快,同时开发模块。

分三个模块写:地图,食物,蛇。

蛇模块分为:定义蛇、蛇移动、蛇死亡、蛇吃食物、蛇移动方向、蛇显示。

地图模块:

创建地图板块,设置样式

function Map() {
        // 创建一个div
        this.map = document.createElement('div')
        this.setStyle(this.map, {
            width: "700px",
            height: '500px',
            border: "10px solid #ccc",
            backgroundColor: "#abcdef",
            position: "relative"
        })
        // 将div放到body中
        document.body.appendChild(this.map)
    }
    // 添加一个设置样式的函数
    Map.prototype.setStyle = function (ele, styleObj) {
        for (var attr in styleObj) {
            ele.style[attr] = styleObj[attr]
        }
    }
    // 添加一个获取随机数的方法
    Map.prototype.getRandom = function (a, b = 0) {
        var max = Math.max(a, b);
        var min = Math.min(a, b)
        return Math.floor(Math.random() * (max - min)) + min
    }

    var m = new Map()

食物模块:

  1. 创建食物div
  2. 放入到地图中
  3. 随机产生食物的范围,随机位置函数
    function Food() {
        // 创建一个小div
        this.food = document.createElement('div')
        m.setStyle(this.food, {
            width: "10px",
            height: "10px",
            backgroundColor: "blue",
            position: "absolute",
            left: parseInt(m.getRandom(m.map.clientWidth - 10) / 10) * 10 + 'px',
            top: parseInt(m.getRandom(m.map.clientHeight - 10) / 10) * 10 + 'px',
        })
        // 放到地图中
        m.map.appendChild(this.food)
    }

    var f = new Food()

定义蛇模块:

  1. 蛇由多个div组成,蛇头样式和蛇身区分设置
  2. 初始蛇大小由三个div组成,蛇移动以后,创建三个新的div给蛇,删除原有的三个div
  3. 随着蛇吃食物,组成蛇的div越多,根据原来的身体的位置,多加相应的div
  4. 每个div都是一个对象组成,由left top坐标组成
  5. 蛇移动方向默认是向右移动
function Snake() {
        // 属性
        // 身体
        this.body = [
            {
                x: 0,
                y: 0
            },
            {
                x: 10,
                y: 0
            },
            {
                x: 20,
                y: 0
            },
            {
                x: 30,
                y: 0
            },
            {
                x: 40,
                y: 0
            },
            {
                x: 50,
                y: 0
            }
        ]

        this.direction = 'right'
        this.timer = null

        // 让蛇显示的方法
        this.show()
        // 改变蛇移动的方向方法
        this.changeDirection()

    }
    // 初始化方法
    Snake.prototype.init = function () {
        // 移动方法
        this.timer = setInterval(() => {
            this.move()
        }, 100)
    }
    // 蛇移动的方法
    Snake.prototype.move = function () {
        // 根据方向移动
        // 先移动除了蛇头的其他身体
        for (var i = 0; i < this.body.length - 1; i++) { // 少循环一次,把蛇头排除了
            // 注意:这里是复杂数据类型赋值,赋的是地址
            // this.body[i] = this.body[i+1]

            this.body[i].x = this.body[i + 1].x
            this.body[i].y = this.body[i + 1].y
        }

蛇移动模块:

  1. 移动时,当前蛇div坐标就是上一个蛇div的坐标
  2. 先移动其他身体,最后再移动蛇头,身体不能跑到蛇头的位置
  3. 改变蛇头方向
Snake.prototype.move = function () {
        // 根据方向移动
        // 先移动除了蛇头的其他身体
        for (var i = 0; i < this.body.length - 1; i++) { // 少循环一次,把蛇头排除了
            // 注意:这里是复杂数据类型赋值,赋的是地址
            // this.body[i] = this.body[i+1]

            this.body[i].x = this.body[i + 1].x
            this.body[i].y = this.body[i + 1].y
        }
        // 根据方向改变蛇头
        switch (this.direction) {
            case 'right':
                this.body[this.body.length - 1].x += 10
                break;
            case 'left':
                this.body[this.body.length - 1].x -= 10;
                break;
            case 'up':
                this.body[this.body.length - 1].y -= 10
                break;
            case 'down':
                this.body[this.body.length - 1].y += 10
                break;
        }
        this.show()

        // 检测是否迟到食物
        this.eat()
        // 检测是否死亡
        this.die()
    }

蛇死亡模块:

  1. 蛇撞墙死、和蛇撞自己身体死
  2. 蛇的left 和top 大于地图的右边界和下边界,判断撞墙
  3. 身体div的x和蛇头div的x相等 或 身体div的y和蛇头div的y相等,蛇撞自己
Snake.prototype.die = function () {
        // 撞墙
        if (this.body[this.body.length - 1].x < 0 || this.body[this.body.length - 1].y < 0 || this.body[this.body.length - 1].x > m.map.clientWidth - 10 || this.body[this.body.length - 1].y > m.map.clientHeight - 10) {
            clearInterval(this.timer)
            alert('GAME OVER')
        }
        // 撞自己身体
        for (var i = 0; i < this.body.length - 1; i++) {
            if (this.body[i].x === this.body[this.body.length - 1].x && this.body[i].y === this.body[this.body.length - 1].y) {
                clearInterval(this.timer)
                alert('GAME OVER')
                break;
            }
        }
    }
    // 蛇吃食物的方法
    Snake.prototype.eat = function () {
        // 蛇头和食物的坐标重合就是吃到了
        if (this.body[this.body.length - 1].x === f.food.offsetLeft && this.body[this.body.length - 1].y === f.food.offsetTop) {
            // 从开头添加一节身体
            this.body.unshift({
                x: this.body[0].x,
                y: this.body[0].y
            })
            // 让食物删除并重新创建食物
            m.map.removeChild(f.food)
            // 重新创建食物
            f = new Food()
        }
    }

蛇吃食物模块:

  1. 蛇头如果和食物重叠,就吃到食物了,
  2. 注意设置蛇移动大小的像素和食物生成位置的坐标,需要让蛇和食物能重叠
  3. 蛇吃到食物后,删除食物div,再生成随机坐标的新食物
  Snake.prototype.eat = function () {
        // 蛇头和食物的坐标重合就是吃到了
        if (this.body[this.body.length - 1].x === f.food.offsetLeft && this.body[this.body.length - 1].y === f.food.offsetTop) {
            // 从开头添加一节身体
            this.body.unshift({
                x: this.body[0].x,
                y: this.body[0].y
            })
            // 让食物删除并重新创建食物
            m.map.removeChild(f.food)
            // 重新创建食物
            f = new Food()
        }
    }

https://blog.csdn.net/weixin_44070254/article/details/117846779

改变蛇移动方向模块:

  1. 设置蛇移动方向对应的键盘按键码
 Snake.prototype.changeDirection = function () {
        document.onkeydown = e => {
            var e = e || window.event;
            var keycode = e.keyCode || e.which;
            // console.log(keycode);
            var keyword = String.fromCharCode(keycode).toLowerCase()
            switch (keyword) {
                case 'a':
                    this.direction = 'left'
                    break;
                case 'd':
                    this.direction = 'right';
                    break;
                case 'w':
                    this.direction = 'up';
                    break;
                case 's':
                    this.direction = 'down';
                    break;
            }
        }
    }

蛇显示模块:

  1. 每一节身体div设置大小10个像素,应该和食物一样大
  2. 设置蛇的样式 蛇头蛇身颜色和坐标
  3. 蛇放入地图中
  4. 先删除原来的身体,再显示新的身体
Snake.prototype.show = function () {
        // 先删除原来的身体再显示新的身体
        var snakes = document.querySelectorAll('.snake')
        if (snakes.length) {
            for (var i = 0; i < snakes.length; i++) {
                m.map.removeChild(snakes[i])
            }
        }

        // 根据身体数组创建div,设置坐标
        for (var i = 0; i < this.body.length; i++) {
            var div = document.createElement('div')
            div.className = 'snake'
            m.setStyle(div, {
                width: "10px",
                height: "10px",
                backgroundColor: "#000",
                position: "absolute",
                left: this.body[i].x + "px",
                top: this.body[i].y + "px"
            })
            // 放到地图中
            m.map.appendChild(div)
            if (i === this.body.length - 1) {
                m.setStyle(div, {
                    backgroundColor: "red",
                    borderRadius: "50%"
                })
            }
        }
    }



源码:

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>document</title>
</head>

<body>
    <button>开始</button>
</body>
<script>
    // 地图
    function Map() {
        // 创建一个div
        this.map = document.createElement('div')
        this.setStyle(this.map, {
            width: "700px",
            height: '500px',
            border: "10px solid #ccc",
            backgroundColor: "#abcdef",
            position: "relative"
        })
        // 将div放到body中
        document.body.appendChild(this.map)
    }
    // 添加一个设置样式的函数
    Map.prototype.setStyle = function (ele, styleObj) {
        for (var attr in styleObj) {
            ele.style[attr] = styleObj[attr]
        }
    }
    // 添加一个获取随机数的方法
    Map.prototype.getRandom = function (a, b = 0) {
        var max = Math.max(a, b);
        var min = Math.min(a, b)
        return Math.floor(Math.random() * (max - min)) + min
    }

    var m = new Map()
    // 食物
    function Food() {
        // 创建一个小div
        this.food = document.createElement('div')
        m.setStyle(this.food, {
            width: "10px",
            height: "10px",
            backgroundColor: "blue",
            position: "absolute",
            left: parseInt(m.getRandom(m.map.clientWidth - 10) / 10) * 10 + 'px',
            top: parseInt(m.getRandom(m.map.clientHeight - 10) / 10) * 10 + 'px',
        })
        // 放到地图中
        m.map.appendChild(this.food)
    }

    var f = new Food()
    // 蛇
    function Snake() {
        // 属性
        // 身体
        this.body = [
            {
                x: 0,
                y: 0
            },
            {
                x: 10,
                y: 0
            },
            {
                x: 20,
                y: 0
            },
            {
                x: 30,
                y: 0
            },
            {
                x: 40,
                y: 0
            以上是关于我用端午假期写了个贪吃蛇,学弟玩的不亦乐乎!附(思路注释+源码)的主要内容,如果未能解决你的问题,请参考以下文章

翻出了高考完后用C语言实现的贪吃蛇

C#贪吃蛇(WPF版)

表弟打把王者的时间,我就用python写了个自动玩贪吃蛇的程序

用代码移动桌面图标(贪吃蛇)

C/C++10分钟教你用C++写一个贪吃蛇附带AI功能(附源代码详解和下载)

老弟学会Python后做了个自动扫雷程序给他的小伙伴,天天玩的不亦乐乎~