1 //事件处理对象
2 //addHandler() 方法接受3个参数:要操作的元素、事件名称和事件处理程序函数。
3 var EventUtil = {
4 addHandler: function (element, type, handler) {
5 if (element.addEventListener) {
6 element.addEventListener(type, handler, false);
7 } else if (element.attachEvent) {
8 element.attachEvent("on" + type, handler);
9 } else {
10 element["on" + type] = handler;
11 } //处理浏览器之间的差异
12 },
13
14 //获取事件对象
15 getEvent: function (event) {
16 return event ? event : window.event; //兼容IE
17 }
18
19 }
20
21 //创建Game对象
22 function Game2048(tileCon, scoreEle, bestScoreEle) {
23 this.tileContainer = tileCon;
24 this.scoreEle = scoreEle;
25 this.bestScoreEle = bestScoreEle;
26 this.tiles = new Array(4);//创建存方块数值与dom对象的一维数组
27
28 }
29
30 Game2048.prototype = { //game的原型方法
31 init: function () { //初始化游戏
32 this.posArray = [];//创建存空白方块坐标的数组 position
33 for (let i = 0, len = this.tiles.length; i < len; i++) {
34
35 this.tiles[i] = []; //变成了二维数组
36 for (let j = 0; j < len; j++) {
37 this.tiles[i][j] = { num: 0 }; //初始化存方块数值与dom对象的数组
38 this.posArray.push({ "x": i, "y": j });
39
40 //初始化存方块坐标的数组
41 }
42 }
43 this.deleteTile(true); //清空全部方块 自定义的方法 传入true 全部clear
44 this.score = 0; //初始化分数
45 this.bestScore = this.bestScore || 0;
46 this.newTile(); //创建两个方块
47 this.newTile();
48 },
49 //创建方块函数
50 newTile: function () {
51 var tile = document.createElement("div");
52 var pos = this.randomPos(); //方块位置
53 var num = Math.random() < 0.9 ? 2 : 4; //新方块数值2或者4
54 this.tiles[pos.x][pos.y] = { num: num, tile: tile };
55 //将新房块的数字与dom对象 存入数组
56 this.setTile(tile, num, pos.x, pos.y); //设置方块属性产生移动与淡入效果
57 this.tileContainer.appendChild(tile);
58 },
59 //设置方块class和显示的数字
60 setTile: function (element, num, x, y) { //xy 是坐标位置 (x,y)让哪一个格子生成div 根据num的值渲染不同的颜色
61 element.innerHTML = num;
62 element.className = "tile tile-" + num + " tile-pos-" + x + "-" + y;
63 },//设置类名
64
65 randomPos: function () { //随机一个方块位置
66 let index = Math.floor(Math.random() * this.posArray.length);
67 // console.log(index);
68 let pos = this.posArray[index]; // posArray 存放的是16个格子的位置 随机产生一个数字即可
69 // console.log(pos);
70 this.posArray.splice(index, 1); // 产生之后就不是一个空白方块了????
71 return pos; //返回的是一个对象 里面存放的位置信息 { "x": i, "y": j }
72 },
73
74 //方块移动 core
75 moveTile: function (keyCode) {
76 let len = this.tiles.length;
77 let merge; //存合并状态 自定义函数
78 switch (keyCode) {
79 //左移
80 case 37:
81 for (let i = 1; i < len; i++) {
82 for (let j = 0; j < len; j++) {
83 if (this.tiles[i][j].num != 0 && this.leftMove(i, j)) { //遍历所有的格子不是空格子就左移
84 merge = this.merge(i, j); //合并
85 }
86 }
87 }
88 break;
89 //右移动
90 case 39:
91 for (let i = len - 2; i >= 0; i--) {
92 for (let j = 0; j < len; j++) {
93 if (this.tiles[i][j].num != 0 && this.rightMove(i, j)) {//遍历所有的格子不是空格子就right移
94 merge = this.merge(i, j);
95 }
96 }
97 }
98 break;
99 case 38: //shang yi dong
100 for (let i = 0; i < len; i++) {
101 for (let j = 1; j < len; j++) {
102 if (this.tiles[i][j].num != 0 && this.upMove(i, j)) {//遍历所有的格子不是空格子就 up
103 merge = this.merge(i, j);
104 }
105 }
106 }
107 break;
108 case 40:
109 for (let i = 0; i < len; i++) {
110 for (let j = len - 2; j >= 0; j--) {
111 if (this.tiles[i][j].num != 0 && this.downMove(i, j)) { //遍历所有的格子不是空格子就down
112
113 merge = this.merge(i, j);
114 }
115 }
116 }
117 break;
118 }
119 if (merge) { //产生了 合并事件就产生一个新的方块
120 this.newTile();//合并后创建一个新的方块
121 } else if (this.posArray.length == 0 && this.gameOverTest()) {
122 this.gameOver(); //游戏结束测试
123 }
124 },
125
126
127 leftMove: function (i, j) { //左移函数
128 this.num = this.tiles[i][j].num; //找到该格子的数字
129 this.moveI = undefined;
130 this.moveJ = undefined;
131 for (let n = i - 1; n >= 0; n--) { //一直试探到碰壁为止
132 if (this.tiles[n][j].num == 0) { //试探左边的的格子是否为空
133 this.moveI = n;
134 } else if (this.tiles[n][j].num == this.num) { //如果左边的数字相同 则合并
135 this.num *= 2;
136 this.moveI = n;
137 if (this.num == 2048) {
138 this.gameWin(); //如果有2048出现 则闯关成功
139 }
140 this.getScore(this.num); //记录分数
141 break;
142 } else {
143 break;
144 }
145 }
146 this.moveJ = j;
147 if (!(this.moveI + 1) || !(this.moveJ + 1)) { //undefined + 1 = NaN;
148 return; //没有产生移动 直接进入的else break循环
149 }
150 return true;
151 },
152
153
154 rightMove: function (i, j) { //与左移同理
155 let len = this.tiles.length;
156 this.num = this.tiles[i][j].num;
157 this.moveI = undefined;
158 this.moveJ = undefined;
159 for (let n = i + 1; n < len; n++) {
160 if (this.tiles[n][j].num == 0) {
161 this.moveI = n;
162 } else if (this.tiles[n][j].num == this.num) {
163 this.num *= 2;
164 this.moveI = n;
165 if (this.num == 2048) {
166 this.gameWin();
167 }
168 this.getScore(this.num);
169 break;
170 } else {
171 break;
172 }
173 }
174 this.moveJ = j;
175 if (!(this.moveI + 1) || !(this.moveJ + 1)) {
176 return;
177 }
178 return true;
179 },
180
181
182 upMove: function (i, j) { //与左移同理
183
184 this.num = this.tiles[i][j].num;
185 this.moveI = undefined;
186 this.moveJ = undefined;
187 for (let n = j - 1; n >= 0; n--) {
188 if (this.tiles[i][n].num == 0) {
189 this.moveJ = n;
190 } else if (this.tiles[i][n].num == this.num) {
191 this.moveJ = n;
192 this.num *= 2;
193 if (this.num == 2048) {
194 this.gameWin(); //同理
195 }
196 this.getScore(this.num);
197 break;
198 }
199 }
200 this.moveI = i;
201 if (!(this.moveI + 1) || !(this.moveJ + 1)) {
202 return;
203 }
204 return true;
205 },
206
207 downMove: function (i, j) { //与左移同理
208 let len = this.tiles.length;
209 this.num = this.tiles[i][j].num;
210 this.moveI = undefined;
211 this.moveJ = undefined;
212 for (let n = j + 1; n < len; n++) {
213 if (this.tiles[i][n].num == 0) {
214 this.moveJ = n;
215 } else if (this.tiles[i][n].num == this.num) {
216 this.moveJ = n;
217 this.num *= 2;
218 if (this.num == 2048) {
219 this.gameWin(); //同理
220 }
221 this.getScore(this.num);
222 break;
223 }
224 }
225 this.moveI = i;
226 if (!(this.moveI + 1) || !(this.moveJ + 1)) {
227 return;
228 }
229 return true;
230 },
231
232 //合并方块
233 merge: function (i, j) {
234 let me = this; //记录this指向
235 if (this.num > this.tiles[i][j].num) {
236 //this.num的值变化,即遇到相同值的方块,可移动到其位置,只需删除被覆盖的方块
237 this.deleteTile(false, this.tiles[this.moveI][this.moveJ].tile);
238 this.posArray.push({ x: i, y: j });
239 } else if (this.num == this.tiles[i][j].num) {
240 this.posArray.forEach(function (item) { // binali
241 if (item.x == me.moveI && item.y == me.moveJ) {
242 item.x = i;
243 item.y = j;
244 }
245 });
246 }
247 //设置将移动的方块的属性,产生移动效果
248 this.setTile(this.tiles[i][j].tile, this.num, this.moveI, this.moveJ);
249 //在存方块数值与dom对象的数组中将移动的方块的值设为空白值(即num:0),被覆盖的方块的值设为将移动的方块的值
250 this.tiles[this.moveI][this.moveJ] = { num: this.num, tile: this.tiles[i][j].tile };
251 this.tiles[i][j] = { num: 0 };
252 return true;
253 },
254
255
256 //删除方块节点
257 deleteTile: function (all, tile) {
258 if (all) {
259 this.tileContainer.innerHTML = ""; //clear;
260 } else {
261 this.tileContainer.removeChild(tile);//删除单个方块
262 }
263 },
264
265
266 //计算得分
267 getScore: function (score) {
268 this.score += score;
269 this.scoreEle.innerHTML = this.score;
270 if (this.score > this.bestScore) {
271 this.bestScore = this.score // 分数超过时 , 就刷新 最高记录
272 this.bestScoreEle.innerHTML = this.bestScore;
273 }
274 },
275
276 //出现2048 gameOver 也可以继续挑战
277 gameWin: function () {
278 let me = this;
279 let win = document.createElement("div");
280 let continueBtn = document.createElement("button");
281 continueBtn.className = "game-win-again";
282 win.className = "game-win";
283 win.appendChild(continueBtn);
284 this.tileContainer.appendChild(win);
285 EventUtil.addHandler(continueBtn, "click", function () {
286 me.deleteTile(false, win);
287 });
288 },
289
290 // 没有方向移动 gameOver
291 //test
292 gameOverTest: function () {
293 let len = this.tiles.length;
294 for (let i = 0; i < len; i++) {
295 for (let j = 0; j < len; j++) {
296 if (this.leftMove(i, j) || this.rightMove(i, j) || this.upMove(i, j) || this.downMove(i, j)) {
297 return; //任意方向 可以移动就继续游戏
298 }
299 }
300 }
301 return true;
302 },
303
304 //游戏结束 消息
305 gameOver: function () {
306 let message = document.createElement("div");
307 message.className = "game-over";
308 this.tileContainer.appendChild(message);
309 },
310
311
312 //添加事件处理程序????
313 initEvent: function () {
314 let me = this;
315 console.log(this); //指向了game2048 对象 ;
316 //限制键盘一直重复触发
317 EventUtil.addHandler(window, "keyup", function (event) {
318 me.moveTile(EventUtil.getEvent(event).keyCode);
319 })
320 },
321
322 }
323
324
325 window.onload = function () {
326 let btn = document.getElementById("newGame");
327 let tileContainer = document.getElementById("tile-container");
328 let scoreEle = document.getElementById("game-score");
329 let bestScoreEle = document.getElementById("game-best-score");
330 var startX, startY, endX, endY;
331 var game = game || new Game2048(tileContainer, scoreEle, bestScoreEle);
332 //创建Game对象 传入game需要的参数
333
334 game.initEvent();//初始化事件处理???
335 game.init(); //初始化游戏
336
337 EventUtil.addHandler(btn, "click", function () {
338 game.init();
339 //点击newgame 初始化游戏
340 });
341 }
上面是js部分
1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0"> 7 <link rel="stylesheet" type="text/css" href="style.css"> 8 <title>2048</title> 9 </head> 10 11 <body> 12 <div class="container" id="container"> 13 <div class="header"> 14 <h1 class="game-title">2048</h1> 15 <div class="game-info"> 16 <span id="game-best-score">0</span> 17 <span id="game-score">0</span> 18 <button id="newGame" type="button">New Game</button> 19 </div> 20 </div> 21 <div class="game-container" id="game-container"> 22 <div class="game-result"> 23 <p></p> 24 </div> 25 <div class="gird-container"> 26 <div class="gird-row"> 27 <div class="gird-col"></div> 28 <div class="gird-col"></div> 29 <div class="gird-col"></div> 30 <div class="gird-col"></div> 31 </div> 32 <div class="gird-row"> 33 <div class="gird-col"></div> 34 <div class="gird-col"></div> 35 <div class="gird-col"></div> 36 <div class="gird-col"></div> 37 </div> 38 <div class="gird-row"> 39 <div class="gird-col"></div> 40 <div class="gird-col"></div> 41 <div class="gird-col"></div> 42 <div class="gird-col"></div> 43 </div> 44 <div class="gird-row"> 45 <div class="gird-col"></div> 46 <div class="gird-col"></div> 47 <div class="gird-col"></div> 48 <div class="gird-col"></div> 49 </div> 50 </div> 51 <div class="tile-container" id="tile-container"></div> 52 </div> 53 </div> 54 <!-- <script type="text/javascript" src="main.js"></script> --> 55 <script type="text/javascript" src="Game2048.js"></script> 56 </body> 57 58 </html>
HTML部分
1 * {
2 margin: 0;
3 padding: 0;
4 }
5
6 .container {
7 width: 500px;
8 height: 640px;
9 position: absolute;
10 top: 0;
11 left: 0;
12 right: 0;
13 bottom: 0;
14 margin: auto;
15 font-family: "微软雅黑";
16 }
17
18 .header {
19 height: 120px;
20 margin-bottom: 20px;
21 }
22
23 .game-title {
24 font-size: 50px;
25 color: #776e65;
26 text-align: center;
27 margin-bottom: 10px;
28 }
29
30 .game-info {
31 height: 40px;
32 }
33
34 #game-score, #game-best-score {
35 height: 100%;
36 float: left;
37 min-width: 65px;
38 background-color: #bbada0;
39 color: #fff;
40 font-size: 18px;
41 border-radius: 5px;
42 text-align: center;
43 line-height: 58px;
44 position: relative;
45 }
46
47 #game-score:after {
48 content: "Score";
49 position: absolute;
50 width: 100%;
51 left: 0;
52 top: -21px;
53 text-align: center;
54 color: #e9dfd4;
55 font-size: 13px;
56 }
57
58 #game-best-score {
59 margin-right: 15px;
60 }
61
62 #game-best-score:after {
63 content: "Best";
64 position: absolute;
65 width: 100%;
66 left: 0;
67 top: -21px;
68 text-align: center;
69 color: #e9dfd4;
70 font-size: 13px;
71 }
72
73 #newGame {
74 height: 100%;
75 width: 100px;
76 float: right;
77 border-radius: 5px;
78 background-color: #8f7a66;
79 border: none;
80 box-shadow: none;
81 color: #fff;
82 font-size: 16px;
83 cursor: pointer;
84 }
85
86 #newGame:focus {
87 outline: none;
88 }
89
90 .game-container {
91 width: 500px;
92 height: 500px;
93 position: relative;
94 background-color: #bbada0;
95 padding: 15px;
96 border-radius: 5px;
97 box-sizing: border-box;
98 -moz-box-sizing: border-box;
99 /* Firefox */
100 -webkit-box-sizing: border-box;
101 /* Safari */
102 }
103
104 .gird-container {
105 width: 470px;
106 height: 470px;
107 }
108
109 .gird-row {
110 width: 470px;
111 height: 106.25px;
112 margin-bottom: 15px;
113 clear: both;
114 }
115
116 .gird-row:last-child {
117 margin-bottom: 0;
118 }
119
120 .gird-col {
121 width: 106.25px;
122 height: 106.25px;
123 margin-right: 15px;
124 background-color: #cdc1b4;
125 float: left;
126 }
127
128 .gird-col:last-child {
129 margin-right: 0;
130 }
131
132 .tile-container {
133 color: #f9f6f2;
134 width: 470px;
135 height: 470px;
136 position: absolute;
137 top: 15px;
138 }
139
140 .game-over {
141 position: absolute;
142 top: 0;
143 bottom: 0;
144 left: 0;
145 right: 0;
146 z-index: 10;
147 background-color: rgba(204, 204, 204, 0.5);
148 }
149
150 .game-over:after {
151 content: "Game Over";
152 font-size: 60px;
153 color: #fff;
154 position: absolute;
155 top: 0;
156 bottom: 0;
157 left: 0;
158 right: 0;
159 height: 70px;
160 margin: auto;
161 text-align: center;
162 }
163
164 .game-win {
165 position: absolute;
166 top: 0;
167 bottom: 0;
168 left: 0;
169 right: 0;
170 z-index: 10;
171 background-color: rgba(204, 204, 204, 0.5);
172 }
173
174 .game-win:after {
175 content: "You Win";
176 font-size: 60px;
177 color: #fff;
178 position: absolute;
179 top: 0;
180 bottom: 0;
181 left: 0;
182 right: 0;
183 height: 70px;
184 margin: auto;
185 text-align: center;
186 }
187
188 .game-win-again {
189 width: 160px;
190 height: 50px;
191 border-radius: 5px;
192 background-color: #8f7a66;
193 border: none;
194 box-shadow: none;
195 color: #fff;
196 cursor: pointer;
197 position: absolute;
198 bottom: 120px;
199 left: 0;
200 right: 0;
201 margin: auto;
202 font-size: 30px;
203 }
204
205 .game-win-again:after {
206 content: "Continue";
207 }
208
209 .tile {
210 position: absolute;
211 width: 106.25px;
212 height: 106.25px;
213 text-align: center;
214 line-height: 106.25px;
215 font-size: 50px;
216 top: 0;
217 transition: transform 150ms ease-out;
218 -moz-transition: transform 150ms ease-out;
219 /* Firefox 4 */
220 -webkit-transition: transform 150ms ease-out;
221 /* Safari 和 Chrome */
222 -o-transition: transform 150ms ease-out;
223 /* Opera */
224 animation: tiledisplay 300ms 1;
225 -webkit-animation: tiledisplay 300ms 1;
226 /* Safari 和 Chrome */
227 }
228
229 @keyframes tiledisplay {
230 0% {
231 opacity: 0;
232 filter: alpha(opacity=0);
233 }
234 50% {
235 opacity: 0;
236 filter: alpha(opacity=0);
237 }
238 100% {
239 opacity: 1;
240 filter: alpha(opacity=100);
241 }
242 }
243
244 @-webkit-keyframes tiledisplay
245 /* Safari and Chrome */
246
247 {
248 0% {
249 opacity: 0;
250 filter: alpha(opacity=0);
251 }
252 50% {
253 opacity: 0;
254 filter: alpha(opacity=0);
255 }
256 100% {
257 opacity: 1;
258 filter: alpha(opacity=100);
259 }
260 }
261
262 .tile-container .tile-2 {
263 color: #776e65;
264 background: #eee4da;
265 }
266
267 .tile-container .tile-4 {
268 color: #776e65;
269 background: #ede0c8;
270 }
271
272 .tile-container .tile-8 {
273 background: #f2b179;
274 }
275
276 .tile-container .tile-16 {
277 background: #f59563;
278 }
279
280 .tile-container .tile-32 {
281 background: #f67c5f;
282 }
283
284 .tile-container .tile-64 {
285 background: #f65e3b;
286 }
287
288 .tile-container .tile-128 {
289 background: #edcf72;
290 }
291
292 .tile-container .tile-256 {
293 background: #edcc61;
294 }
295
296 .tile-container .tile-512 {
297 background: #edc850;
298 }
299
300 .tile-container .tile-1024 {
301 background: #edc53f;
302 }
303
304 .tile-container .tile-2048 {
305 background: #edc22e;
306 }
307
308 .tile-container .tile-pos-0-0 {
309 -webkit-transform: translate(0, 0);
310 -ms-transform: translate(0, 0);
311 -o-transform: translate(0, 0);
312 transform: translate(0, 0);
313 }
314
315 .tile-container .tile-pos-0-1 {
316 -webkit-transform: translate(0, 121.25px);
317 -ms-transform: translate(0, 121.25px);
318 -o-transform: translate(0, 121.25px);
319 transform: translate(0, 121.25px);
320 }
321
322 .tile-container .tile-pos-0-2 {
323 -webkit-transform: translate(0, 242.5px);
324 -ms-transform: translate(0, 242.5px);
325 -o-transform: translate(0, 242.5px);
326 transform: translate(0, 242.5px);
327 }
328
329 .tile-container .tile-pos-0-3 {
330 -webkit-transform: translate(0, 363.75px);
331 -ms-transform: translate(0, 363.75px);
332 -o-transform: translate(0, 363.75px);
333 transform: translate(0, 363.75px);
334 }
335
336 .tile-container .tile-pos-1-0 {
337 -webkit-transform: translate(121.25px, 0);
338 -ms-transform: translate(121.25px, 0);
339 -o-transform: translate(121.25px, 0);
340 transform: translate(121.25px, 0);
341 }
342
343 .tile-container .tile-pos-1-1 {
344 -webkit-transform: translate(121.25px, 121.25px);
345 -ms-transform: translate(121.25px, 121.25px);
346 -o-transform: translate(121.25px, 121.25px);
347 transform: translate(121.25px, 121.25px);
348 }
349
350 .tile-container .tile-pos-1-2 {
351 -webkit-transform: translate(121.25px, 242.5px);
352 -ms-transform: translate(121.25px, 242.5px);
353 -o-transform: translate(121.25px, 242.5px);
354 transform: translate(121.25px, 242.5px);
355 }
356
357 .tile-container .tile-pos-1-3 {
358 -webkit-transform: translate(121.25px, 363.75px);
359 -ms-transform: translate(121.25px, 363.75px);
360 -o-transform: translate(121.25px, 363.75px);
361 transform: translate(121.25px, 363.75px);
362 }
363
364 .tile-container .tile-pos-2-0 {
365 -webkit-transform: translate(242.5px, 0);
366 -ms-transform: translate(242.5px, 0);
367 -o-transform: translate(242.5px, 0);
368 transform: translate(242.5px, 0);
369 }
370
371 .tile-container .tile-pos-2-1 {
372 -webkit-transform: translate(242.5px, 121.25px);
373 -ms-transform: translate(242.5px, 121.25px);
374 -o-transform: translate(242.5px, 121.25px);
375 transform: translate(242.5px, 121.25px);
376 }
377
378 .tile-container .tile-pos-2-2 {
379 -webkit-transform: translate(242.5px, 242.5px);
380 -ms-transform: translate(242.5px, 242.5px);
381 -o-transform: translate(242.5px, 242.5px);
382 transform: translate(242.5px, 242.5px);
383 }
384
385 .tile-container .tile-pos-2-3 {
386 -webkit-transform: translate(242.5px, 363.75px);
387 -ms-transform: translate(242.5px, 363.75px);
388 -o-transform: translate(242.5px, 363.75px);
389 transform: translate(242.5px, 363.75px);
390 }
391
392 .tile-container .tile-pos-3-0 {
393 -webkit-transform: translate(363.75px, 0);
394 -ms-transform: translate(363.75px, 0);
395 -o-transform: translate(363.75px, 0);
396 transform: translate(363.75px, 0);
397 }
398
399 .tile-container .tile-pos-3-1 {
400 -webkit-transform: translate(363.75px, 121.25px);
401 -ms-transform: translate(363.75px, 121.25px);
402 -o-transform: translate(363.75px, 121.25px);
403 transform: translate(363.75px, 121.25px);
404 }
405
406 .tile-container .tile-pos-3-2 {
407 -webkit-transform: translate(363.75px, 242.5px);
408 -ms-transform: translate(363.75px, 242.5px);
409 -o-transform: translate(363.75px, 242.5px);
410 transform: translate(363.75px, 242.5px);
411 }
412
413 .tile-container .tile-pos-3-3 {
414 -webkit-transform: translate(363.75px, 363.75px);
415 -ms-transform: translate(363.75px, 363.75px);
416 -o-transform: translate(363.75px, 363.75px);
417 transform: translate(363.75px, 363.75px);
418 }
419
420 @media screen and (max-width: 525px) {
421 .container {
422 width: 280px;
423 height: 405px;
424 }
425 .header {
426 height: 110px;
427 margin-bottom: 15px;
428 }
429 .game-info {
430 height: 40px;
431 }
432 .game-title {
433 font-size: 50px;
434 }
435 .game-container {
436 width: 280px;
437 height: 280px;
438 padding: 7px;
439 }
440 .gird-container {
441 width: 266px;
442 height: 266px;
443 }
444 .gird-row {
445 width: 266px;
446 height: 61.25px;
447 margin-bottom: 7px;
448 }
449 .gird-col {
450 width: 61.25px;
451 height: 61.25px;
452 margin-right: 7px;
453 }
454 .tile-container {
455 width: 266px;
456 height: 266px;
457 top: 7px;
458 }
459 .game-over:after {
460 font-size: 40px;
461 height: 70px;
462 }
463 .game-win:after {
464 font-size: 45px;
465 height: 60px;
466 }
467 .game-win-again {
468 width: 130px;
469 height: 40px;
470 bottom: 60px;
471 font-size: 25px;
472 }
473 .game-win-again:after {
474 content: "Continue";
475 }
476 .tile {
477 width: 61.25px;
478 height: 61.25px;
479 line-height: 61.25px;
480 font-size: 35px;
481 }
482 .tile-container .tile-pos-0-1 {
483 -webkit-transform: translate(0, 68.25px);
484 -ms-transform: translate(0, 68.25px);
485 -o-transform: translate(0, 68.25px);
486 transform: translate(0, 68.25px);
487 }
488 .tile-container .tile-pos-0-2 {
489 -webkit-transform: translate(0, 136.5px);
490 -ms-transform: translate(0, 136.5px);
491 -o-transform: translate(0, 136.5px);
492 transform: translate(0, 136.5px);
493 }
494 .tile-container .tile-pos-0-3 {
495 -webkit-transform: translate(0, 204.75px);
496 -ms-transform: translate(0, 204.75px);
497 -o-transform: translate(0, 204.75px);
498 transform: translate(0, 204.75px);
499 }
500 .tile-container .tile-pos-1-0 {
501 -webkit-transform: translate(68.25px, 0);
502 -ms-transform: translate(68.25px, 0);
503 -o-transform: translate(68.25px, 0);
504 transform: translate(68.25px, 0);
505 }
506 .tile-container .tile-pos-1-1 {
507 -webkit-transform: translate(68.25px, 68.25px);
508 -ms-transform: translate(68.25px, 68.25px);
509 -o-transform: translate(68.25px, 68.25px);
510 transform: translate(68.25px, 68.25px);
511 }
512 .tile-container .tile-pos-1-2 {
513 -webkit-transform: translate(68.25px, 136.5px);
514 -ms-transform: translate(68.25px, 136.5px);
515 -o-transform: translate(68.25px, 136.5px);
516 transform: translate(68.25px, 136.5px);
517 }
518 .tile-container .tile-pos-1-3 {
519 -webkit-transform: translate(68.25px, 204.75px);
520 -ms-transform: translate(68.25px, 204.75px);
521 -o-transform: translate(68.25px, 204.75px);
522 transform: translate(68.25px, 204.75px);
523 }
524 .tile-container .tile-pos-2-0 {
525 -webkit-transform: translate(136.5px, 0);
526 -ms-transform: translate(136.5px, 0);
527 -o-transform: translate(136.5px, 0);
528 transform: translate(136.5px, 0);
529 }
530 .tile-container .tile-pos-2-1 {
531 -webkit-transform: translate(136.5px, 68.25px);
532 -ms-transform: translate(136.5px, 68.25px);
533 -o-transform: translate(136.5px, 68.25px);
534 transform: translate(136.5px, 68.25px);
535 }
536 .tile-container .tile-pos-2-2 {
537 -webkit-transform: translate(136.5px, 136.5px);
538 -ms-transform: translate(136.5px, 136.5px);
539 -o-transform: translate(136.5px, 136.5px);
540 transform: translate(136.5px, 136.5px);
541 }
542 .tile-container .tile-pos-2-3 {
543 -webkit-transform: translate(136.5px, 204.75px);
544 -ms-transform: translate(136.5px, 204.75px);
545 -o-transform: translate(136.5px, 204.75px);
546 transform: translate(136.5px, 204.75px);
547 }
548 .tile-container .tile-pos-3-0 {
549 -webkit-transform: translate(204.75px, 0);
550 -ms-transform: translate(204.75px, 0);
551 -o-transform: translate(204.75px, 0);
552 transform: translate(204.75px, 0);
553 }
554 .tile-container .tile-pos-3-1 {
555 -webkit-transform: translate(204.75px, 68.25px);
556 -ms-transform: translate(204.75px, 68.25px);
557 -o-transform: translate(204.75px, 68.25px);
558 transform: translate(204.75px, 68.25px);
559 }
560 .tile-container .tile-pos-3-2 {
561 -webkit-transform: translate(204.75px, 136.5px);
562 -ms-transform: translate(204.75px, 136.5px);
563 -o-transform: translate(204.75px, 136.5px);
564 transform: translate(204.75px, 136.5px);
565 }
566 .tile-container .tile-pos-3-3 {
567 -webkit-transform: translate(204.75px, 204.75px);
568 -ms-transform: translate(204.75px, 204.75px);
569 -o-transform: translate(204.75px, 204.75px);
570 transform: translate(204.75px, 204.75px);
571 }
572 }