JavaScript之2048 JS css
Posted fatinggoodboy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript之2048 JS css相关的知识,希望对你有一定的参考价值。
/*game 2048*/
//事件处理对象
var EventUtil =
//添加事件
addHandler: function (element, type, handler)
if (element.addEventListener)
element.addEventListener(type, handler, false);
else if (element.attachEvent)
element.attachEvent("on" + type, handler);
else
element["on" + type] = handler;
,
//获取事件对象
getEvent: function (event)
return event ? event : window.event;//兼容ie
function Game(tileContainer, scoreEle, bestScoreEle)
this.tileContainer = tileContainer;
this.scoreEle = scoreEle;
this.bestScoreEle = bestScoreEle;
this.tiles = new Array(4);//创建存方块数值与dom对象的数组
Game.prototype =
//初始化游戏
init: function ()
this.posArray = [];//创建存空白方块坐标的数组
for (var i = 0, len = this.tiles.length; i < len; i++)
this.tiles[i] = [];
for (var j = 0; j < len; j++)
this.tiles[i][j] = num: 0 ; //初始化存方块数值与dom对象的数组
this.posArray.push( "x": i, "y": j );//初始化存方块坐标的数组
this.deleteTile(true);//清空全部方块
this.score = 0;//初始化分数
this.bestScore = this.bestScore || 0;//初始化最佳分数,第一次为0
this.newTile();//随机创建一个方块
this.newTile();
,
//创建一个方块
newTile: function ()
var tile = document.createElement("div"),
pos = this.randomPos(),//随机新方块位置
num = Math.random() < 0.9 ? 2 : 4;//随机新方块数值2或4
this.tiles[pos.x][pos.y] = num: num, tile: tile ;//将新方块的数值与dom对象存入数组
this.setTile(tile, num, pos.x, pos.y);//设置方块属性产生移动与淡入效果
this.tileContainer.appendChild(tile);
,
//设置方块class和显示的数字,
setTile: function (element, num, x, y)
element.innerhtml = num;
element.className = "tile tile-" + num + " tile-pos-" + x + "-" + y;
,
//随机一方块的位置
randomPos: function ()
var index = Math.floor(Math.random() * this.posArray.length);
var pos = this.posArray[index];
this.posArray.splice(index, 1);//将新方块的位置从存空白坐标的数组中删除
return pos;
,
//方块移动处理
moveTile: function (keyCode)
var len = this.tiles.length,
merge;//存合并状态
switch (keyCode)
//左移
case 37:
for (var i = 1; i < len; i++)
for (var j = 0; j < len; j++)
if (this.tiles[i][j].num != 0 && this.leftMove(i, j)) //值不为0且可移动
merge = this.merge(i, j);//合并
break;
//右移
case 39:
for (var i = len - 2; i >= 0; i--)
for (var j = 0; j < len; j++)
if (this.tiles[i][j].num != 0 && this.rightMove(i, j))
merge = this.merge(i, j);
break;
//上移
case 38:
for (var i = 0; i < len; i++)
for (var j = 1; j < len; j++)
if (this.tiles[i][j].num != 0 && this.upMove(i, j))
merge = this.merge(i, j);
break;
//下移
case 40:
for (var i = 0; i < len; i++)
for (var j = len - 2; j >= 0; j--)
if (this.tiles[i][j].num != 0 && this.downMove(i, j))
merge = this.merge(i, j);
break;
if (merge)
this.newTile();//合并之后创建一个方块
else if (this.posArray.length == 0 && this.gameOverTest()) //当存空白位置的数组为空且没有一个方向可移动,游戏结束
this.gameOver();
,
//方块左移动
leftMove: function (i, j)
this.num = this.tiles[i][j].num;
this.moveI = undefined;
this.moveJ = undefined;
for (var n = i - 1; n >= 0; n--)
if (this.tiles[n][j].num == 0)
this.moveI = n;
else if (this.tiles[n][j].num == this.num)
this.num *= 2;
this.moveI = n;
if (this.num == 2048)
this.gameWin();
this.getScore(this.num);
break;
else
break;
this.moveJ = j;
if (!(this.moveI + 1) || !(this.moveJ + 1))
return;
return true;
,
//方块右移动
rightMove: function (i, j)
var len = this.tiles.length;
this.num = this.tiles[i][j].num;
this.moveI = undefined;
this.moveJ = undefined;
for (var n = i + 1; n < len; n++)
if (this.tiles[n][j].num == 0)
this.moveI = n;
else if (this.tiles[n][j].num == this.num)
this.num *= 2;
this.moveI = n;
if (this.num == 2048)
this.gameWin();
this.getScore(this.num);
break;
else
break;
this.moveJ = j;
if (!(this.moveI + 1) || !(this.moveJ + 1))
return;
return true;
,
//方块上移动
upMove: function (i, j)
this.num = this.tiles[i][j].num;
this.moveI = undefined;
this.moveJ = undefined;
for (var n = j - 1; n >= 0; n--)
if (this.tiles[i][n].num == 0)
this.moveJ = n;
else if (this.tiles[i][n].num == this.num)
this.moveJ = n;
this.num *= 2;
if (this.num == 2048)
this.gameWin();
this.getScore(this.num);
break;
else
break;
this.moveI = i;
if (!(this.moveI + 1) || !(this.moveJ + 1))
return;
return true;
,
//方块下移动
downMove: function (i, j)
var len = this.tiles.length;
this.num = this.tiles[i][j].num;
this.moveI = undefined;
this.moveJ = undefined;
for (var n = j + 1; n < len; n++)
if (this.tiles[i][n].num == 0)
this.moveJ = n;
else if (this.tiles[i][n].num == this.num)
this.moveJ = n;
this.num *= 2;
if (this.num == 2048)
this.gameWin();
this.getScore(this.num);
break;
else
break;
this.moveI = i;
if (!(this.moveI + 1) || !(this.moveJ + 1))
return;
return true;
,
//合并方块
merge: function (i, j)
var me = this;
if (this.num > this.tiles[i][j].num)
//this.num的值变化,即遇到相同值的方块,可移动到其位置,只需删除被覆盖的方块
this.deleteTile(false, this.tiles[this.moveI][this.moveJ].tile);
//将移到相同值的方块的位置上的方块的原始位置添加到存空白坐标的数组中
this.posArray.push( x: i, y: j );
else if (this.num == this.tiles[i][j].num)
//值未变化,即遇到空白方块。只需将空白数组中该空白方块的坐标改为移动的方块的原始坐标
this.posArray.forEach(function (item)
if (item.x == me.moveI && item.y == me.moveJ)
item.x = i;
item.y = j;
);
//设置将移动的方块的属性,产生移动效果
this.setTile(this.tiles[i][j].tile, this.num, this.moveI, this.moveJ);
//在存方块数值与dom对象的数组中将移动的方块的值设为空白值(即num:0),被覆盖的方块的值设为将移动的方块的值
this.tiles[this.moveI][this.moveJ] = num: this.num, tile: this.tiles[i][j].tile ;
this.tiles[i][j] = num: 0 ;
return true;
,
//删除dom节点
deleteTile: function (all, tile)
if (all)
this.tileContainer.innerHTML = "";//清空所有
else
this.tileContainer.removeChild(tile);//删除单个
,
//得分计算
getScore: function (score)
this.score += score;
this.scoreEle.innerHTML = this.score;
if (this.score > this.bestScore)
this.bestScore = this.score//当前分数大于最佳分数,覆盖最佳分数
this.bestScoreEle.innerHTML = this.bestScore;
,
//当出现2048即win,可继续挑战
gameWin: function ()
var me = this;
win = document.createElement("div"),
continueBtn = document.createElement("button");
continueBtn.className = "game-win-again";
win.className = "game-win";
win.appendChild(continueBtn);
this.tileContainer.appendChild(win);
EventUtil.addHandler(continueBtn, "click", function ()
me.deleteTile(false, win);
);
,
//游戏结束测试
gameOverTest: function ()
var len = this.tiles.length;
for (var i = 0; i < len; i++)
for (var j = 0; j < len; j++)
if (this.leftMove(i, j) || this.rightMove(i, j) || this.upMove(i, j) || this.downMove(i, j))
return;//只要有一个方向可移动即退出
return true;//没有一个方向可移动即游戏结束
,
//游戏结束消息
gameOver: function ()
var message = document.createElement("div");
message.className = "game-over";
this.tileContainer.appendChild(message);
,
//添加事件处理程序
initEvent: function ()
var me = this;
//添加键盘弹起事件,限制一直按下重复触发
EventUtil.addHandler(window, "keyup", function (event)
me.moveTile(EventUtil.getEvent(event).keyCode);
);
,
//用于移动端,判断toustart的开始坐标是否在游戏区域gameContainer内
touchPosTest: function (startX, startY)
var container = document.getElementById("container"),
gameContainer = document.getElementById("game-container");
//container与gameContainer宽度一致,即gameContainer的offsetLeft是其已定位父元素container的offsetLeft
var gameContainerStartX = container.offsetLeft,
gameContainerStartY = container.offsetTop + gameContainer.offsetTop,
gameContainerEndX = gameContainerStartX + gameContainer.offsetWidth,
gameContainerEndY = gameContainerStartY + gameContainer.offsetHeight;
return (startX >= gameContainerStartX && startX <= gameContainerEndX) && (startY >= gameContainerStartY && startY <= gameContainerEndY) ? true : false;
,
//移动端滑动
slidMove: function (startX, startY, endX, endY)
var dx = endX - startX,
dy = endY - startY;
var deg = Math.atan2(dy, dx) * 180 / Math.PI;//反正切值求滑动角度
if (deg >= -45 && deg <= 45) //右
this.moveTile(39);
else if (deg < 135 && deg > 45) //下
this.moveTile(40);
else if ((deg >= 135 && deg <= 180) || (deg <= -135 && deg >= -180)) //左
this.moveTile(37);
else if (deg > -135 && deg < -45) //上
this.moveTile(38);
,
;
window.onload = function ()
var btn = document.getElementById("newGame"),
tileContainer = document.getElementById("tile-container"),
scoreEle = document.getElementById("game-score"),
bestScoreEle = document.getElementById("game-best-score"),
startX, startY, endX, endY;
var game = game || new Game(tileContainer, scoreEle, bestScoreEle);
game.initEvent();//初始化事件处理
game.init();//初始化游戏
EventUtil.addHandler(btn, "click", function ()
game.init();//newgame按钮被点击,初始化游戏,最佳分数保留直至刷新页面
);
//移动端触摸开始事件
EventUtil.addHandler(document, "touchstart", function (event)
event.preventDefault();
startX = event.touches[0].clientX;
startY = event.touches[0].clientY;
);
//移动端触摸滑动事件
EventUtil.addHandler(document, "touchend", function (event)
event.preventDefault();
endX = event.changedTouches[0].clientX;
endY = event.changedTouches[0].clientY;
//只有toustart的开始坐标在游戏区域gameContainer内才出发方块四个方向滑动
if (game.touchPosTest(startX, startY))
game.slidMove(startX, startY, endX, endY);
);
CSS:
*
margin: 0;
padding: 0;
.container
width: 500px;
height: 640px;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
font-family: "微软雅黑";
.header
height: 120px;
margin-bottom: 20px;
.game-title
font-size: 50px;
color: #776e65;
text-align: center;
margin-bottom: 10px;
.game-info
height: 40px;
#game-score, #game-best-score
height: 100%;
float: left;
min-width: 65px;
background-color: #bbada0;
color: #fff;
font-size: 18px;
border-radius: 5px;
text-align: center;
line-height: 58px;
position: relative;
#game-score:after
content: "Score";
position: absolute;
width: 100%;
left: 0;
top: -21px;
text-align: center;
color: #e9dfd4;
font-size: 13px;
#game-best-score
margin-right: 15px;
#game-best-score:after
content: "Best";
position: absolute;
width: 100%;
left: 0;
top: -21px;
text-align: center;
color: #e9dfd4;
font-size: 13px;
#newGame
height: 100%;
width: 100px;
float: right;
border-radius: 5px;
background-color: #8f7a66;
border: none;
box-shadow: none;
color: #fff;
font-size: 16px;
cursor: pointer;
#newGame:focus
outline: none;
.game-container
width: 500px;
height: 500px;
position: relative;
background-color: #bbada0;
padding: 15px;
border-radius: 5px;
box-sizing: border-box;
-moz-box-sizing: border-box;
/* Firefox */
-webkit-box-sizing: border-box;
/* Safari */
.gird-container
width: 470px;
height: 470px;
.gird-row
width: 470px;
height: 106.25px;
margin-bottom: 15px;
clear: both;
.gird-row:last-child
margin-bottom: 0;
.gird-col
width: 106.25px;
height: 106.25px;
margin-right: 15px;
background-color: #cdc1b4;
float: left;
.gird-col:last-child
margin-right: 0;
.tile-container
color: #f9f6f2;
width: 470px;
height: 470px;
position: absolute;
top: 15px;
.game-over
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 10;
background-color: rgba(204, 204, 204, 0.5);
.game-over:after
content: "Game Over";
font-size: 60px;
color: #fff;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
height: 70px;
margin: auto;
text-align: center;
.game-win
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 10;
background-color: rgba(204, 204, 204, 0.5);
.game-win:after
content: "You Win";
font-size: 60px;
color: #fff;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
height: 70px;
margin: auto;
text-align: center;
.game-win-again
width: 160px;
height: 50px;
border-radius: 5px;
background-color: #8f7a66;
border: none;
box-shadow: none;
color: #fff;
cursor: pointer;
position: absolute;
bottom: 120px;
left: 0;
right: 0;
margin: auto;
font-size: 30px;
.game-win-again:after
content: "Continue";
.tile
position: absolute;
width: 106.25px;
height: 106.25px;
text-align: center;
line-height: 106.25px;
font-size: 50px;
top: 0;
transition: transform 150ms ease-out;
-moz-transition: transform 150ms ease-out;
/* Firefox 4 */
-webkit-transition: transform 150ms ease-out;
/* Safari 和 Chrome */
-o-transition: transform 150ms ease-out;
/* Opera */
animation: tiledisplay 300ms 1;
-webkit-animation: tiledisplay 300ms 1;
/* Safari 和 Chrome */
@keyframes tiledisplay
0%
opacity: 0;
filter: alpha(opacity=0);
50%
opacity: 0;
filter: alpha(opacity=0);
100%
opacity: 1;
filter: alpha(opacity=100);
@-webkit-keyframes tiledisplay
/* Safari and Chrome */
0%
opacity: 0;
filter: alpha(opacity=0);
50%
opacity: 0;
filter: alpha(opacity=0);
100%
opacity: 1;
filter: alpha(opacity=100);
.tile-container .tile-2
color: #776e65;
background: #eee4da;
.tile-container .tile-4
color: #776e65;
background: #ede0c8;
.tile-container .tile-8
background: #f2b179;
.tile-container .tile-16
background: #f59563;
.tile-container .tile-32
background: #f67c5f;
.tile-container .tile-64
background: #f65e3b;
.tile-container .tile-128
background: #edcf72;
.tile-container .tile-256
background: #edcc61;
.tile-container .tile-512
background: #edc850;
.tile-container .tile-1024
background: #edc53f;
.tile-container .tile-2048
background: #edc22e;
.tile-container .tile-pos-0-0
-webkit-transform: translate(0, 0);
-ms-transform: translate(0, 0);
-o-transform: translate(0, 0);
transform: translate(0, 0);
.tile-container .tile-pos-0-1
-webkit-transform: translate(0, 121.25px);
-ms-transform: translate(0, 121.25px);
-o-transform: translate(0, 121.25px);
transform: translate(0, 121.25px);
.tile-container .tile-pos-0-2
-webkit-transform: translate(0, 242.5px);
-ms-transform: translate(0, 242.5px);
-o-transform: translate(0, 242.5px);
transform: translate(0, 242.5px);
.tile-container .tile-pos-0-3
-webkit-transform: translate(0, 363.75px);
-ms-transform: translate(0, 363.75px);
-o-transform: translate(0, 363.75px);
transform: translate(0, 363.75px);
.tile-container .tile-pos-1-0
-webkit-transform: translate(121.25px, 0);
-ms-transform: translate(121.25px, 0);
-o-transform: translate(121.25px, 0);
transform: translate(121.25px, 0);
.tile-container .tile-pos-1-1
-webkit-transform: translate(121.25px, 121.25px);
-ms-transform: translate(121.25px, 121.25px);
-o-transform: translate(121.25px, 121.25px);
transform: translate(121.25px, 121.25px);
.tile-container .tile-pos-1-2
-webkit-transform: translate(121.25px, 242.5px);
-ms-transform: translate(121.25px, 242.5px);
-o-transform: translate(121.25px, 242.5px);
transform: translate(121.25px, 242.5px);
.tile-container .tile-pos-1-3
-webkit-transform: translate(121.25px, 363.75px);
-ms-transform: translate(121.25px, 363.75px);
-o-transform: translate(121.25px, 363.75px);
transform: translate(121.25px, 363.75px);
.tile-container .tile-pos-2-0
-webkit-transform: translate(242.5px, 0);
-ms-transform: translate(242.5px, 0);
-o-transform: translate(242.5px, 0);
transform: translate(242.5px, 0);
.tile-container .tile-pos-2-1
-webkit-transform: translate(242.5px, 121.25px);
-ms-transform: translate(242.5px, 121.25px);
-o-transform: translate(242.5px, 121.25px);
transform: translate(242.5px, 121.25px);
.tile-container .tile-pos-2-2
-webkit-transform: translate(242.5px, 242.5px);
-ms-transform: translate(242.5px, 242.5px);
-o-transform: translate(242.5px, 242.5px);
transform: translate(242.5px, 242.5px);
.tile-container .tile-pos-2-3
-webkit-transform: translate(242.5px, 363.75px);
-ms-transform: translate(242.5px, 363.75px);
-o-transform: translate(242.5px, 363.75px);
transform: translate(242.5px, 363.75px);
.tile-container .tile-pos-3-0
-webkit-transform: translate(363.75px, 0);
-ms-transform: translate(363.75px, 0);
-o-transform: translate(363.75px, 0);
transform: translate(363.75px, 0);
.tile-container .tile-pos-3-1
-webkit-transform: translate(363.75px, 121.25px);
-ms-transform: translate(363.75px, 121.25px);
-o-transform: translate(363.75px, 121.25px);
transform: translate(363.75px, 121.25px);
.tile-container .tile-pos-3-2
-webkit-transform: translate(363.75px, 242.5px);
-ms-transform: translate(363.75px, 242.5px);
-o-transform: translate(363.75px, 242.5px);
transform: translate(363.75px, 242.5px);
.tile-container .tile-pos-3-3
-webkit-transform: translate(363.75px, 363.75px);
-ms-transform: translate(363.75px, 363.75px);
-o-transform: translate(363.75px, 363.75px);
transform: translate(363.75px, 363.75px);
@media screen and (max-width: 525px)
.container
width: 280px;
height: 405px;
.header
height: 110px;
margin-bottom: 15px;
.game-info
height: 40px;
.game-title
font-size: 50px;
.game-container
width: 280px;
height: 280px;
padding: 7px;
.gird-container
width: 266px;
height: 266px;
.gird-row
width: 266px;
height: 61.25px;
margin-bottom: 7px;
.gird-col
width: 61.25px;
height: 61.25px;
margin-right: 7px;
.tile-container
width: 266px;
height: 266px;
top: 7px;
.game-over:after
font-size: 40px;
height: 70px;
.game-win:after
font-size: 45px;
height: 60px;
.game-win-again
width: 130px;
height: 40px;
bottom: 60px;
font-size: 25px;
.game-win-again:after
content: "Continue";
.tile
width: 61.25px;
height: 61.25px;
line-height: 61.25px;
font-size: 35px;
.tile-container .tile-pos-0-1
-webkit-transform: translate(0, 68.25px);
-ms-transform: translate(0, 68.25px);
-o-transform: translate(0, 68.25px);
transform: translate(0, 68.25px);
.tile-container .tile-pos-0-2
-webkit-transform: translate(0, 136.5px);
-ms-transform: translate(0, 136.5px);
-o-transform: translate(0, 136.5px);
transform: translate(0, 136.5px);
.tile-container .tile-pos-0-3
-webkit-transform: translate(0, 204.75px);
-ms-transform: translate(0, 204.75px);
-o-transform: translate(0, 204.75px);
transform: translate(0, 204.75px);
.tile-container .tile-pos-1-0
-webkit-transform: translate(68.25px, 0);
-ms-transform: translate(68.25px, 0);
-o-transform: translate(68.25px, 0);
transform: translate(68.25px, 0);
.tile-container .tile-pos-1-1
-webkit-transform: translate(68.25px, 68.25px);
-ms-transform: translate(68.25px, 68.25px);
-o-transform: translate(68.25px, 68.25px);
transform: translate(68.25px, 68.25px);
.tile-container .tile-pos-1-2
-webkit-transform: translate(68.25px, 136.5px);
-ms-transform: translate(68.25px, 136.5px);
-o-transform: translate(68.25px, 136.5px);
transform: translate(68.25px, 136.5px);
.tile-container .tile-pos-1-3
-webkit-transform: translate(68.25px, 204.75px);
-ms-transform: translate(68.25px, 204.75px);
-o-transform: translate(68.25px, 204.75px);
transform: translate(68.25px, 204.75px);
.tile-container .tile-pos-2-0
-webkit-transform: translate(136.5px, 0);
-ms-transform: translate(136.5px, 0);
-o-transform: translate(136.5px, 0);
transform: translate(136.5px, 0);
.tile-container .tile-pos-2-1
-webkit-transform: translate(136.5px, 68.25px);
-ms-transform: translate(136.5px, 68.25px);
-o-transform: translate(136.5px, 68.25px);
transform: translate(136.5px, 68.25px);
.tile-container .tile-pos-2-2
-webkit-transform: translate(136.5px, 136.5px);
-ms-transform: translate(136.5px, 136.5px);
-o-transform: translate(136.5px, 136.5px);
transform: translate(136.5px, 136.5px);
.tile-container .tile-pos-2-3
-webkit-transform: translate(136.5px, 204.75px);
-ms-transform: translate(136.5px, 204.75px);
-o-transform: translate(136.5px, 204.75px);
transform: translate(136.5px, 204.75px);
.tile-container .tile-pos-3-0
-webkit-transform: translate(204.75px, 0);
-ms-transform: translate(204.75px, 0);
-o-transform: translate(204.75px, 0);
transform: translate(204.75px, 0);
.tile-container .tile-pos-3-1
-webkit-transform: translate(204.75px, 68.25px);
-ms-transform: translate(204.75px, 68.25px);
-o-transform: translate(204.75px, 68.25px);
transform: translate(204.75px, 68.25px);
.tile-container .tile-pos-3-2
-webkit-transform: translate(204.75px, 136.5px);
-ms-transform: translate(204.75px, 136.5px);
-o-transform: translate(204.75px, 136.5px);
transform: translate(204.75px, 136.5px);
.tile-container .tile-pos-3-3
-webkit-transform: translate(204.75px, 204.75px);
-ms-transform: translate(204.75px, 204.75px);
-o-transform: translate(204.75px, 204.75px);
transform: translate(204.75px, 204.75px);
以上是关于JavaScript之2048 JS css的主要内容,如果未能解决你的问题,请参考以下文章