Files
HTML-Game/2048.html
T
2026-05-28 18:46:53 +03:00

176 lines
5.4 KiB
HTML

<!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>