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

本文详细介绍了使用JavaScript实现贪吃蛇游戏的模块化开发过程,包括地图、食物和蛇的各个模块。通过封装、继承和多态等面向对象特性,实现地图创建、食物生成、蛇的移动、碰撞检测和食物吃食等功能。同时,文章提供了完整的源码,有助于读者理解和学习游戏开发及JavaScript编程技巧。
摘要由CSDN通过智能技术生成

学弟玩法:(蚯蚓找妈)

在这里插入图片描述

我的玩法:(王母摇头)

在这里插入图片描述


模块化开发

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

为什么要封装 : 实现模块化开发,封装为一个块一个块的,利于维护,有某个模块出现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
            },
            {
                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
        }
        // 根据方向改变蛇头
        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()
    }
    // 蛇死亡的方法
    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()
        }
    }
    // 改变移动方向
    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;
            }
        }
    }
    // 让蛇显示的方法
    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%"
                })
            }
        }
    }

    var s = new Snake()

    document.querySelector('button').onclick = function () {
        s.init()
    }
</script>

</html>


觉得博主总结的不错的,可以收藏支持一波~

在这里插入图片描述

好的,以下是一个简单的贪吃蛇代码,带有详细的注释: ```python import pygame import random # 初始化pygame pygame.init() # 设置游戏窗口大小 WINDOW_WIDTH = 640 WINDOW_HEIGHT = 480 WINDOW_SIZE = (WINDOW_WIDTH, WINDOW_HEIGHT) # 设置游戏窗口标题 pygame.display.set_caption('Snake Game') # 定义颜色 BLACK = (0, 0, 0) WHITE = (255, 255, 255) RED = (255, 0, 0) GREEN = (0, 255, 0) BLUE = (0, 0, 255) # 创建游戏窗口 screen = pygame.display.set_mode(WINDOW_SIZE) # 设置游戏时钟 clock = pygame.time.Clock() # 设置游戏变量 score = 0 # 得分 game_over = False # 游戏结束标志 # 定义方向常量 UP = 1 DOWN = 2 LEFT = 3 RIGHT = 4 # 定义贪吃蛇类 class Snake: def __init__(self): self.x = 0 # 贪吃蛇头部x坐标 self.y = 0 # 贪吃蛇头部y坐标 self.direction = RIGHT # 贪吃蛇初始方向 self.body = [] # 贪吃蛇身体列表 self.length = 3 # 贪吃蛇初始长度 def move(self): # 根据方向移动贪吃蛇 if self.direction == UP: self.y -= 20 elif self.direction == DOWN: self.y += 20 elif self.direction == LEFT: self.x -= 20 elif self.direction == RIGHT: self.x += 20 # 将新的头部坐标加入贪吃蛇身体列表 self.body.insert(0, (self.x, self.y)) # 如果贪吃蛇的长度大于指定长度,则删除尾部坐标 if len(self.body) > self.length: self.body.pop() def draw(self): # 绘制贪吃蛇 for x, y in self.body: pygame.draw.rect(screen, GREEN, (x, y, 20, 20)) def collision(self): # 判断贪吃蛇是否与边界或自身碰撞 if self.x < 0 or self.x > WINDOW_WIDTH - 20 or self.y < 0 or self.y > WINDOW_HEIGHT - 20: return True for x, y in self.body[1:]: if self.x == x and self.y == y: return True return False def eat(self, food): # 判断贪吃蛇是否吃到食物 if self.x == food.x and self.y == food.y: self.length += 1 # 贪吃蛇长度加1 return True return False # 定义食物类 class Food: def __init__(self): self.x = random.randrange(0, WINDOW_WIDTH - 20, 20) # 食物x坐标 self.y = random.randrange(0, WINDOW_HEIGHT - 20, 20) # 食物y坐标 def draw(self): # 绘制食物 pygame.draw.rect(screen, RED, (self.x, self.y, 20, 20)) # 创建贪吃蛇和食物对象 snake = Snake() food = Food() # 游戏循环 while not game_over: # 处理事件 for event in pygame.event.get(): if event.type == pygame.QUIT: game_over = True elif event.type == pygame.KEYDOWN: if event.key == pygame.K_UP and snake.direction != DOWN: snake.direction = UP elif event.key == pygame.K_DOWN and snake.direction != UP: snake.direction = DOWN elif event.key == pygame.K_LEFT and snake.direction != RIGHT: snake.direction = LEFT elif event.key == pygame.K_RIGHT and snake.direction != LEFT: snake.direction = RIGHT # 移动贪吃蛇 snake.move() # 判断是否吃到食物 if snake.eat(food): # 创建新的食物对象 food = Food() # 得分加1 score += 1 # 绘制背景 screen.fill(BLACK) # 绘制得分文本 font = pygame.font.SysFont(None, 30) text = font.render('Score: ' + str(score), True, WHITE) screen.blit(text, (10, 10)) # 绘制贪吃蛇和食物 snake.draw() food.draw() # 判断是否与边界或自身碰撞 if snake.collision(): game_over = True # 更新屏幕 pygame.display.update() # 设置游戏帧率 clock.tick(10) # 退出pygame pygame.quit() ``` 希望对你有帮助!
评论 243
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贪吃ღ大魔王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值