贪吃蛇
一、html
< div class = " container" id = " app" > </ div> < script src = " ./js/index.js" > </ script>
二、css
* { margin : 0; top : 0; }
.set { margin : 15px auto; width : 600px;
}
.container { width : 600px; height : 600px; background-color : #225675; margin : 40px auto; outline : 20px solid #7dd9ff; position : relative;
}
.snake { position : absolute;
}
.snake-head { width : 0px; height : 0px; border-bottom : 10px solid transparent; border-left : 10px solid rgb ( 157, 219, 177) ; border-right : 10px solid transparent; border-top : 10px solid transparent; transform : rotate ( 0deg) ;
} .snake-body { border-radius : 50%; background-color : #7db5ff;
}
.egg { position : absolute; background-color : rgb ( 241, 54, 232) ; border-radius : 50%;
} .cover { position : absolute; top : 0; left : 0; right : 0; bottom : 0; background-color : rgba ( 0, 0, 0, 0.5) ; display : flex; justify-content : center; align-items : center;
}
.cover .content { width : 60%; height : 50px; background-color : rgb ( 134, 225, 237) ; display : flex; justify-content : center; align-items : center;
}
三、JavaScript
function getRandom ( rate ) { return Math. floor ( Math. random ( ) * rate) ;
}
class Snake { constructor ( snakeBody, size, direction ) { this . direction = direction; this . size = size; this . snakeBody = snakeBody. length > 0 && snakeBody. map ( ( pos ) => ( { left : pos. left * size, top : pos. top * size, } ) ) ; } render ( ) { let template = "" ; let transformDeg = 0 ; switch ( this . direction) { case "right" : transformDeg = 0 ; break ; case "down" : transformDeg = 90 ; break ; case "left" : transformDeg = 180 ; break ; case "up" : transformDeg = - 90 ; break ; } return this . snakeBody. reduce ( ( prev, next, currentIndex ) => { if ( currentIndex === 0 ) { template = prev + ` <div class="snake-head snake" style="left: ${ next. left} px;top: ${ next. top} px;border-width: ${ this . size / 2 } px;transform: rotate( ${ transformDeg} deg);"></div>\n ` ; } else { template = prev + ` <div class="snake-body snake" style="left: ${ next. left} px;top: ${ next. top} px;width: ${ this . size} px;height: ${ this . size} px;transform: rotate( ${ transformDeg} deg);"></div> ` ; } return template; } , "" ) ; } nextStep ( ) { const head = this . snakeBody[ 0 ] ; let newHead; switch ( this . direction) { case "right" : newHead = { left : head. left + this . size, top : head. top } ; break ; case "down" : newHead = { left : head. left, top : head. top + this . size } ; break ; case "left" : newHead = { left : head. left - this . size, top : head. top } ; break ; case "up" : newHead = { left : head. left, top : head. top - this . size } ; break ; } this . snakeBody. unshift ( newHead) ; this . snakeBody. pop ( ) ; console. log ( this . direction) ; console. log ( this . size) ; console. log ( this . snakeBody) ; } snakeGrowUp ( ) { let snake = this . snakeBody; let lens = snake. length; let snakeTail; const prev = snake[ lens - 2 ] ; const next = snake[ lens - 1 ] ; if ( prev. top === next. top && prev. left < next. left) { snakeTail = { ... next, left : next. left + this . size } ; } else if ( prev. top === next. top && prev. left > next. left) { snakeTail = { ... next, left : next. left - this . size } ; } else if ( prev. left === next. left && prev. top > next. top) { snakeTail = { ... next, top : next. top - this . size } ; } else { snakeTail = { ... next, top : next. top + this . size } ; } this . snakeBody. push ( snakeTail) ; this . render ( ) ; } isArriveWall ( ) { const snake = this . snakeBody; let isEnd; if ( snake[ 0 ] . left >= this . size * MAPSIZE || snake[ 0 ] . top >= this . size * MAPSIZE || snake[ 0 ] . left < 0 || snake[ 0 ] . top < 0 ) { isEnd = true ; } for ( let i = 1 ; i < snake. length; i++ ) { if ( snake[ 0 ] . left === snake[ i] . left && snake[ 0 ] . top === snake[ i] . top) { isEnd = true ; break ; } } return isEnd; } changeSnakeDirection ( direction ) { this . direction = direction; }
}
class Egg { constructor ( size ) { this . position = { left : 3 * size, top : 0 * size } ; this . size = size; } render ( ) { const div = document. createElement ( "div" ) ; div. innerHTML = ` <div class='egg' style="left: ${ this . position. left} px;top: ${ this . position. top} px;width: ${ this . size} px;height: ${ this . size} px"> ` ; return div. children[ 0 ] ; } flushed ( ) { this . position = { left : getRandom ( MAPSIZE ) * this . size, top : getRandom ( MAPSIZE ) * this . size, } ; }
}
function isArriveEgg ( snake, egg ) { const snakeBody = snake. snakeBody; return ( snakeBody[ 0 ] . left === egg. position. left && snakeBody[ 0 ] . top === egg. position. top) ;
} const MAPSIZE = 30 ;
let timer;
function init ( app ) { const snake = new Snake ( [ { left : 2 , top : 0 } , { left : 1 , top : 0 } , { left : 0 , top : 0 } , ] , 20 ) ; const egg = new Egg ( 20 ) ; render ( app, snake, egg) ; let direction; document. addEventListener ( "keydown" , ( e ) => { if ( e. key === "ArrowUp" || e. key. toLocaleLowerCase ( ) === "w" ) { direction != "down" && ( direction = "up" ) ; } else if ( e. key === "ArrowDown" || e. key. toLocaleLowerCase ( ) === "s" ) { direction != "up" && ( direction = "down" ) ; } else if ( e. key === "ArrowRight" || e. key. toLocaleLowerCase ( ) === "d" ) { direction != "left" && ( direction = "right" ) ; } else if ( e. key === "ArrowLeft" || e. key. toLocaleLowerCase ( ) === "a" ) { direction != "right" && ( direction = "left" ) ; } else { return ; } snake. changeSnakeDirection ( direction) ; timer && clearInterval ( timer) ; direction && autoMove ( app, snake, egg) ; } ) ;
}
function autoMove ( app, snake, egg ) { timer = setInterval ( ( ) => { snake. nextStep ( ) ; if ( isArriveEgg ( snake, egg) ) { snake. snakeGrowUp ( ) ; egg. flushed ( ) ; } if ( snake. isArriveWall ( ) ) { endGame ( app, snake) ; } else { render ( app, snake, egg) ; } } , Math. floor ( 1000 / 5 ) ) ;
}
function render ( app, snake, egg ) { const snakeTemplate = snake. render ( ) ; const eggDom = egg. render ( ) ; app. innerHTML = snakeTemplate; app. appendChild ( eggDom) ;
}
function endGame ( App, snake ) { timer && clearInterval ( timer) ; const div = document. createElement ( "div" ) ; div. innerHTML = ` <div class="cover"><div class="content">游戏结束,得分 ${ snake. snakeBody. length - 3 } </div></div> ` ; const endGameDom = div. children[ 0 ] ; App. parentNode. appendChild ( endGameDom) ; endGameDom. addEventListener ( "click" , ( ) => { App. parentNode. removeChild ( endGameDom) ; init ( App) ; } ) ;
}
四、样式截图