Добавить 2048.html
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>2048</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body {
|
||||
background: #faf8ef;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
font-family: 'Segoe UI', sans-serif;
|
||||
}
|
||||
h1 { font-size: 3em; color: #776e65; }
|
||||
#score { font-size: 1.2em; color: #776e65; margin-bottom: 10px; }
|
||||
.board {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 85px);
|
||||
grid-template-rows: repeat(4, 85px);
|
||||
gap: 8px;
|
||||
background: #bbada0;
|
||||
padding: 8px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.cell {
|
||||
width: 85px;
|
||||
height: 85px;
|
||||
border-radius: 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.8em;
|
||||
font-weight: bold;
|
||||
color: #776e65;
|
||||
background: #cdc1b4;
|
||||
transition: all 0.15s;
|
||||
}
|
||||
.cell[data-val="2"] { background: #eee4da; }
|
||||
.cell[data-val="4"] { background: #ede0c8; }
|
||||
.cell[data-val="8"] { background: #f2b179; color: #f9f6f2; }
|
||||
.cell[data-val="16"] { background: #f59563; color: #f9f6f2; }
|
||||
.cell[data-val="32"] { background: #f67c5f; color: #f9f6f2; }
|
||||
.cell[data-val="64"] { background: #f65e3b; color: #f9f6f2; }
|
||||
.cell[data-val="128"] { background: #edcf72; color: #f9f6f2; font-size: 1.5em; }
|
||||
.cell[data-val="256"] { background: #edcc61; color: #f9f6f2; font-size: 1.5em; }
|
||||
.cell[data-val="512"] { background: #edc850; color: #f9f6f2; font-size: 1.5em; }
|
||||
.cell[data-val="1024"] { background: #edc53f; color: #f9f6f2; font-size: 1.2em; }
|
||||
.cell[data-val="2048"] { background: #edc22e; color: #f9f6f2; font-size: 1.2em; box-shadow: 0 0 30px gold; }
|
||||
#info { color: #776e65; margin-top: 15px; }
|
||||
#restart {
|
||||
margin-top: 10px;
|
||||
padding: 8px 24px;
|
||||
background: #8f7a66;
|
||||
color: #f9f6f2;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
font-size: 1em;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>2048</h1>
|
||||
<div id="score">Счёт: 0</div>
|
||||
<div class="board" id="board"></div>
|
||||
<div id="info">Стрелки / WASD для управления</div>
|
||||
<button id="restart">🔄 Заново</button>
|
||||
|
||||
<script>
|
||||
let grid, score;
|
||||
function init() {
|
||||
grid = Array(4).fill(null).map(() => Array(4).fill(0));
|
||||
score = 0;
|
||||
addRandom();
|
||||
addRandom();
|
||||
render();
|
||||
}
|
||||
function addRandom() {
|
||||
const empty = [];
|
||||
for (let r = 0; r < 4; r++) for (let c = 0; c < 4; c++) if (!grid[r][c]) empty.push([r, c]);
|
||||
if (empty.length) {
|
||||
const [r, c] = empty[Math.floor(Math.random() * empty.length)];
|
||||
grid[r][c] = Math.random() < 0.9 ? 2 : 4;
|
||||
}
|
||||
}
|
||||
function render() {
|
||||
const board = document.getElementById('board');
|
||||
board.innerHTML = '';
|
||||
for (let r = 0; r < 4; r++) {
|
||||
for (let c = 0; c < 4; c++) {
|
||||
const cell = document.createElement('div');
|
||||
cell.className = 'cell';
|
||||
if (grid[r][c]) {
|
||||
cell.textContent = grid[r][c];
|
||||
cell.dataset.val = grid[r][c];
|
||||
}
|
||||
board.appendChild(cell);
|
||||
}
|
||||
}
|
||||
document.getElementById('score').textContent = 'Счёт: ' + score;
|
||||
}
|
||||
function slide(row) {
|
||||
let arr = row.filter(v => v);
|
||||
for (let i = 0; i < arr.length - 1; i++) {
|
||||
if (arr[i] === arr[i + 1]) {
|
||||
arr[i] *= 2;
|
||||
score += arr[i];
|
||||
arr.splice(i + 1, 1);
|
||||
}
|
||||
}
|
||||
while (arr.length < 4) arr.push(0);
|
||||
return arr;
|
||||
}
|
||||
function move(dir) {
|
||||
let moved = false;
|
||||
const old = JSON.stringify(grid);
|
||||
if (dir === 'left') {
|
||||
for (let r = 0; r < 4; r++) grid[r] = slide(grid[r]);
|
||||
} else if (dir === 'right') {
|
||||
for (let r = 0; r < 4; r++) grid[r] = slide(grid[r].reverse()).reverse();
|
||||
} else if (dir === 'up') {
|
||||
for (let c = 0; c < 4; c++) {
|
||||
let col = [grid[0][c], grid[1][c], grid[2][c], grid[3][c]];
|
||||
col = slide(col);
|
||||
for (let r = 0; r < 4; r++) grid[r][c] = col[r];
|
||||
}
|
||||
} else if (dir === 'down') {
|
||||
for (let c = 0; c < 4; c++) {
|
||||
let col = [grid[0][c], grid[1][c], grid[2][c], grid[3][c]].reverse();
|
||||
col = slide(col).reverse();
|
||||
for (let r = 0; r < 4; r++) grid[r][c] = col[r];
|
||||
}
|
||||
}
|
||||
if (JSON.stringify(grid) !== old) {
|
||||
addRandom();
|
||||
render();
|
||||
if (isGameOver()) {
|
||||
setTimeout(() => alert('Игра окончена! Счёт: ' + score), 200);
|
||||
}
|
||||
}
|
||||
}
|
||||
function isGameOver() {
|
||||
for (let r = 0; r < 4; r++)
|
||||
for (let c = 0; c < 4; c++) {
|
||||
if (!grid[r][c]) return false;
|
||||
if (c < 3 && grid[r][c] === grid[r][c + 1]) return false;
|
||||
if (r < 3 && grid[r][c] === grid[r + 1][c]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
document.addEventListener('keydown', e => {
|
||||
const map = { ArrowLeft: 'left', ArrowRight: 'right', ArrowUp: 'up', ArrowDown: 'down',
|
||||
a: 'left', d: 'right', w: 'up', s: 'down' };
|
||||
if (map[e.key]) { e.preventDefault(); move(map[e.key]); }
|
||||
});
|
||||
document.getElementById('restart').onclick = init;
|
||||
|
||||
let touchStartX, touchStartY;
|
||||
document.addEventListener('touchstart', e => { touchStartX = e.touches[0].clientX; touchStartY = e.touches[0].clientY; });
|
||||
document.addEventListener('touchend', e => {
|
||||
const dx = e.changedTouches[0].clientX - touchStartX;
|
||||
const dy = e.changedTouches[0].clientY - touchStartY;
|
||||
if (Math.abs(dx) > Math.abs(dy)) {
|
||||
move(dx > 0 ? 'right' : 'left');
|
||||
} else {
|
||||
move(dy > 0 ? 'down' : 'up');
|
||||
}
|
||||
});
|
||||
init();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user