回歸原生,運用javascript編寫小遊戲 --- 貪食蛇

需求剖析

  1. 天生輿圖。

    • 將運用籠統成一個對象。
    • 輿圖運用一個二維數組作為構造。
  2. 天生食品。

    • 天生食品的局限。
    • 食品不能和身材天生位置重合。
  3. 天生蛇,最先挪動。

    • 蛇遇到牆壁,計算出穿過牆的局限.
    • 蛇遇到本身的身材,Game Over .
    • 蛇吃到食品,長度加一,並天生新的食品
  4. 監聽鍵盤事宜。

    • 對上下左右挪動做出迴響反映。

代碼完成(也能夠檢察 github

html (index.html)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link rel="stylesheet" href="./style/index.css">
</head>
<body>
    <div class="wrap">
        <div id="container">
        </div>
    </div>
    <script src="./js/index.js" ></script>
</body>
</html>

css (./style/index.css)

* {
    margin: 0;
    padding: 0;
}

.wrap{
    display: flex;
    justify-content: center;
    align-content: center;
}

#container{
    width: 100%;
    text-align: center;
}

#container div{
    /* width: 20px;
    height: 20px; */
    float: left;
    border: 1px solid #000;
}

js(./js/index.js)

    (function(self){

    function GreedySnake(gridXN,gridYN){
        // 輿圖
        this.gridXN = gridXN >= 10 ? gridXN : 10; 
        this.gridYN = gridYN >= 10 ? gridYN : 10;
        this.gridSize = 20; //每一個格子的牢固大小
        this.map = []; //保留輿圖中dom對象的二維數組
        this.container = document.getElementById('container');
        

        // 食品屬性
        this.food = null;
        this.foodX = null;
        this.foodY = null;

        // 蛇
        this.snake = [];//將蛇籠統成一個二維列表,列為身材長度,排為坐標數組 
        this.snakeLen = null ; //默許蛇長為3
        // 初始蛇頭坐標
        this.snakeHead = []

        // 蛇的挪動方向
        this.direction = 'top'

        // 速率
        this.speed = 1 ;

        this.timer = null
    }

    GreedySnake.prototype.init = function(){
        this.initMap();
        this.createSnake();
        this.createFood();
        this.snakeMove()
        this.listenKeyBoardEvents()
    }

    GreedySnake.prototype.restart = function(gridXN,gridYN){
    
        // 輿圖
        this.gridXN = null
        this.gridYN = null
        this.gridSize = null
        this.map = null
        this.container = null
        
        // 食品屬性
        this.food = null;
        this.foodX = null;
        this.foodY = null;

        // 蛇
        this.snake = null;
        this.snakeLen = null; 
        // 初始蛇頭坐標
        this.snakeHead = null;

        // 蛇的挪動方向
        this.direction = null;

        // 速率
        this.speed = null;

    }


    // 初始化輿圖
    GreedySnake.prototype.initMap = function(){
        var gridYN = this.gridYN,
            gridXN = this.gridXN,
            w = gridXN * this.gridSize + gridXN + 1 ,
            h = gridYN * this.gridSize + gridYN + 1;
        
        this.container.style.width = w + "px";
        this.container.style.height = h  + 'px';

        for(let y = 0 ; y < gridXN ; y++){
            this.map[y] = [] //初始化二維數組
            for(let x = 0 ; x < gridYN ; x++){
                this.createGrid(x,y)
            }
        }   
    }
    // 建立每一個格子,x軸格子索引,y軸格子索引
    GreedySnake.prototype.createGrid = function(idxX,idxY){
        // 當idxY > 0 時,對應的grid的向左挪動1px,將格子之間的線重合;
        // 當idxX > 0 時,對應的grid的向上挪動1px,將格子之間的線重合;
        let grid = document.createElement('div');
        grid.style.width = this.gridSize + 'px';
        grid.style.height = this.gridSize + "px";
        this.map[idxY][idxX] = grid
        if(idxX > 0 ){
            grid.style.marginLeft = '-1px';
        }
        if(idxY > 0 ){
            grid.style.marginTop = '-1px';
        }
        this.container.appendChild(grid);
    }

    // 建立食品:道理就是依據在局限內的格子數,天生兩個隨機數,作為元素的坐標
    GreedySnake.prototype.createFood = function(){
        var gridYN = this.gridYN,
            gridXN = this.gridXN,
            temp = null ,
            flag = true;
        this.foodX = Math.floor(Math.random() * gridXN); //緩存
        this.foodY = Math.floor(Math.random() * gridYN);

        for(var i = 0 ; i<this.snake.length ; i++){
            temp = this.snake[i]
            // 檢測食品是不是和蛇的身材重合
            while(temp[0] == this.foodY && temp[1] == this.foodX){
                flag = false
                this.createFood();
            }
        }
        if(flag){
            this.food = this.map[this.foodY][this.foodX];
            this.food.style.backgroundColor = '#f00';
        }
    }

    // 天生蛇
    GreedySnake.prototype.createSnake = function(){
        this.snakeLen = 3 ; //默許蛇長為3
        let i = this.snakeLen - 1;
        for(i ; i >= 0; i--){
            this.snake.push([this.gridYN - 1 - i ,this.gridXN - 1 - 3])
            this.map[this.gridYN - 1 - i][this.gridXN - 1 - 3].style.backgroundColor = 'blue'
        }
        // 初始蛇頭坐標
        this.snakeHead = this.snake[0]
        // console.log(this.snake)
    }
    
    // 最先挪動,挪動后蛇頭坐標 +-1 
    GreedySnake.prototype.snakeMove = function(){
        let _this = this,
            sH = this.snakeHead,
            y = null,
            x = null,
            tempH = null,
            last = null,
            alive = true

        function common(){
            
            _this.map[tempH[0]][tempH[1]].style.backgroundColor = 'blue'
            _this.snake.unshift(tempH);
            _this.snakeHead = tempH;
            // 檢測蛇頭是不是和蛇的身材相撞
            for(var i = 1 ; i < _this.snake.length;i++){
                if(_this.snakeHead[0] == _this.snake[i][0] && _this.snakeHead[1] ==  _this.snake[i][2]){
                    alert('GAME OVER');
                    alive = false
                    return false
                }
            }
            // 當蛇吃到食品后再從新建立食品
            if(sH[0] === _this.foodY && sH[1] === _this.foodX){
                _this.createFood()
                return false
            }
            last = _this.snake.pop();
            _this.map[last[0]][last[1]].style.backgroundColor = ''
        }

        switch(this.direction){
            case 'top':
                y = sH[0] //緩存
                tempH = [--y , sH[1] ];
                if(tempH[0] < 0){
                    tempH = [this.gridYN - 1 , sH[1]]
                }
                common();
                break;
            case 'bottom':
                y = sH[0]
                tempH = [++y , sH[1] ];
                // 邊境推斷
                if(tempH[0] > this.gridYN - 1){
                    tempH = [ 0 , sH[1]]
                }
                common()
                break;
            case 'left':
                x = sH[1]
                tempH = [sH[0] , --x ];
                if(tempH[1] < 0){
                    tempH = [ sH[0] , this.gridXN - 1]
                }
                common()
                break;
            case 'right':
                x = sH[1]
                tempH = [sH[0] , ++x ];
                if(tempH[1] > this.gridXN - 1){
                    tempH = [  sH[0] ,  0 ]
                }
                common()
                break;
        }

        alive && setTimeout(function(){
            _this.snakeMove()
        },500 / this.speed)
    }

    // 註冊鍵盤事宜
    GreedySnake.prototype.listenKeyBoardEvents = function(){
        let _this = this
        self.onkeyup = function(e){
            let dir = _this.direction
            switch(e.keyCode){
                case 37:
                    if(dir != 'right'){
                       _this.direction = 'left';
                    }
                    break;
                case 38:
                    if(dir != 'bottom'){
                        _this.direction = 'top';
                    }
                    break;
                case 39:
                    if(dir != 'left'){
                        _this.direction = 'right';
                    }
                    break;
                case 40:
                    if(dir != 'top'){
                        _this.direction = 'bottom';
                    }
                    break;
            }
        }
    }

    GreedySnake.prototype.print = function(){
        return this.map
    }
    
    // 參數寄義:x軸,y軸上的格子數目
    var greedySnake = new GreedySnake(20,20);
    greedySnake.init()
})(window)
    原文作者:lxnxbnq
    原文地址: https://segmentfault.com/a/1190000014515100
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞