天天看點

我用端午假期寫了個貪吃蛇,學弟玩的不亦樂乎!附(思路注釋+源碼)子產品化開發

學弟玩法:(蚯蚓找媽)

我用端午假期寫了個貪吃蛇,學弟玩的不亦樂乎!附(思路注釋+源碼)子產品化開發

我的玩法:(王母搖頭)

我用端午假期寫了個貪吃蛇,學弟玩的不亦樂乎!附(思路注釋+源碼)子產品化開發

子產品化開發

為什麼要用面向對象寫,有三大特性:封裝、繼承、多态。

為什麼要封裝 : 實作子產品化開發,封裝為一個塊一個塊的,利于維護,有某個子產品出現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>
           

覺得部落客總結的不錯的,可以收藏支援一波~

我用端午假期寫了個貪吃蛇,學弟玩的不亦樂乎!附(思路注釋+源碼)子產品化開發

繼續閱讀