首先这个小游戏,相信大家一定都玩过,那今天就一步一步来实现。目前为止,基本功能已经实现,只是没有添加相应的动画效果,待以后有机会补上。
基本思路
当初次游戏的时候,视图更新,分数更新,随机在两个位置生成一个数,当按左键的时候,所有的数字往左移动,如果有相邻相同的数字就相加,同时再随机生成一个,右上下亦是如此。
主要功能
1.游戏初始化:新建游戏4×4的16宫格画布,随机格子上生成2或者4两个数字
2.格子的移动:先判断能否移动,移动后判断能否合并,合并后改变格子颜色和数字
3.新格子的生成:移动一次,就在剩余的空格子中随机生成一个2或者4
4.GAMEOVER:16宫格中没有剩余空格子且不能再向任何方向移动则为游戏失败
一、HTML结构
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2048</title>
<link rel="shortcout icon" href="https://2048game.com/favicon.ico">
<link rel="stylesheet" href="index.css">
</head>
<body>
<p class="score" >SCORE:<span id="score01">0</span></p>
<div class="play">
<!-- 第一行 -->
<div class="cell n2" id="c00">2</div>
<div class="cell n4" id="c01">4</div>
<div class="cell n8" id="c02">8</div>
<div class="cell" id="c03"></div>
<!-- 第二行 -->
<div class="cell" id="c10"></div>
<div class="cell" id="c11"></div>
<div class="cell" id="c12"></div>
<div class="cell" id="c13"></div>
<!-- 第三行 -->
<div class="cell" id="c20"></div>
<div class="cell" id="c21"></div>
<div class="cell" id="c22"></div>
<div class="cell" id="c23"></div>
<!-- 第四行 -->
<div class="cell" id="c30"></div>
<div class="cell" id="c31"></div>
<div class="cell" id="c32"></div>
<div class="cell" id="c33"></div>
</div>
<!-- 游戏结束 -->
<div class="gameover" id="gameover">
<p>
GAME OVER!<br>
SCORE: <span id="score02">0</span><br>
<a href="">Try again</a>
</p>
</div>
<script src="index.js"></script>
</body>
</html>
HTML结构的主要思路为:利用网格布局将游戏画布的16宫格绘制出来,通过class定制样式,id定位到具体的格子以重绘格子样式
二、CSS样式
*{
margin: 0;
padding: 0;
font-family: "Arial";
}
.score{
width: 500px;
margin: auto;
font-size: 40px;
padding-top: 50px;
font-weight: bold;
}
.play{
width: 500px;
height: 500px;
background-color: #BBADA0;
border-radius: 15px;
margin: 10px auto;
}
.cell{
width: 100px;
height: 100px;
margin: 20px 0 0 20px;
background-color: #CDC1B4;
float: left;
border-radius: 5px;
text-align: center;
line-height: 100px;
font-size: 40px;
color: white;
}
.n2{background-color: #eee3da;color: #776e65;}
.n4{background-color: #ede0c8;color: #776e65;}
.n8{background-color: #f2b179;}
.n16{background-color: #f59563;}
.n32{background-color: #f67c5f;}
.n64{background-color: #f65e3b;}
.n128{background-color: #edcf72;}
.n256{background-color: #edcc61;}
.n512{background-color: #9c0;}
.n1024{background-color: #33b5e5;font-size: 40px;}
.n2048{background-color: #09c;font-size: 40px;}
.n4096{background-color: #a6c;font-size: 40px;}
.n8192{background-color: #93c;font-size: 40px;}
.gameover{
display: none;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: rgba(0,0,0,.3);
}
.gameover p{
width: 400px;
height: 300px;
background-color: white;
border: 1px solid #000;
border-radius: 10px;
position: absolute;
top: 50%;
left: 50%;
margin-left: -180px;
margin-top: -140px;
text-align: center;
font-weight: bold;
font-size: 35px;
line-height: 100px;
}
.gameover a{
color: white;
background-color:#f2b179 ;
text-decoration: none;
border-radius: 5px;
padding: 15px;
}
三、JS逻辑代码
方法肯定是多种多样的,这里我们创建了一个game对象,将所有的方法放到这个对象中,直接调用。
完整的移动逻辑应该是:先判断该方向上能否移动,但由于我们的移动是分次传入,只要有一次的结果是可移动,那么整个二维数组都是可移动的,所以要先将分次传入的数组进行移动处理后的结果保存在新数组里,当四次分次传入均处理完且其中有一个能移动时,将新数组的值赋值给原数组board,完成二维数组的条件更新。
var game = {
data: [], //存放数据
score: 0, //分数
status: 0, //当前游戏状态
gameover: 0,
gameRunning: 1,
//开始游戏的方法
start: function () {
this.score = 0; //清空分数
this.data = [
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]
]
this.status = this.gameRunning;
this.randomNum();
this.randomNum();
this.dataView();
},
//随机数的方法
randomNum: function () {
for (;;) {
var r = Math.floor(Math.random() * 4);
var c = Math.floor(Math.random() * 4);
if (this.data[r][c] == 0) {
var num = Math.random() > 0.2 ? 2 : 4;
this.data[r][c] = num;
break;
}
}
},
//更新视图的方法
dataView: function () {
for (var r = 0; r < 4; r++) {
for (var c = 0; c < 4; c++) {
var 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.gameover) {
document.getElementById('score02').innerHTML = this.score;
document.getElementById('gameover').style.display = 'block';
} else {
document.getElementById('gameover').style.display = 'none';
}
},
//判断游戏结束的方法
isgameover: function () {
for (var r = 0; r < 4; r++) {
for (var 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 : function () {
var before = String(this.data); //移动之前
//处理移动的逻辑
for (var r = 0; r < 4; r++) {
this.moveLeftInRow(r);
}
var after = String(this.data); //移动之后
if (before != after) {
this.randomNum();
if (this.isgameover()) {
this.status = this.gameover;
}
this.dataView();
}
},
//单独处理每一行
moveLeftInRow: function (r) {
for (var c = 0; c < 3; c++) {
var nextc = this.getLeftNextInRow(r, c);
if (nextc != -1) {
if (this.data[r][c] == 0) {
this.data[r][c] = this.data[r][nextc];
this.data[r][nextc] = 0;
c--;
} else if (this.data[r][c] == this.data[r][nextc]) {
this.data[r][c] *= 2;
this.score += this.data[r][c];
this.data[r][nextc] = 0;
}
} else {
break;
}
}
},
//查找返回下一个不是0的下标
getLeftNextInRow : function (r,c) {
for (var i = c + 1; i < 4; i++) {
if (this.data[r][i] != 0) {
return i;
}
}
return -1;
},
//右移动
moveRight:function(){
var before = String(this.data); //移动之前
//处理移动的逻辑
for (var r = 0; r < 4; r++) {
this.moveRightInRow(r);
}
var after = String(this.data); //移动之后
if (before != after) {
this.randomNum();
if (this.isgameover()) {
this.status = this.gameover;
}
this.dataView();
}
},
//单独处理每一行
moveRightInRow : function(r){
for(var c=3;c>0;c--){
var nextc = this.getRightNextInRow(r, c);
if (nextc != -1) {
if (this.data[r][c] == 0) {
this.data[r][c] = this.data[r][nextc];
this.data[r][nextc] = 0;
c++;
} else if (this.data[r][c] == this.data[r][nextc]) {
this.data[r][c] *= 2;
this.score += this.data[r][c];
this.data[r][nextc] = 0;
}
} else {
break;
}
}
},
//查找返回下一个不是0的下标
getRightNextInRow : function (r,c) {
for (var i = c - 1; i>=0; i--) {
if (this.data[r][i] != 0) {
return i;
}
}
return -1;
},
//上移动
moveUp : function(){
var before = String(this.data); //移动之前
//处理移动的逻辑
for (var c = 0; c < 4; c++) {
this.moveUpInRow(c);
}
var after = String(this.data); //移动之后
if (before != after) {
this.randomNum();
if (this.isgameover()) {
this.status = this.gameover;
}
this.dataView();
}
},
//单独处理每一行
moveUpInRow : function(c){
for (var r = 0; r < 3; r++) {
var nextr = this.getUpNextInRow(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.score += this.data[r][c];
this.data[nextr][c] = 0;
}
} else {
break;
}
}
},
//查找返回下一个不是0的下标
getUpNextInRow : function(r,c){
for (var i = r + 1; i < 4; i++) {
if (this.data[i][c] != 0) {
return i;
}
}
return -1;
},
//下移动
moveDown : function(){
var before = String(this.data); //移动之前
//处理移动的逻辑
for (var c = 0; c < 4; c++) {
this.moveDownInRow(c);
}
var after = String(this.data); //移动之后
if (before != after) {
this.randomNum();
if (this.isgameover()) {
this.status = this.gameover;
}
this.dataView();
}
},
//单独处理每一行
moveDownInRow : function(c){
for (var r = 3; r > 0; r--) {
var nextr = this.getDownNextInRow(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.score += this.data[r][c];
this.data[nextr][c] = 0;
}
} else {
break;
}
}
},
//查找返回下一个不是0的下标
getDownNextInRow : function(r,c){
for (var i = r - 1; i>=0; i--) {
if (this.data[i][c] != 0) {
return i;
}
}
return -1;
},
}
game.start();
document.onkeydown = function (e) {
if (e.keyCode == 37) {
game.moveLeft();
}
if(e.keyCode==39){
game.moveRight();
}
if(e.keyCode==38){
game.moveUp();
}
if(e.keyCode==40){
game.moveDown();
}
}
本文地址:https://blog.csdn.net/qq_46366496/article/details/107281088
如对本文有疑问, 点击进行留言回复!!
androidx+viewpage+tablayout+json开发(加载图片和视频)
网友评论