前端vue写贪吃蛇

1.首先创建游戏框

全部代码在最下方

代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://unpkg.com/vue@2/dist/vue.js"></script>
    <style>
        div {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            height: 100vh;
            width: 100vw;
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        #app {
            height: 100%;
            width: 100%;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        .gameBox {
            width: 80%;
            height: 80%;
            border: 1px solid black;
        }

        .flexBox {
            display: flex;
            width: 100%;
        }
        .flexBox:last-of-type .inBox{
            border-bottom: 0;
        }

        .inBox{
            border: 1px solid #ebeaea;
            border-left: 0;
            border-top: 0;
        }
        .inBox:nth-of-type(100n){
            border-right: 0;
        }
    </style>
</head>

<body>
    <div id="app">
        <div class="gameBox" ref="gameBox">
            <div v-for="(item, index) in height" :key="index" class="flexBox">
                <div v-for="(l, i) in width" :key="i+1000" :style="`width: ${boxwidth}px;height:${boxheight}px`" class="inBox"></div>
            </div>
        </div>
    </div>
    <script type="module">
        new Vue({
            el: '#app',
            data: function () {
                return {
                    boxwidth: 0, // 每个格子的宽
                    boxheight: 0, // 每个格子的高
                    width: 20, // 横着渲染多少个格子  调整表格宽修改这
                    height: 10, // 竖着渲染多少个格子  调整表格高修改这
                }
            },
            methods: {

            },
            mounted() {
                // 首先获取盒子的高宽
                this.boxwidth = this.$refs.gameBox.offsetWidth / this.width
                this.boxheight = this.$refs.gameBox.offsetHeight / this.height
            }
        })
    </script>
</body>

</html>

区域讲解:

我将其分为了每行20块,每列10块的区域,首先我在 mounted 当中获取了游戏区域的宽高,并利用其宽高计算出了每个格子的长和宽

2.初始化网格

代码如下:

// 初始化
gameBegin() {
    this.gameArr = []
    this.snake = []
    // 计算每个格子的值
    for (let i = 0; i < this.height; i++) {
        this.gameArr.push([])
        for (let a = 0; a < this.width; a++) {
            this.gameArr[i].push({
                row: i + 1, // 第几行
                col: a + 1, // 第几列
                isHaveSnake: false, // 这块当中是否有蛇
                isHaveFood: false, // 是否有食物
            })
        }
    }
    // 默认第一格有蛇
    this.gameArr[0][0].isHaveSnake = true
    this.snake.push(this.gameArr[0][0])
},

区域讲解:

初始化表格  gameArr 就是所有的格子数据 row 是第几行 col 为第几列 isHaveSnake 是这块当中是否为蛇块 isHaveFood 为是否是食物块

3.贪吃蛇移动

代码如下:

// 蛇移动函数
snakeMove() {
    if (this.nowMoveDirection == 'bottom') {
        if (this.snake[0].row + 1 > this.height) {
            this.stop()
            alert("游戏结束!")
            return
        }
        this.snake.unshift({
            row: this.snake[0].row + 1,
            col: this.snake[0].col,
            isHaveSnake: true,
            isHaveFood: false,
        })
    }
    if (this.nowMoveDirection == 'top') {
        if (this.snake[0].row - 1 < 1) {
            this.stop()
            alert("游戏结束!")
            return
        }
        this.snake.unshift({
            row: this.snake[0].row - 1,
            col: this.snake[0].col,
            isHaveSnake: true,
            isHaveFood: false,
        })

    }
    if (this.nowMoveDirection == 'right') {
        if (this.snake[0].col + 1 > this.width) {
            this.stop()
            alert("游戏结束!")
            return
        }
        this.snake.unshift({
            row: this.snake[0].row,
            col: this.snake[0].col + 1,
            isHaveSnake: true,
            isHaveFood: false,
        })

    }
    if (this.nowMoveDirection == 'left') {
        if (this.snake[0].col - 1 < 1) {
            this.stop()
            alert("游戏结束!")
            return
        }
        this.snake.unshift({
            row: this.snake[0].row,
            col: this.snake[0].col - 1,
            isHaveSnake: true,
            isHaveFood: false,
        })

    }
    // 默认无视单位体积碰撞 打开此代码则碰撞游戏结束
    // this.snake.forEach((item, index) => {
    //     if (index != 0 && item.row == this.snake[0].row && item.col == this.snake[0].col) {
    //         this.stop()
    //         alert("游戏结束!")
    //     }
    // })

    this.moveDirection = JSON.parse(JSON.stringify(this.nowMoveDirection))
    // 如果吃到食物则不用去掉最后一个  否则去掉最后一个
    if (!this.gameArr[this.snake[0].row - 1][this.snake[0].col - 1].isHaveFood) {
        this.gameArr[this.snake[this.snake.length - 1].row - 1][this.snake[this.snake.length - 1].col - 1].isHaveSnake = false
        this.snake.splice(this.snake.length - 1, 1)
    } else {
        this.snakeWidth++
        this.randomFood()
    }


    this.snake.forEach((item, index) => {
        if (index != 0 && item.row == this.snake[0].row && item.col == this.snake[0].col) {
            this.stop()
            alert("游戏结束!")
        }
        this.gameArr.forEach((l, i) => {
            l.forEach((p, q) => {
                if (item.row == p.row && item.col == p.col) {
                    this.gameArr[i][q].isHaveSnake = true
                }
            })

        })
    });
},
// 监听键盘
keyDown() {
    document.onkeydown = (e) => {
        //事件对象兼容
        let e1 = e || event || window.event || arguments.callee.caller.arguments[0]
        // 如果蛇长度大于1就不能往当前移动方向的相反方向移动
        if (this.snakeWidth > 1) {
            if (e1 && e1.keyCode == 37 && this.moveDirection == 'right') {
                console.log("左 can not move");
                return
            }
            if (e1 && e1.keyCode == 38 && this.moveDirection == 'bottom') {
                console.log("上 can not move");
                return
            }
            if (e1 && e1.keyCode == 39 && this.moveDirection == 'left') {
                console.log("右 can not move");
                return
            }
            if (e1 && e1.keyCode == 40 && this.moveDirection == 'top') {
                console.log("下 can not move");
                return
            }
        }
        // 多按加速  
        // if (e1 && e1.keyCode == 37 && this.moveDirection == 'left') {
        //     this.snakeMove()
        // }
        // if (e1 && e1.keyCode == 38 && this.moveDirection == 'top') {
        //     this.snakeMove()
        // }
        // if (e1 && e1.keyCode == 39 && this.moveDirection == 'right') {
        //     this.snakeMove()
        // }
        // if (e1 && e1.keyCode == 40 && this.moveDirection == 'bottom') {
        //     this.snakeMove()
        // }


        //键盘按键判断:左箭头-37;上箭头-38;右箭头-39;下箭头-40
        if (e1 && e1.keyCode == 37) {
            // 按下左箭头
            this.nowMoveDirection = "left"
            console.log("左");
        } else if (e1 && e1.keyCode == 39) {
            // 按下右箭头
            this.nowMoveDirection = "right"
            console.log("右");
        } else if (e1 && e1.keyCode == 38) {
            // 按下右箭头
            this.nowMoveDirection = "top"
            console.log("上");
        } else if (e1 && e1.keyCode == 40) {
            // 按下右箭头
            this.nowMoveDirection = "bottom"
            console.log("下");
        }
    }
},

区域讲解:

本块是蛇在移动过程中,碰到边界则游戏结束,碰到自己的尾巴也是一样的还有吃到食物变长以及监听键盘上下左右移动事件

4.随机食物

代码如下:

// 随机食物位置
randomFood() {
    let row = Math.floor(Math.random() * this.height) + 1
    let col = Math.floor(Math.random() * this.width) + 1
    this.gameArr.forEach((item, index) => {
        item.forEach((l, i) => {
            if (l.row == row && l.col == col && !l.isHaveSnake) {
                // 生成新的随机食物时  将之前食物置空
                this.gameArr.forEach((p, q) => {
                    p.forEach((k, j) => {
                        k.isHaveFood = false
                    })
                })
                this.gameArr[index][i].isHaveFood = true
            }
        })
    })
},

区域讲解:

本块是随机生成食物块 在格子当中横纵坐标不为蛇块的地方生成食物块

5.总体代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://unpkg.com/vue@2/dist/vue.js"></script>
    <style>
        div {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            height: 100vh;
            width: 100vw;
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        #app {
            height: 100%;
            width: 100%;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        .gameBox {
            width: 80%;
            height: 80%;
            border: 1px solid black;
        }

        .flexBox {
            display: flex;
            width: 100%;
        }

        .flexBox:last-of-type .inBox {
            border-bottom: 0;
        }

        .inBox {
            border: 1px solid #ebeaea;
            border-left: 0;
            border-top: 0;
        }

        .inBox:nth-of-type(100n) {
            border-right: 0;
        }

        .haveSnake {
            background: rgb(114, 111, 111);
        }

        .haveFood {
            background: #5ee252;
        }

        .posiBox {
            position: absolute;
            right: 6px;
            top: 6px;
        }
    </style>
</head>

<body>
    <div id="app">
        <div class="posiBox">
            <!-- <button @click="randomFood">随机食物测试</button> -->
            <button @click="gameBegin">重新开始</button>
            <button @click="again">继续</button>
            <button @click="stop">暂停</button>
        </div>
        <div class="gameBox" ref="gameBox">
            <div v-for="(item, index) in gameArr" :key="index" class="flexBox">
                <div v-for="(l, i) in item" :key="i+1000" :style="`width: ${boxwidth}px;height:${boxheight}px`"
                    class="inBox" :class="l.isHaveSnake?'haveSnake':l.isHaveFood?'haveFood':''"></div>
            </div>
        </div>
    </div>
    <script type="module">
        new Vue({
            el: '#app',
            data: function () {
                return {
                    timer: "", // 蛇移动时的定时器  清除使用
                    boxwidth: 0, // 每个格子的宽
                    boxheight: 0, // 每个格子的高
                    width: 20, // 横着渲染多少个格子
                    height: 10, // 竖着渲染多少个格子
                    gameArr: [], // 渲染贪吃蛇的所有格子
                    snakeWidth: 1, // 贪吃蛇长度
                    snake: [], // 当前贪吃蛇占格
                    moveDirection: "bottom", // 之前移动方向
                    nowMoveDirection: "bottom", // 蛇默认往下走
                    isAgain: true, // 防抖
                }
            },
            methods: {
                // 随机食物位置
                randomFood() {
                    let row = Math.floor(Math.random() * this.height) + 1
                    let col = Math.floor(Math.random() * this.width) + 1
                    this.gameArr.forEach((item, index) => {
                        item.forEach((l, i) => {
                            if (l.row == row && l.col == col && !l.isHaveSnake) {
                                // 生成新的随机食物时  将之前食物置空
                                this.gameArr.forEach((p, q) => {
                                    p.forEach((k, j) => {
                                        k.isHaveFood = false
                                    })
                                })
                                this.gameArr[index][i].isHaveFood = true
                            }
                        })
                    })
                },
                // 初始化
                gameBegin() {
                    this.gameArr = []
                    this.snake = []
                    // 计算每个格子的值
                    for (let i = 0; i < this.height; i++) {
                        this.gameArr.push([])
                        for (let a = 0; a < this.width; a++) {
                            this.gameArr[i].push({
                                row: i + 1, // 第几行
                                col: a + 1, // 第几列
                                isHaveSnake: false, // 这块当中是否有蛇
                                isHaveFood: false, // 是否有食物
                            })
                        }
                    }
                    // 默认第一格有蛇
                    this.gameArr[0][0].isHaveSnake = true
                    this.snake.push(this.gameArr[0][0])
                    this.keyDown()
                    this.again()
                    this.randomFood()
                },
                // 蛇移动函数
                snakeMove() {
                    if (this.nowMoveDirection == 'bottom') {
                        if (this.snake[0].row + 1 > this.height) {
                            this.stop()
                            alert("游戏结束!")
                            return
                        }
                        this.snake.unshift({
                            row: this.snake[0].row + 1,
                            col: this.snake[0].col,
                            isHaveSnake: true,
                            isHaveFood: false,
                        })
                    }
                    if (this.nowMoveDirection == 'top') {
                        if (this.snake[0].row - 1 < 1) {
                            this.stop()
                            alert("游戏结束!")
                            return
                        }
                        this.snake.unshift({
                            row: this.snake[0].row - 1,
                            col: this.snake[0].col,
                            isHaveSnake: true,
                            isHaveFood: false,
                        })

                    }
                    if (this.nowMoveDirection == 'right') {
                        if (this.snake[0].col + 1 > this.width) {
                            this.stop()
                            alert("游戏结束!")
                            return
                        }
                        this.snake.unshift({
                            row: this.snake[0].row,
                            col: this.snake[0].col + 1,
                            isHaveSnake: true,
                            isHaveFood: false,
                        })

                    }
                    if (this.nowMoveDirection == 'left') {
                        if (this.snake[0].col - 1 < 1) {
                            this.stop()
                            alert("游戏结束!")
                            return
                        }
                        this.snake.unshift({
                            row: this.snake[0].row,
                            col: this.snake[0].col - 1,
                            isHaveSnake: true,
                            isHaveFood: false,
                        })

                    }
                    // 默认无视单位体积碰撞 打开此代码则碰撞游戏结束
                    // this.snake.forEach((item, index) => {
                    //     if (index != 0 && item.row == this.snake[0].row && item.col == this.snake[0].col) {
                    //         this.stop()
                    //         alert("游戏结束!")
                    //     }
                    // })

                    this.moveDirection = JSON.parse(JSON.stringify(this.nowMoveDirection))
                    // 如果吃到食物则不用去掉最后一个  否则去掉最后一个
                    if (!this.gameArr[this.snake[0].row - 1][this.snake[0].col - 1].isHaveFood) {
                        this.gameArr[this.snake[this.snake.length - 1].row - 1][this.snake[this.snake.length - 1].col - 1].isHaveSnake = false
                        this.snake.splice(this.snake.length - 1, 1)
                    } else {
                        this.snakeWidth++
                        this.randomFood()
                    }


                    this.snake.forEach((item, index) => {
                        if (index != 0 && item.row == this.snake[0].row && item.col == this.snake[0].col) {
                            this.stop()
                            alert("游戏结束!")
                        }
                        this.gameArr.forEach((l, i) => {
                            l.forEach((p, q) => {
                                if (item.row == p.row && item.col == p.col) {
                                    this.gameArr[i][q].isHaveSnake = true
                                }
                            })

                        })
                    });
                },
                // 暂停
                stop() {
                    // 防抖 如果游戏是继续的  才能暂停
                    if (!this.isAgain) {
                        this.isAgain = true
                        clearInterval(this.timer)
                    }
                },
                // 继续
                again() {
                    // 防抖 如果游戏暂停 才能继续
                    if (this.isAgain) {
                        this.isAgain = false
                        this.timer = setInterval(() => {
                            this.snakeMove()
                        }, 1000)
                    }
                },
                // 监听键盘
                keyDown() {
                    document.onkeydown = (e) => {
                        //事件对象兼容
                        let e1 = e || event || window.event || arguments.callee.caller.arguments[0]
                        // 如果蛇长度大于1就不能往当前移动方向的相反方向移动
                        if (this.snakeWidth > 1) {
                            if (e1 && e1.keyCode == 37 && this.moveDirection == 'right') {
                                console.log("左 can not move");
                                return
                            }
                            if (e1 && e1.keyCode == 38 && this.moveDirection == 'bottom') {
                                console.log("上 can not move");
                                return
                            }
                            if (e1 && e1.keyCode == 39 && this.moveDirection == 'left') {
                                console.log("右 can not move");
                                return
                            }
                            if (e1 && e1.keyCode == 40 && this.moveDirection == 'top') {
                                console.log("下 can not move");
                                return
                            }
                        }
                        // 多按加速  
                        // if (e1 && e1.keyCode == 37 && this.moveDirection == 'left') {
                        //     this.snakeMove()
                        // }
                        // if (e1 && e1.keyCode == 38 && this.moveDirection == 'top') {
                        //     this.snakeMove()
                        // }
                        // if (e1 && e1.keyCode == 39 && this.moveDirection == 'right') {
                        //     this.snakeMove()
                        // }
                        // if (e1 && e1.keyCode == 40 && this.moveDirection == 'bottom') {
                        //     this.snakeMove()
                        // }


                        //键盘按键判断:左箭头-37;上箭头-38;右箭头-39;下箭头-40
                        if (e1 && e1.keyCode == 37) {
                            // 按下左箭头
                            this.nowMoveDirection = "left"
                            console.log("左");
                        } else if (e1 && e1.keyCode == 39) {
                            // 按下右箭头
                            this.nowMoveDirection = "right"
                            console.log("右");
                        } else if (e1 && e1.keyCode == 38) {
                            // 按下右箭头
                            this.nowMoveDirection = "top"
                            console.log("上");
                        } else if (e1 && e1.keyCode == 40) {
                            // 按下右箭头
                            this.nowMoveDirection = "bottom"
                            console.log("下");
                        }
                    }
                },

            },
            mounted() {
                // 首先获取盒子的高宽
                this.boxwidth = this.$refs.gameBox.offsetWidth / this.width
                this.boxheight = this.$refs.gameBox.offsetHeight / this.height
                this.gameBegin()
            },
            destroy() {
                this.stop()
            }
        })
    </script>
</body>

</html>

猜你喜欢

转载自blog.csdn.net/notagoodwriter/article/details/131411783