# 2048-原生JS版 **Repository Path**: fenav/game-2048-js ## Basic Information - **Project Name**: 2048-原生JS版 - **Description**: 2048-原生JS版 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-07-17 - **Last Updated**: 2022-07-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 原生JS版2048 ## 核心代码 ```js //创建一个对象,里面存储所有的游戏数据及游戏方法 const game = { data: [], //定义一个数组,用来存所有的游戏的数据 score: 0, //定义一个分数的属性 gamerunning: 1, //定义一个游戏运行的状态,将其设置为1与其他状态区分开 gameover: 0, //定义一个游戏结束的状态 status: 0, //这个是目前游戏的状态,时刻的跟上面两个状态做比较,确定游戏处于运行或者结束 start() { //游戏开始时候的方法 // 游戏开始的时候肯定是要把游戏的状态设置成游戏运行的状态 // this == game this.status = this.gamerunning // 游戏开始的时候分数清空 this.score = 0 // 数组中的所有元素全部设置成0 this.data = [ [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], ] this.randomNum() //调用下面自定义的随机函数,可以在移动和开始的时候随机出来一个数 this.randomNum() //调用两次是因为这是游戏开始时的方法,开局随机出现两个数和位置,因此需要调用两次 this.dataView() //调用下面所写的更新视图的方法 }, // 随机数的函数,开始的时候随机生成,移动的时候随机生成 randomNum() { while (true) { // 随机生成行和列 0 - 3随机整数 const r = Math.floor(Math.random() * 4) //随机生成一个行 const c = Math.floor(Math.random() * 4) //随机生成一个列 // 如果是空,则生成随机数 if (this.data[r][c] === 0) { const num = Math.random() > 0.5 ? 2 : 4 //随机出现2或4 this.data[r][c] = num // 生成后退出循环 break } } }, // 更新试图的方法 dataView() { // 大的循环,然后把所有的元素全部遍历一遍 for (let r = 0; r < 4; r++) { for (let c = 0; c < 4; c++) { // 找到对应的div const div = document.getElementById(`c${r}${c}`) // 字符串拼接 // 如果数值为非空 if (this.data[r][c] !== 0) { // 数组中对应的内容放到格子上面去 div.innerHTML = this.data[r][c] // 样式也写成对应的 div.className = `cell n${this.data[r][c]}` } else { // 为空的情况 div.innerHTML = '' div.className = 'cell' } } } // 更新分数 document.getElementById('score01').innerHTML = this.score //游戏没有结束的时候 弹出层时刻都是隐藏的 if (this.status === this.gamerunning) { document.getElementById('gameover').style.display = 'none' } else { document.getElementById('gameover').style.display = 'block' document.getElementById('score02').innerHTML = this.score } }, // 判断游戏是否结束的方法 isgameover() { for (let r = 0; r < 4; r++) { for (let c = 0; c < 4; c++) { // 里面有空格子的时候,游戏还是可以运行 if (this.data[r][c] === 0) { return false //表示游戏还没有结束 } // 判断左右是否有相同的 if (c < 3) { if (this.data[r][c] === this.data[r][c + 1]) { return false } } if (r < 3) { if (this.data[r][c] === this.data[r + 1][c]) { return false } } } } return true }, // 左 右 上 下 // 左移的方法 moveLeft() { const before = String(this.data) //之前做一次转换 // 具体的移动需要处理的逻辑,直接处理好每一行即可 for (let r = 0; r < 4; r++) { this.moveLeftInRow(r) } const after = String(this.data) //移动之后再做一次转换 // 如果说移动之前不等于移动之后,肯定是发生了移动 if (before !== after) { this.randomNum() //生成随机数 // 生成的随机数可能会造成游戏的 gameover if (this.isgameover()) { // 改变游戏的状态 this.status = this.gameover } // 更新视图 this.dataView() } }, moveLeftInRow(r) { //只去做处理每一行的逻辑 for (let c = 0; c < 3; c++) { const nextc = this.getNextinRow(r, c) if (nextc !== -1) { // 如果等于0,直接替换 if (this.data[r][c] === 0) { this.data[r][c] = this.data[r][nextc] this.data[r][nextc] = 0 //位置恢复成0 c-- //要让位置恢复到原地 } else if (this.data[r][c] == this.data[r][nextc]) { this.data[r][c] *= 2 //位置直接翻一倍 this.data[r][nextc] = 0 this.score += this.data[r][c] //更新分数 } } else { //没有找到 break //直接退出循环 } } }, getNextinRow(r, c) { for (let i = c + 1; i < 4; i++) { if (this.data[r][i] !== 0) { return i //表示已经找到位置,并且把位置返回出来 } } return -1 //返回一个标识符 }, // 右移的方法 moveRight() { const before = String(this.data) for (let r = 0; r < 4; r++) { this.moveRightInRow(r) } const after = String(this.data) if (before !== after) { this.randomNum() if (this.isgameover()) { this.status = this.gameover } this.dataView() } }, moveRightInRow(r) { for (let c = 4; c > 0; c--) { const prevc = this.getPrevInRow(r, c) if (prevc !== -1) { if (this.data[r][c] === 0) { this.data[r][c] = this.data[r][prevc] this.data[r][prevc] = 0 c++ } else if (this.data[r][c] === this.data[r][prevc]) { this.data[r][c] *= 2 this.data[r][prevc] = 0 this.score += this.data[r][c] } } else { break } } }, getPrevInRow(r, c) { for (let i = c - 1; i >= 0; i--) { if (this.data[r][i] != 0) { return i } } return -1 }, // 上移 moveUp() { const before = String(this.data) for (let c = 0; c < 4; c++) { this.moveUpInCol(c) } const after = String(this.data) if (before !== after) { this.randomNum() if (this.isgameover()) { this.status = this.gameover } this.dataView() } }, moveUpInCol(c) { for (let r = 0; r < 4; r++) { const nextr = this.getNextInCol(r, c) if (nextr !== -1) { if (this.data[r][c] === 0) { this.data[r][c] = this.data[nextr][c] this.data[nextr][c] = 0 r-- } else if (this.data[r][c] === this.data[nextr][c]) { this.data[r][c] *= 2 this.data[nextr][c] = 0 this.score += this.data[r][c] } } else { break } } }, getNextInCol(r, c) { for (let i = r + 1; i < 4; i++) { if (this.data[i][c] != 0) { return i } } return -1 }, // 下移的方法 moveDown() { const before = String(this.data) for (let c = 0; c < 4; c++) { this.moveDownInCol(c) } const after = String(this.data) if (before !== after) { this.randomNum() if (this.isgameover()) { this.status = this.gameover } this.dataView() } }, moveDownInCol(c) { for (let r = 3; r > 0; r--) { const prev = this.getPrevIncol(r, c) if (prev !== -1) { if (this.data[r][c] === 0) { this.data[r][c] = this.data[prev][c] this.data[prev][c] = 0 r-- } else if (this.data[r][c] === this.data[prev][c]) { this.data[r][c] *= 2 this.data[prev][c] = 0 this.score += this.data[r][c] } } else { break } } }, getPrevIncol(r, c) { for (let i = r - 1; i >= 0; i--) { if (this.data[i][c] != 0) { return i } } return -1 }, } game.start() console.log(game.data) console.log(game.status) console.log(game.score) //键盘事件 document.onkeydown = function (event) { if (event.keyCode === 37) { //console.log("左") game.moveLeft() } else if (event.keyCode === 38) { //console.log("上") game.moveUp() } else if (event.keyCode === 39) { //console.log("右") game.moveRight() } else if (event.keyCode === 40) { //console.log("下") game.moveDown() } } //touch事件 //手指按下 let startX //设定开始起始位置的x坐标 let startY //设定开始起始位置的y坐标 let endX //设定结束滑动位置的x坐标 let endY //设定结束滑动位置的y坐标 document.addEventListener('touchstart', function (event) { // console.log("手指按下了屏幕") console.log(event) startX = event.touches[0].pageX startY = event.touches[0].pageY }) //手指移动 //document.addEventListener('touchmove',function(){ // console.log("手指的移动") //}) //手指松开 document.addEventListener('touchend', function (event) { // console.log("手指松开") console.log(event) endX = event.changedTouches[0].pageX //如何获取结束时的位置x endY = event.changedTouches[0].pageY const X = endX - startX const Y = endY - startY const absX = Math.abs(X) > Math.abs(Y) const absY = Math.abs(Y) > Math.abs(X) if (X > 0 && absX) { console.log('右滑动') game.moveRight() } else if (X < 0 && absX) { console.log('左滑动') game.moveLeft() } if (Y > 0 && absY) { console.log('下滑动') game.moveDown() } if (Y < 0 && absY) { console.log('上滑动') game.moveUp() } }) document.querySelector('.startbtn').addEventListener('click', () => { game.start() }) ```