生成地圖。css
生成食物。html
生成蛇,開始移動。git
監聽鍵盤事件。github
<!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>
* { 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; }
(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)