kelompok06-2048/2048_Logic.js
Evelyn Sucitro 79a0cfc00f 2048
2025-12-01 21:17:50 +07:00

195 lines
4.5 KiB
JavaScript

/* ------------------------
5. GAME LOGIC
------------------------ */
function addNewTile() {
const empty = [];
for (let r = 0; r < 4; r++) {
for (let c = 0; c < 4; c++) {
if (board[r][c] === 0) empty.push({ r, c });
}
}
if (empty.length === 0) return false;
const spot = empty[Math.floor(Math.random() * empty.length)];
board[spot.r][spot.c] = 2;
const tile = document.getElementById(`${spot.r}-${spot.c}`);
if (tile) {
tile.classList.add("new");
playSound(audio.pop);
setTimeout(() => tile.classList.remove("new"), 300);
}
updateTile(spot.r, spot.c, 2);
return true;
}
function filterZero(row) {
return row.filter(n => n !== 0);
}
function slide(row) {
row = filterZero(row);
let mergedThisMove = false;
let mergedPositions = [];
let mergeCount = 0;
for (let i = 0; i < row.length - 1; i++) {
if (row[i] === row[i + 1]) {
row[i] = row[i] * 2;
playSound(audio.merge);
if (navigator.vibrate) {
navigator.vibrate([80, 20, 80]);
}
currentScore += row[i];
row[i + 1] = 0;
mergedThisMove = true;
mergedPositions.push(i);
mergeCount++;
}
}
row = filterZero(row);
while (row.length < 4) row.push(0);
return { row, merged: mergedThisMove, mergedPositions, mergeCount };
}
function arraysEqual(a, b) {
return a.length === b.length && a.every((v, i) => v === b[i]);
}
/* Move functions */
function moveLeft() {
let moved = false;
let mergedCells = [];
mergesInCurrentMove = 0;
for (let r = 0; r < 4; r++) {
const { row: newRow, mergedPositions, mergeCount } = slide(board[r]);
if (!arraysEqual(newRow, board[r])) moved = true;
board[r] = newRow;
mergesInCurrentMove += mergeCount;
if (mergedPositions && mergedPositions.length > 0) {
mergedPositions.forEach(c => {
mergedCells.push({ r, c });
});
}
}
if (moved) {
refreshBoard();
triggerComboEffect(mergedCells, mergesInCurrentMove);
}
return moved;
}
function moveRight() {
let moved = false;
let mergedCells = [];
mergesInCurrentMove = 0;
for (let r = 0; r < 4; r++) {
let reversed = [...board[r]].reverse();
const { row: slid, mergedPositions, mergeCount } = slide(reversed);
let newRow = slid.reverse();
if (!arraysEqual(newRow, board[r])) moved = true;
board[r] = newRow;
mergesInCurrentMove += mergeCount;
if (mergedPositions && mergedPositions.length > 0) {
mergedPositions.forEach(pos => {
const c = 3 - pos;
mergedCells.push({ r, c });
});
}
}
if (moved) {
refreshBoard();
triggerComboEffect(mergedCells, mergesInCurrentMove);
}
return moved;
}
function moveUp() {
let moved = false;
let mergedCells = [];
mergesInCurrentMove = 0;
for (let c = 0; c < 4; c++) {
const col = [board[0][c], board[1][c], board[2][c], board[3][c]];
const { row: newCol, mergedPositions, mergeCount } = slide(col);
for (let r = 0; r < 4; r++) {
if (board[r][c] !== newCol[r]) moved = true;
board[r][c] = newCol[r];
}
mergesInCurrentMove += mergeCount;
if (mergedPositions && mergedPositions.length > 0) {
mergedPositions.forEach(r => {
mergedCells.push({ r, c });
});
}
}
if (moved) {
refreshBoard();
triggerComboEffect(mergedCells, mergesInCurrentMove);
}
return moved;
}
function moveDown() {
let moved = false;
let mergedCells = [];
mergesInCurrentMove = 0;
for (let c = 0; c < 4; c++) {
const col = [board[3][c], board[2][c], board[1][c], board[0][c]];
const { row: slid, mergedPositions, mergeCount } = slide(col);
const newCol = slid.reverse();
for (let r = 0; r < 4; r++) {
if (board[r][c] !== newCol[r]) moved = true;
board[r][c] = newCol[r];
}
mergesInCurrentMove += mergeCount;
if (mergedPositions && mergedPositions.length > 0) {
mergedPositions.forEach(pos => {
const r = 3 - pos;
mergedCells.push({ r, c });
});
}
}
if (moved) {
refreshBoard();
triggerComboEffect(mergedCells, mergesInCurrentMove);
}
return moved;
}
function canMove() {
for (let r = 0; r < 4; r++) {
for (let c = 0; c < 4; c++) {
if (board[r][c] === 0) return true;
}
}
for (let r = 0; r < 4; r++) {
for (let c = 0; c < 4; c++) {
const current = board[r][c];
if (c < 3 && board[r][c + 1] === current) return true;
if (r < 3 && board[r + 1][c] === current) return true;
}
}
return false;
}