console
let el = document.querySelector('.wrap')
let data = [
['', '', '', ''],
['', '', '', ''],
['', '', '', ''],
['', '', '', '']
]
let hasAdd = false
const colorObj = {
"": "#d3d3d3",
"2": "#fef4f2",
"4": "#fed9a2",
"8": "#fc8c5e",
"16": "#f8692f",
"32": "#f8563d",
"64": "#ff3936",
"128": "#00c3dd",
"256": "#00a4be",
"512": "#00abcb",
"1024": "#00abcb",
"2048": "#00abcb",
"4096": "#005d6e"
}
function getRandomNum(min, max) {
return Math.round(min + Math.random() * (max - min))
}
function getRandomPosition() {
let arrs = []
for(let i = 0; i < 4; i++) {
for(let j = 0; j < 4; j++) {
if (!data[i][j]) arrs.push([i,j])
}
}
if (arrs.length === 0) return false
return arrs[getRandomNum(0, arrs.length)]
}
function insertNum() {
let position = getRandomPosition()
if (!position) return false
data[position[0]][position[1]] = 2
render(position)
}
function keydownHandle() {
switch(event.keyCode){
case 37:
toLeft()
break;
case 38:
toTop()
break;
case 39:
toRight()
break
case 40:
toBottom()
break;
}
insertNum()
if ([37, 38, 39, 40].includes(event.keyCode) && isEnd()) alert('游戏结束')
}
function toLeft() {
for (let row = 0; row < 4; row++) {
hasAdd = false
for(let start = 0; start < 3; start++) {
for(let col = 0; col < 3; col++) {
change([row, col], [row, col + 1])
}
}
}
}
function toTop() {
for (let col = 0; col < 4; col++) {
hasAdd = false
for(let start = 0; start < 3; start++) {
for(let row = 0; row < 3; row++) {
change([row, col], [row + 1, col])
}
}
}
}
function toRight() {
for (let row = 0; row < 4; row++) {
hasAdd = false
for(let start = 0; start < 3; start++) {
for(let col = 3; col > 0; col--) {
change([row, col], [row, col - 1])
}
}
}
}
function toBottom() {
for (let col = 0; col < 4; col++) {
hasAdd = false
for(let start = 0; start < 3; start++) {
for(let row = 3; row > 0; row--) {
change([row, col], [row - 1, col])
}
}
}
}
function change(firstPosition, secPosition) {
let firstVal = data[firstPosition[0]][firstPosition[1]]
let secVal = data[secPosition[0]][secPosition[1]]
if (!firstVal && secVal) {
data[firstPosition[0]][firstPosition[1]] = data[secPosition[0]][secPosition[1]]
data[secPosition[0]][secPosition[1]] = ''
} else if (firstVal !== '' && firstVal === secVal && !hasAdd) {
data[firstPosition[0]][firstPosition[1]] = firstVal + secVal
data[secPosition[0]][secPosition[1]] = ''
hasAdd = true
}
}
function render(position) {
let str = ''
data.forEach((item, row) => {
item.forEach((num, col) => {
let className = ''
if (row === position[0] && col === position[1]) className = 'new'
str += `<div style="background-color: ${colorObj[num]}" class="${className}">${num}</div>`
})
})
el.innerHTML = str
}
function isEnd() {
for(let row = 0; row < 4; row++) {
for(let col = 0; col < 3; col++) {
if (data[row][col] === '' || data[row][col + 1] === '') return false
if(data[row][col] === data[row][col + 1]) return false
}
}
for(let col = 0; col < 4; col++) {
for(let row = 0; row < 3; row++) {
if(data[row][col] === data[row + 1][col]) return false
}
}
return true
}
function reset() {
data = [
['', '', '', ''],
['', '', '', ''],
['', '', '', ''],
['', '', '', '']
]
insertNum()
}
insertNum()
<body onkeydown="keydownHandle()">
<button onclick="reset()">重新开始</button>
<div class="wrap">
</div>
</body>
body {
text-align: center;
}
.wrap {
background-color: #999;
padding: 5px;
display: inline-flex;
border-radius: 4px;
flex-wrap: wrap;
width: 240px;
text-align: center;
}
.wrap div {
width: 50px;
height: 50px;
text-align: center;
line-height: 50px;
background: red;
border-radius: 4px;
margin: 5px;
opacity: 1;
}
.new {
animation: newFrame 2s;
}
@keyframes newFrame{
0% {
opacity: 0.5;
}
30% {
opacity: 1;
}
60% {
opacity: 0.2;
}
100% {
opacity: 1;
}
}