经典小游戏2048 代码教学
程序员文章站
2022-03-06 10:38:44
2048的玩法:使用方向键移动方块,两个数字相同的方块撞在一起后,将会合并为一个数字是原来两倍的新方块!在手机上可以滑动屏幕来移动方块!html代码部分Document ...
2048的玩法:
使用方向键移动方块,两个数字相同的方块撞在一起后,将会合并为一个数字是原来两倍的新方块!
在手机上可以滑动屏幕来移动方块!
html代码部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="css/0710.css">
</head>
<body>
<div class="container">
<div class="message">
<span class="span0">游戏说明:</span>移动数字方块,相邻的两个数字方块相同,可合成一块!
</div>
<div class="box">
<p class="pp">Score:<span id="span1">0</span></p>
<button id="btn-start">开始游戏</button>
</div>
<div class="bgall">
<!--第一行-->
<div class="cell" id="c00"></div>
<div class="cell" id="c01"></div>
<div class="cell" id="c02"></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>
<div class="gameover" id="gameover">
<p>GameOver!<br>
Score:<span id="span2">0</span><br />
<a href="#">Try Again!</a>
</p>
</div>
<script src="js/0710.js"></script>
</body>
</html>
css样式
*{
padding: 0;
margin: 0;
font-family: "Arvo", Helvetica, sans-serif;
font-family: 12px;
}
.container{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
.message{
border-top: 1px solid black;
border-bottom: 1px solid black;
padding: 25px 0;
}
.span0{
font-weight: bolder;
}
.bgall{
width: 480px;
height: 480px;
margin:0 auto;
position: relative;
background-color: #9a9a95;
border-radius: 10px;
opacity: 0.7;
}
.box{
width: 480px;
margin: 0 auto;
height: 70px;
}
.pp{
font-size: 45px;
font-weight: bold;
display: inline-block;
width: 250px;
}
/*开始游戏*/
button:nth-of-type(1){
margin-left: 123px;
border-radius: 5px;
background-color: skyblue;
width: 100px;
height: 40px;
color: white;
border: none;
font-size: 17px;
}
/*分数*/
#span1{
color: pink;
}
/*每个小方块的统一样式*/
.cell{
width: 100px;
height: 100px;
border-radius: 6px;
/*position: absolute;*/
margin-top: 16px;
margin-left: 16px;
float: left;
background-color: #F8FFE5;
font-size: 40px;
text-align: center;
color: #fff;
line-height: 100px;
}
.n2{background-color:#FFC43D}
.n4{background-color:#EF476F}
.n8{background-color:#1B9AAA}
.n16{background-color:#06D6A0}
.n32{background-color:#f37694}
.n64{background-color:#22c2d6}
.n128{background-color:#17f8be}
.n256{background-color:#ffd470}
.n512{background-color:#eb184a}
.n1024{background-color:#14727e}
.n2048{background-color:#05a47b}
.n4096{background-color:#a6c}
.n8192{background-color:#93c}
.n2,.n4{color:#F8FFE5}
.n1024,.n2048,.n4096,.n8192{font-size:40px}
/*游戏结束*/
.gameover{
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: rgba(55,55,55,.5);
display: none;
}
.gameover>p{
width: 300px;
height: 200px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
background-color: #fff;
/*外边距调整宽和高的一半,保证元素在页面正中间显示*/
/* margin-top: -257px;
margin-left: -150px; */
text-align: center;
line-height: 1.5em;
border-radius: 10px;
border:1px solid #edcf72;
font-size: 42px;
}
a{
text-decoration: none;
color: pink;
}
#span2{
color: red;
}
js部分
var game = {
data:[], //存放数据
status:0, //当前游戏状态
score: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.updateView();
// 给键盘按下事件绑定事件处理函数
document.onkeydown = function(evert){
var e = evert || window.evert;//兼容性
switch (e.keyCode) {
case 37:
this.moveLeft();
break;
case 39:
this.moveRight();
break;
case 38:
this.moveUp();
break;
case 40:
this.moveDown();
break;
}
}.bind(this);//不改变this指向的话 this是指向document
remove();
},
// 生成随机数
randomNum:function(){
while(true){
var r = Math.floor(Math.random()*4);
var c = Math.floor(Math.random()*4);
// 如果当前位置是0,随机生成2,当前位置值为随机生成的2
if(this.data[r][c] == 0){
var num = 2;
this.data[r][c] = num;
break;
}
}
},
// 更新视图
updateView:function(){
// 循环遍历每个位置
for(var r = 0;r < 4;r++){
for(var c = 0; c < 4;c++){
// 获取当前div的位置
var div = document.getElementById("c" + r + c);
// 如果当前位置的数字不是0,获取的div的内容等于这个数
// 且div的类名为cell n+这个数
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("span1").innerHTML = this.score;
// 监测游戏状态
// 如果游戏状态等于游戏结束状态 游戏结束弹框显示,分数等于当前分数
if(this.status == this.gameover){
document.getElementById("span2").innerHTML = this.score;
document.getElementById("gameover").style.display = "block";
}else{//否则隐藏
document.getElementById("gameover").style.display = "none";
}
},
// 判断游戏是否结束,游戏没有结束返回false,游戏结束返回true
isgameover:function(){
for(var r = 0;r < 4;r++){
for(var c = 0; c < 4;c++){
// 没有结束,3种情况
// 1.数组中还有0
// 2.左右相邻的有相同的
// 3.上下相邻有相同的
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);
// 如果移动前不等于移动后,随机位置生成2 更新视图
if(before != after){
this.randomNum();
// 如果游戏状态是游戏结束 更改游戏状态
if(this.isgameover()){
this.status = this.gameover;
}
this.updateView();
}
},
// 单独处理每一行的逻辑
moveLeftInRow : function(r){
// 循环每一列
for(var c = 0;c < 3;c++){
var nextc = this.getNextInRow(r,c);
// 如果找到了下一个不为0的位置
if(nextc != -1){
// 如果当前位置为0 这个位置和下一个不为0 的交换数字
//如果当前位置数等于下一个位置数 当前位置数*2 分数增加 下一个位置数变为0
if(this.data[r][c] == 0){
this.data[r][c] = this.data[r][nextc];
this.data[r][nextc] = 0;
// c留在原地 等待下一次可能的计算
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;
}
}
},
// 当前位置的下一个位置
getNextInRow : function(r,c){
// 循环下一个位置
for(var i = c +1;i<4;i++){
// 如果当前位置数字不等于0 返回这个数字
if(this.data[r][i] != 0){
return i
}
}
// 等于0 没找到 返回-1
return -1
},
// 右移动
moveRight:function(){
// 移动之前
var before = String(this.data);
// 移动逻辑 循环四行
for(var r = 0;r < 4;r++){
this.moveRightInRow(r);
}
// 移动之后
var after = String(this.data);
// 如果移动前不等于移动后,随机位置生成2 更新视图
if(before != after){
this.randomNum();
// 如果游戏状态是游戏结束 更改游戏状态
if(this.isgameover()){
this.status = this.gameover;
}
this.updateView();
}
},
// 单独处理每一行的逻辑
moveRightInRow : function(r){
// 循环每一列
for(var c =3;c > 0;c--){
var prev = this.getPrevInRow(r,c);
// 如果找到了上一个不为0的位置
if(prev != -1){
// 如果当前位置为0 这个位置和上一个不为0 的交换数字
//如果当前位置数等于上一个位置数 当前位置数*2 分数增加 上一个位置数变为0
if(this.data[r][c] == 0){
this.data[r][c] = this.data[r][prev];
this.data[r][prev] = 0;
// c留在原地 等待下一次可能的计算
c++;
}else if(this.data[r][c] == this.data[r][prev]){
this.data[r][c] *= 2;
this.score += this.data[r][c]
this.data[r][prev] = 0;
}
}else{
// 没找到 跳出
break;
}
}
},
// 当前位置的上一个位置
getPrevInRow : function(r,c){
// 循环上一个位置
for(var i = c - 1;i >= 0;i--){
// 如果当前位置数字不等于0 返回这个数字
if(this.data[r][i] != 0){
return i
}
}
// 等于0 没找到 返回-1
return -1
},
//上移
moveUp : function(){
var before = new String(this.data);
for(var c = 0;c < 4;c++){//从c列开始
this.moveUpInRow(c);
}
var after = String(this.data);
if(before != after){
this.randomNum();
if (this.isgameover()) {
this.status = this.gameover;
}
this.updateView();
}
},
moveUpInRow : function(c){//上移操作
for(var r = 0;r < 3;r++){
// 查找c列r行不为0的
var up = this.getUpInRow(r,c);
if(up != -1){//如果找到
// 如果r位置的值是0
if(this.data[r][c] == 0){
// 将up位置的值赋值给r位置
this.data[r][c] = this.data[up][c];
// 将up位置的值置为0
this.data[up][c] = 0;
// r留在原地 等待下一次可能的计算
r--;
}else if(this.data[r][c] == this.data[up][c]){// 否则,如果r位置的值等于nextc位置的值
// 将r位置的值*2
this.data[r][c] *= 2;
// 将up位置的值置为0
this.data[up][c] = 0;
this.score += this.data[r][c];
}
}else{// 如果没找到
break;
}//退出循环
}
},
getUpInRow : function(r,c){//下一个
for(var i = r + 1;i < 4;i++){
//如果不为0,表示找到,就返回i,i对应的格子的几个位置
if(this.data[i][c] != 0){
return i;
}
}
return -1;//找不到 给一个状态 用-1表示该方法的返回
},
moveDown : function(){//下移
var before = String(this.data);
for(var c = 0; c < 4;c++){
this.moveDownInRow(c);//找每一列不为0的位置
}
var after = String(this.data);
if(before != after){
this.randomNum();
this.updateView();
}
},
moveDownInRow : function(c){//下移操作
for(var r = 3;r > 0;r--){
var Down = this.getDownInRow(r,c);//找到下一个数
if(Down != -1){
// 如果r位置的值是0
if(this.data[r][c] == 0){
// 将up位置的值赋值给r位置
this.data[r][c] = this.data[Down][c];
// 将up位置的值置为0
this.data[Down][c] = 0;
// r留在原地 等待下一次可能的计算
r++;
}else if(this.data[r][c] == this.data[Down][c]){// 否则,如果r位置的值等于nextc位置的值
// 将r位置的值*2
this.data[r][c] *= 2;
// 将up位置的值置为0
this.data[Down][c] = 0;
this.score += this.data[r][c];
}
}else{// 如果没找到
break;
}//退出循环
}
},
getDownInRow : function(r,c){
for(var i = r - 1;i >= 0;i--){
if(this.data[i][c] != 0){
return i;
}
}
return -1;
}
}
document.getElementById("btn-start").onclick = function(){
game.start();
}
大家一步一步来写,看注释,分析。这个是在电脑上玩的,下次我们来教如何把2048小游戏打包成手机APP;
本文地址:https://blog.csdn.net/Orange_Sheep/article/details/107344806