JSFiddle - React, Tailwind, and code Playground

by awesomespaceman

HTML

<div class="stage">
    <div class="grid num_0"></div>
    <div class="grid num_0"></div>
    <div class="grid num_0"></div>
    <div class="grid num_0"></div>
    <div class="grid num_0"></div>
    <div class="grid num_0"></div>
    <div class="grid num_0"></div>
    <div class="grid num_0"></div>
    <div class="grid num_0"></div>
    <div class="grid num_0"></div>
    <div class="grid num_0"></div>
    <div class="grid num_0"></div>
    <div class="grid num_0"></div>
    <div class="grid num_0"></div>
    <div class="grid num_0"></div>
    <div class="grid num_0"></div>
</div>

CSS

html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
    margin: 0;
    padding: 0;
    border: 0;
    font-size: 100%;
    font-family:sans-serif;
    vertical-align: baseline
}
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
    display: block
}
body {
    line-height: 1
}
ol, ul {
    list-style: none
}
blockquote, q {
    quotes: none
}
blockquote:before, blockquote:after, q:before, q:after {
    content:'';
    content: none
}
table {
    border-collapse: collapse;
    border-spacing: 0
}
.stage {
    width: 480px;
    height: 480px;
    padding: 10px;
    background-color: #DDD;
    border-radius: 8px;
    box-shadow: 0px 3px 0px #BBB inset
}
.stage .grid {
    display: inline-block;
    width: 110px;
    height: 110px;
    margin: 5px;
    border-radius: 5px;
    float: left;
    line-height: 110px;
    font-size: 60px;
    box-shadow: 0px 3px 0px #CCC;
    background-color: white
}
.num {
    display: block;
    width: 110px;
    height: 110px;
    border-radius: 5px;
    background: rgba(191, 207, 108, 0.3);
    text-align: center;
    line-height: 110px
}
.hidden {
    display: none
}
.bounceIn:before {
    -webkit-animation: bounceIn 1s .2s ease both;
}
@-webkit-keyframes bounceIn {
    0% {
        opacity: 0;
        -webkit-transform: scale(.3)
    }
    50% {
        opacity: 1;
        -webkit-transform: scale(1.05)
    }
    70% {
        -webkit-transform: scale(.9)
    }
    100% {
        -webkit-transform: scale(1)
    }
}
.flip:before {
    -webkit-animation: flipY 1s...

JavaScript

(function() {
	"use strict"
	var stage = document.getElementsByClassName('stage')[0];
	var movingClock = 0;
	var randomArr = [2, 2, 4]; // 生成的数字可用列表
	var moveAction = function moveAction(direction) {
		// direction: 0 向下 1 向左 2 向上 3 向右
		var moveAble = false;

		function move(indexs) {
			var clockIndex = [];
			for (var i = 1; i < indexs.length; i++) {
				var index = indexs[i];
				if (map.get(index) != 0) {
					var result = tryMerge(i, clockIndex);
					switch (result[0]) {
						case true:
							map.set(result[1], map.get(index) * 2, 'flip');
							map.set(index, 0);
							moveAble = true;
							clockIndex.push(result[1]);
							break;
						case 0:
							map.set(result[1], map.get(index));
							map.set(index, 0);
							moveAble = true;
							break;
						case false:
							break;
						default:
							break;
					}
				}
			};

			function tryMerge(i, clockIndex) {
				for (var j = i - 1; j >= 0; j--) {
					if (map.get(indexs[j]) != 0) {
						if (map.get(indexs[j]) == map.get(indexs[i]) && isInArr(clockIndex, indexs[j]) >= 0) { //值相等 但是前面的那个已经合并过
							if (j == i - 1) {
								return [false, 0];
							} else {
								return [0, indexs[j + 1]];
							}
						} else if (map.get(indexs[j]) == map.get(indexs[i])) {
							return [true, indexs[j]];
						} else if (j == i - 1) {
							return [false, 0];
						} else {
							break;
						}
					}
				}
				return [0, indexs[j + 1]]
			}
		}
		switch (direction) {
			case 0:
				for (var i = 0; i < 4; i++) {
					move([i + 12, i + 8, i + 4, i]);
				};
				break;
			case 1:
				for (var i = 0; i < 4; i++) {
					move([i * 4, i * 4 + 1, i * 4 + 2, i * 4 + 3]);
				};
				break;
			case 2:
				for (var i = 0; i < 4; i++) {
					move([i, i + 4, i + 8, i + 12]);
				};
				break;
			case 3:
				for (var i = 0; i < 4; i++) {
					move([i * 4 + 3, i * 4 + 2, i * 4 + 1, i * 4]);
				};
				break;
			default:
				break;
		}
		if (moveAble && map.check()) {
			map.randomSetBlank();
		}
	}
	var map =...