From 88eaaccc2e3810c590dfca74530ff1904c58efe3 Mon Sep 17 00:00:00 2001 From: Iryna Mariiko Date: Wed, 6 Nov 2024 21:25:44 +0200 Subject: [PATCH 01/14] moveLeft, right, up, down done --- .github/workflows/test.yml-template | 29 +++++ README.md | 2 +- package-lock.json | 9 +- package.json | 2 +- src/modules/Game.class.js | 186 ++++++++++++++++++++++++++-- src/styles/main.scss | 6 +- 6 files changed, 218 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/test.yml-template diff --git a/.github/workflows/test.yml-template b/.github/workflows/test.yml-template new file mode 100644 index 000000000..44ac4e963 --- /dev/null +++ b/.github/workflows/test.yml-template @@ -0,0 +1,29 @@ +name: Test + +on: + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [20.x] + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - run: npm install + - run: npm start & sleep 5 && npm test + - name: Upload tests report(cypress mochaawesome merged HTML report) + if: ${{ always() }} + uses: actions/upload-artifact@v2 + with: + name: report + path: reports diff --git a/README.md b/README.md index 5aab92544..0d692a183 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ You can change the HTML/CSS layout if you need it. ## Deploy and Pull Request 1. Replace `` with your Github username in the link - - [DEMO LINK](https://.github.io/js_2048_game/) + - [DEMO LINK](https://IrynaMariiko00.github.io/js_2048_game/) 2. Follow [this instructions](https://mate-academy.github.io/layout_task-guideline/) - Run `npm run test` command to test your code; - Run `npm run test:only -- -n` to run fast test ignoring linter; diff --git a/package-lock.json b/package-lock.json index f209cb6e0..ff37dc85b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "@mate-academy/eslint-config": "latest", "@mate-academy/jest-mochawesome-reporter": "^1.0.0", "@mate-academy/linthtml-config": "latest", - "@mate-academy/scripts": "^1.8.5", + "@mate-academy/scripts": "^1.9.12", "@mate-academy/stylelint-config": "latest", "@parcel/transformer-sass": "^2.12.0", "cypress": "^13.13.0", @@ -1467,10 +1467,11 @@ "dev": true }, "node_modules/@mate-academy/scripts": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@mate-academy/scripts/-/scripts-1.8.5.tgz", - "integrity": "sha512-mHRY2FkuoYCf5U0ahIukkaRo5LSZsxrTSgMJheFoyf3VXsTvfM9OfWcZIDIDB521kdPrScHHnRp+JRNjCfUO5A==", + "version": "1.9.12", + "resolved": "https://registry.npmjs.org/@mate-academy/scripts/-/scripts-1.9.12.tgz", + "integrity": "sha512-/OcmxMa34lYLFlGx7Ig926W1U1qjrnXbjFJ2TzUcDaLmED+A5se652NcWwGOidXRuMAOYLPU2jNYBEkKyXrFJA==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/rest": "^17.11.2", "@types/get-port": "^4.2.0", diff --git a/package.json b/package.json index 0335978ca..05abe81e0 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "@mate-academy/eslint-config": "latest", "@mate-academy/jest-mochawesome-reporter": "^1.0.0", "@mate-academy/linthtml-config": "latest", - "@mate-academy/scripts": "^1.8.5", + "@mate-academy/scripts": "^1.9.12", "@mate-academy/stylelint-config": "latest", "@parcel/transformer-sass": "^2.12.0", "cypress": "^13.13.0", diff --git a/src/modules/Game.class.js b/src/modules/Game.class.js index 65cd219c9..a7fa68949 100644 --- a/src/modules/Game.class.js +++ b/src/modules/Game.class.js @@ -5,6 +5,11 @@ * Now it has a basic structure, that is needed for testing. * Feel free to add more props and methods if needed. */ +const IDLE = 'idle'; +const PLAYING = 'playing'; +// const WIN = 'win'; +// const LOSE = 'lose'; + class Game { /** * Creates a new game instance. @@ -21,14 +26,182 @@ class Game { * initial state. */ constructor(initialState) { - // eslint-disable-next-line no-console - console.log(initialState); + this.board = initialState || [ + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + ]; + + this.score = 0; + + this.status = IDLE; + } + + addRandomTitle() { + const emptyCells = []; + + for (let row = 0; row < 4; row++) { + for (let col = 0; col < 4; col++) { + if (this.board[row][col] === 0) { + emptyCells.push({ row, col }); + } + } + } + + if (emptyCells.length > 0) { + const { row, col } = + emptyCells[Math.floor(Math.random() * emptyCells.length)]; + + this.board[row][col] = 2; + } + } + + createColumn(col) { + const newColumn = []; + + for (let row = 0; row < this.board.length; row++) { + if (this.board[row][col] !== 0) { + newColumn.push(this.board[row][col]); + } + } + + return newColumn; + } + + updateColumn(col, newColumn) { + let moved = false; + + for (let row = 0; row < this.board.length; row++) { + if (this.board[row][col] !== newColumn[row]) { + this.board[row][col] = newColumn[row]; + moved = true; + } + } + + return moved; + } + + resetGameStart() { + this.score = 0; + this.status = PLAYING; + + this.board = [ + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + ]; + + this.addRandomTitle(); + this.addRandomTitle(); + } + + moveLeft() { + let moved = false; + + for (let row = 0; row < this.board.length; row++) { + const currentRow = this.board[row]; + const newRow = currentRow.filter((val) => val !== 0); + const canMerge = new Array(newRow.length).fill(true); + + for (let i = 0; i < newRow.length - 1; i++) { + if (newRow[i] === newRow[i + 1]) { + newRow[i] *= 2; + newRow.splice(i + 1, 1); + moved = true; + canMerge[i] = false; + } + } + + while (newRow.length < currentRow.length) { + newRow.push(0); + } + + this.board[row] = newRow; + } + + return moved; + } + + moveRight() { + let moved = false; + + for (let row = this.board.length - 1; row >= 0; row--) { + const currentRow = this.board[row]; + const newRow = currentRow.filter((val) => val !== 0); + const canMerge = new Array(newRow.length).fill(true); + + for (let i = newRow.length - 1; i > 0; i--) { + if (newRow[i] === newRow[i - 1]) { + newRow[i] *= 2; + newRow.splice(i - 1, 1); + moved = true; + canMerge[i] = false; + } + } + + while (newRow.length < currentRow.length) { + newRow.unshift(0); + } + + this.board[row] = newRow; + } + + return moved; + } + + moveUp() { + let moved = false; + + for (let col = 0; col < this.board.length; col++) { + const newColumn = this.createColumn(col); + const canMerge = new Array(newColumn.length).fill(true); + + for (let i = 0; i < newColumn.length - 1; i++) { + if (newColumn[i] === newColumn[i + 1]) { + newColumn[i] *= 2; + newColumn.splice(i + 1, 1); + moved = true; + canMerge[i] = false; + } + } + + while (newColumn.length < this.board.length) { + newColumn.push(0); + } + + moved = this.updateColumn(col, newColumn) || moved; + } + + return moved; } - moveLeft() {} - moveRight() {} - moveUp() {} - moveDown() {} + moveDown() { + let moved = false; + + for (let col = 0; col < this.board.length; col++) { + const newColumn = this.createColumn(col); + const canMerge = new Array(newColumn.length).fill(true); + + for (let i = newColumn.length - 1; i > 0; i--) { + if (newColumn[i] === newColumn[i - 1]) { + newColumn[i] *= 2; + newColumn.splice(i - 1, 1); + moved = true; + canMerge[i] = false; + } + } + + while (newColumn.length < this.board.length) { + newColumn.unshift(0); + } + + moved = this.updateColumn(col, newColumn) || moved; + } + + return moved; + } /** * @returns {number} @@ -39,7 +212,6 @@ class Game { * @returns {number[][]} */ getState() {} - /** * Returns the current game status. * diff --git a/src/styles/main.scss b/src/styles/main.scss index c43f37dcf..8e10eb4d5 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -91,7 +91,7 @@ body { } h1 { - background: #edc22e; + background: #3a6ed6; color: #f9f6f2; width: 75px; height: 75px; @@ -138,11 +138,11 @@ h1 { } .start { - background: #1dae28; + background: #0aca6d; font-size: 20px; &:hover { - background: #179921; + background: #10b96a;; } } From 39b89dad81ef2447c506dc87d95258a7004af4eb Mon Sep 17 00:00:00 2001 From: Iryna Mariiko Date: Thu, 7 Nov 2024 22:21:27 +0200 Subject: [PATCH 02/14] started adding event Listener --- src/index.html | 2 +- src/modules/Game.class.js | 199 ++++++++++++++++++++++++++++++++------ src/scripts/main.js | 19 +++- src/styles/main.scss | 14 ++- 4 files changed, 195 insertions(+), 39 deletions(-) diff --git a/src/index.html b/src/index.html index aff3d1a98..5139d5aa2 100644 --- a/src/index.html +++ b/src/index.html @@ -65,6 +65,6 @@

2048

- + diff --git a/src/modules/Game.class.js b/src/modules/Game.class.js index a7fa68949..99f1d5ffe 100644 --- a/src/modules/Game.class.js +++ b/src/modules/Game.class.js @@ -7,8 +7,8 @@ */ const IDLE = 'idle'; const PLAYING = 'playing'; -// const WIN = 'win'; -// const LOSE = 'lose'; +const WIN = 'win'; +const LOSE = 'lose'; class Game { /** @@ -36,9 +36,35 @@ class Game { this.score = 0; this.status = IDLE; + this.isStarted = false; } - addRandomTitle() { + updateBoard() { + const cells = document.querySelectorAll('.field-cell'); + // всі клітинки дошки + + let cellIndex = 0; + + for (let row = 0; row < this.board.length; row++) { + for (let col = 0; col < this.board[row].length; col++) { + const cell = cells[cellIndex++]; + const value = this.board[row][col]; + + if (value === 0) { + const previousValue = cell.textContent; + + cell.classList.remove(`field-cell--${previousValue}`); + cell.textContent = ''; + } else { + cell.classList.remove(`field-cell--${value / 2}`); + cell.classList.add(`field-cell--${value}`); + cell.textContent = value; // оновлюємо текст + } + } + } + } + + addRandomTile() { const emptyCells = []; for (let row = 0; row < 4; row++) { @@ -53,7 +79,30 @@ class Game { const { row, col } = emptyCells[Math.floor(Math.random() * emptyCells.length)]; - this.board[row][col] = 2; + if (this.score === 0) { + this.board[row][col] = 2; // Додаємо плитку 2 лише один раз на старті + } + this.updateBoard(); // оновлюємо DOM після додавання плитки + } + } + + addRandomCellAfterMoving() { + const emptyCells = []; + + for (let row = 0; row < 4; row++) { + for (let col = 0; col < 4; col++) { + if (this.board[row][col] === 0) { + emptyCells.push({ row, col }); + } + } + } + + if (emptyCells.length > 0) { + const { row, col } = + emptyCells[Math.floor(Math.random() * emptyCells.length)]; + + this.board[row][col] = Math.random() < 0.9 ? 2 : 4; + this.updateBoard(); // оновлюємо DOM після додавання плитки } } @@ -93,8 +142,23 @@ class Game { [0, 0, 0, 0], ]; - this.addRandomTitle(); - this.addRandomTitle(); + this.addRandomTile(); + this.addRandomTile(); + } + + mergeTitles(newRow, canMerge) { + const mergedThisMove = []; // масив для відслідковування злитих плиток + + for (let i = 0; i < newRow.length - 1; i++) { + if (newRow[i] === newRow[i + 1]) { + newRow[i] *= 2; + newRow.splice(i + 1, 1); + canMerge[i] = false; // вказуємо, що плитка вже злилася + mergedThisMove.push(i); // зберігаємо індекс злитої плитки + } + } + + return mergedThisMove; } moveLeft() { @@ -104,14 +168,17 @@ class Game { const currentRow = this.board[row]; const newRow = currentRow.filter((val) => val !== 0); const canMerge = new Array(newRow.length).fill(true); + // [true, true, і тд] - for (let i = 0; i < newRow.length - 1; i++) { - if (newRow[i] === newRow[i + 1]) { - newRow[i] *= 2; - newRow.splice(i + 1, 1); - moved = true; - canMerge[i] = false; - } + const mergedThisMove = this.mergeTitles(newRow, canMerge); + // виконується злиття клітинок та передається масив в + // якому є індекси злитих клітинок + + if ( + mergedThisMove.length > 0 || + newRow.length !== currentRow.filter((val) => val !== 0).length + ) { + moved = true; } while (newRow.length < currentRow.length) { @@ -119,6 +186,15 @@ class Game { } this.board[row] = newRow; + + // Оновлюємо рахунок, передаючи індекси злитих плиток + for (let i = 0; i < mergedThisMove.length; i++) { + this.getScore(moved, this.board[mergedThisMove[i]]); + } + } + + if (moved) { + this.addRandomCellAfterMoving(); } return moved; @@ -132,13 +208,13 @@ class Game { const newRow = currentRow.filter((val) => val !== 0); const canMerge = new Array(newRow.length).fill(true); - for (let i = newRow.length - 1; i > 0; i--) { - if (newRow[i] === newRow[i - 1]) { - newRow[i] *= 2; - newRow.splice(i - 1, 1); - moved = true; - canMerge[i] = false; - } + const mergedThisMove = this.mergeTitles(newRow, canMerge); + + if ( + mergedThisMove.length > 0 || + newRow.length !== currentRow.filter((val) => val !== 0).length + ) { + moved = true; } while (newRow.length < currentRow.length) { @@ -146,6 +222,14 @@ class Game { } this.board[row] = newRow; + + for (let i = 0; i < mergedThisMove.length; i++) { + this.getScore(moved, this.board[mergedThisMove[i]]); + } + } + + if (moved) { + this.addRandomCellAfterMoving(); } return moved; @@ -159,11 +243,16 @@ class Game { const canMerge = new Array(newColumn.length).fill(true); for (let i = 0; i < newColumn.length - 1; i++) { - if (newColumn[i] === newColumn[i + 1]) { + if ( + newColumn[i] === newColumn[i + 1] && + canMerge[i] && + canMerge[i + 1] + ) { newColumn[i] *= 2; newColumn.splice(i + 1, 1); moved = true; canMerge[i] = false; + this.getScore(moved, newColumn[i]); } } @@ -174,6 +263,10 @@ class Game { moved = this.updateColumn(col, newColumn) || moved; } + if (moved) { + this.addRandomCellAfterMoving(); + } + return moved; } @@ -185,11 +278,16 @@ class Game { const canMerge = new Array(newColumn.length).fill(true); for (let i = newColumn.length - 1; i > 0; i--) { - if (newColumn[i] === newColumn[i - 1]) { + if ( + newColumn[i] === newColumn[i - 1] && + canMerge[i] && + canMerge[i - 1] + ) { newColumn[i] *= 2; newColumn.splice(i - 1, 1); moved = true; canMerge[i] = false; + this.getScore(moved, newColumn[i]); } } @@ -200,18 +298,24 @@ class Game { moved = this.updateColumn(col, newColumn) || moved; } + if (moved) { + this.addRandomCellAfterMoving(); + } + return moved; } - /** - * @returns {number} - */ - getScore() {} - + getScore(moved, value) { + if (moved && value > 0) { + this.score += value; // додаємо значення плитки до рахунку + } + } /** * @returns {number[][]} */ - getState() {} + getState() { + return this.board; + } /** * Returns the current game status. * @@ -222,17 +326,50 @@ class Game { * `win` - the game is won; * `lose` - the game is lost */ - getStatus() {} + getStatus() { + if (this.score === 0) { + this.status = IDLE; + } else { + let hasEmptyCell = false; + let has2048Cell = false; + + for (let row = 0; row < this.board.length; row++) { + for (let col = 0; col < this.board[row].length; col++) { + if (this.board[row][col] === 0) { + hasEmptyCell = true; + } + + if (this.board[row][col] === 2048) { + has2048Cell = true; + } + } + } + + if (has2048Cell) { + this.status = WIN; + } else if (hasEmptyCell) { + this.status = PLAYING; + } else { + this.status = LOSE; + } + } + + return this.status; + } /** * Starts the game. */ - start() {} + start() { + this.resetGameStart(); + } /** * Resets the game. */ - restart() {} + restart() { + this.resetGameStart(); + } // Add your own methods here } diff --git a/src/scripts/main.js b/src/scripts/main.js index dc7f045a3..4815b1821 100644 --- a/src/scripts/main.js +++ b/src/scripts/main.js @@ -1,7 +1,20 @@ 'use strict'; // Uncomment the next lines to use your game instance in the browser -// const Game = require('../modules/Game.class'); -// const game = new Game(); +const Game = require('../modules/Game.class'); +const game = new Game(); -// Write your code here +const startButton = document.querySelector('.start'); +const cells = document.querySelectorAll('.field-cell'); + +startButton.addEventListener('click', (e) => { + startButton.textContent = 'Restart'; + startButton.classList.remove('start'); + startButton.classList.add('restart'); + + cells.forEach((cell) => { + cell.classList.remove('hidden'); + }); + + game.start(); +}); diff --git a/src/styles/main.scss b/src/styles/main.scss index 8e10eb4d5..f1e8504ce 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -18,9 +18,14 @@ body { color: #776e65; box-sizing: border-box; text-align: center; - vertical-align: center; + vertical-align: middle; /* змінено на 'middle' замість 'center' */ user-select: none; + position: relative; /* забезпечує правильне відображення фону */ +/* Це для порожніх клітинок */ +.field-cell:empty { + background: #d6cdc4; /* фон клітинки */ +} &--2 { background: #eee4da; } @@ -142,18 +147,19 @@ h1 { font-size: 20px; &:hover { - background: #10b96a;; + background: #10b96a; } } .restart { - background: #f1b2b2; + background: #eb5b7d; &:hover { - background: #f87474; + background: #d45271;; } } + .message { box-sizing: border-box; width: 100%; From c6125ac9c90455b3f35760b87e39c977704b1c5d Mon Sep 17 00:00:00 2001 From: Iryna Mariiko Date: Sat, 9 Nov 2024 18:12:54 +0200 Subject: [PATCH 03/14] almost done --- src/modules/Game.class.js | 116 ++++++++++++++++++++++++-------------- src/scripts/main.js | 20 +++++++ 2 files changed, 95 insertions(+), 41 deletions(-) diff --git a/src/modules/Game.class.js b/src/modules/Game.class.js index 99f1d5ffe..d066a1467 100644 --- a/src/modules/Game.class.js +++ b/src/modules/Game.class.js @@ -49,14 +49,13 @@ class Game { for (let col = 0; col < this.board[row].length; col++) { const cell = cells[cellIndex++]; const value = this.board[row][col]; + const previousValue = cell.textContent; - if (value === 0) { - const previousValue = cell.textContent; + cell.classList.remove(`field-cell--${previousValue}`); - cell.classList.remove(`field-cell--${previousValue}`); + if (value === 0) { cell.textContent = ''; } else { - cell.classList.remove(`field-cell--${value / 2}`); cell.classList.add(`field-cell--${value}`); cell.textContent = value; // оновлюємо текст } @@ -165,73 +164,106 @@ class Game { let moved = false; for (let row = 0; row < this.board.length; row++) { - const currentRow = this.board[row]; - const newRow = currentRow.filter((val) => val !== 0); - const canMerge = new Array(newRow.length).fill(true); - // [true, true, і тд] - - const mergedThisMove = this.mergeTitles(newRow, canMerge); - // виконується злиття клітинок та передається масив в - // якому є індекси злитих клітинок - - if ( - mergedThisMove.length > 0 || - newRow.length !== currentRow.filter((val) => val !== 0).length - ) { - moved = true; - } + const currentRow = this.board[row].filter((val) => val !== 0); + // Відфільтровуємо нулі для зміщення плиток вліво + const mergedRow = []; + + let skip = false; + + for (let i = 0; i < currentRow.length; i++) { + if (skip) { + skip = false; + continue; + } - while (newRow.length < currentRow.length) { - newRow.push(0); + // Якщо плитки однакові, зливаємо їх + if (currentRow[i] === currentRow[i + 1]) { + mergedRow.push(currentRow[i] * 2); + this.getScore(true, currentRow[i] * 2); // Оновлюємо рахунок за злиття + skip = true; + moved = true; + } else { + mergedRow.push(currentRow[i]); + } } - this.board[row] = newRow; + // Заповнюємо ряд до повної довжини, додаючи нулі + while (mergedRow.length < this.board[row].length) { + mergedRow.push(0); + } - // Оновлюємо рахунок, передаючи індекси злитих плиток - for (let i = 0; i < mergedThisMove.length; i++) { - this.getScore(moved, this.board[mergedThisMove[i]]); + // Перевіряємо, чи відбулася зміна в ряду + if (!moved) { + for (let i = 0; i < this.board[row].length; i++) { + if (this.board[row][i] !== mergedRow[i]) { + moved = true; + break; + } + } } + + this.board[row] = mergedRow; // Оновлюємо ряд } if (moved) { this.addRandomCellAfterMoving(); } + this.updateBoard(); + return moved; } moveRight() { let moved = false; - for (let row = this.board.length - 1; row >= 0; row--) { - const currentRow = this.board[row]; - const newRow = currentRow.filter((val) => val !== 0); - const canMerge = new Array(newRow.length).fill(true); + for (let row = 0; row < this.board.length; row++) { + // Фільтруємо нулі й залишаємо лише ненульові значення + const currentRow = this.board[row].filter((val) => val !== 0); - const mergedThisMove = this.mergeTitles(newRow, canMerge); + const mergedRow = []; + let skip = false; - if ( - mergedThisMove.length > 0 || - newRow.length !== currentRow.filter((val) => val !== 0).length - ) { - moved = true; - } + // Зливаємо плитки, якщо вони однакові + for (let i = 0; i < currentRow.length; i++) { + if (skip) { + skip = false; + continue; + } - while (newRow.length < currentRow.length) { - newRow.unshift(0); + if (currentRow[i] === currentRow[i + 1]) { + mergedRow.push(currentRow[i] * 2); // Зливаємо плитки + this.getScore(true, currentRow[i] * 2); // Оновлюємо рахунок + skip = true; // Пропускаємо наступну плитку + moved = true; + } else { + mergedRow.push(currentRow[i]); + } } - this.board[row] = newRow; + // Додаємо нулі на початок для вирівнювання ряду вправо + while (mergedRow.length < this.board[row].length) { + mergedRow.unshift(0); + } - for (let i = 0; i < mergedThisMove.length; i++) { - this.getScore(moved, this.board[mergedThisMove[i]]); + // Перевіряємо, чи відбулись зміни в ряду + for (let i = 0; i < this.board[row].length; i++) { + if (this.board[row][i] !== mergedRow[i]) { + moved = true; + break; + } } + + // Оновлюємо ряд у дошці без додаткового реверсу + this.board[row] = mergedRow; } if (moved) { this.addRandomCellAfterMoving(); } + this.updateBoard(); + return moved; } @@ -266,6 +298,7 @@ class Game { if (moved) { this.addRandomCellAfterMoving(); } + this.updateBoard(); return moved; } @@ -301,6 +334,7 @@ class Game { if (moved) { this.addRandomCellAfterMoving(); } + this.updateBoard(); return moved; } diff --git a/src/scripts/main.js b/src/scripts/main.js index 4815b1821..ceb598978 100644 --- a/src/scripts/main.js +++ b/src/scripts/main.js @@ -18,3 +18,23 @@ startButton.addEventListener('click', (e) => { game.start(); }); + +document.addEventListener('keydown', (e) => { + switch (e.key) { + case 'ArrowLeft': + game.moveLeft(); + break; + + case 'ArrowRight': + game.moveRight(); + break; + + case 'ArrowUp': + game.moveUp(); + break; + + case 'ArrowDown': + game.moveDown(); + break; + } +}); From ad4151e61860e7d4d62bed48938191c8e46948d6 Mon Sep 17 00:00:00 2001 From: Iryna Mariiko Date: Mon, 11 Nov 2024 19:36:12 +0200 Subject: [PATCH 04/14] Done --- src/index.html | 4 ++ src/modules/Game.class.js | 80 +++++++++++++++++++++++++-------- src/scripts/main.js | 69 ++++++++++++++++++++++++++--- src/styles/main.scss | 93 +++++++++++++++++++++++++++++++++------ 4 files changed, 208 insertions(+), 38 deletions(-) diff --git a/src/index.html b/src/index.html index 5139d5aa2..f91a066cd 100644 --- a/src/index.html +++ b/src/index.html @@ -17,6 +17,10 @@

2048

+

+ Best: + 0 +

Score: 0 diff --git a/src/modules/Game.class.js b/src/modules/Game.class.js index d066a1467..f2f3d7cec 100644 --- a/src/modules/Game.class.js +++ b/src/modules/Game.class.js @@ -7,10 +7,11 @@ */ const IDLE = 'idle'; const PLAYING = 'playing'; -const WIN = 'win'; -const LOSE = 'lose'; -class Game { +export const WIN = 'win'; +export const LOSE = 'lose'; + +export class Game { /** * Creates a new game instance. * @@ -25,7 +26,7 @@ class Game { * If passed, the board will be initialized with the provided * initial state. */ - constructor(initialState) { + constructor(initialState, winCallback, loseCallback) { this.board = initialState || [ [0, 0, 0, 0], [0, 0, 0, 0], @@ -37,6 +38,36 @@ class Game { this.status = IDLE; this.isStarted = false; + this.winCallback = winCallback; + this.loseCallback = loseCallback; + } + + moveTile(fromCell, toCell) { + // Отримуємо координати клітинок + const fromCellRect = fromCell.getBoundingClientRect(); + const toCellRect = toCell.getBoundingClientRect(); + + // Вираховуємо зміщення + const xOffset = toCellRect.left - fromCellRect.left; + const yOffset = toCellRect.top - fromCellRect.top; + + // Встановлюємо зміщення через CSS перемінні + fromCell.style.setProperty('--x-offset', `${xOffset}px`); + fromCell.style.setProperty('--y-offset', `${yOffset}px`); + + // Додаємо клас для запуску анімації + fromCell.classList.add('moving'); + + // Затримка для застосування анімації збільшення + setTimeout(() => { + // Додаємо клас 'merged' для анімації збільшення + toCell.classList.add('merged'); + + // Затримка для видалення класу 'merged' після завершення анімації + setTimeout(() => { + toCell.classList.remove('merged'); + }, 300); // Час анімації (300ms) + }, 120); // Затримка до початку анімації } updateBoard() { @@ -207,10 +238,10 @@ class Game { if (moved) { this.addRandomCellAfterMoving(); + this.updateBoard(); + this.getStatus(); } - this.updateBoard(); - return moved; } @@ -260,10 +291,10 @@ class Game { if (moved) { this.addRandomCellAfterMoving(); + this.updateBoard(); + this.getStatus(); } - this.updateBoard(); - return moved; } @@ -297,8 +328,9 @@ class Game { if (moved) { this.addRandomCellAfterMoving(); + this.updateBoard(); + this.getStatus(); } - this.updateBoard(); return moved; } @@ -333,17 +365,13 @@ class Game { if (moved) { this.addRandomCellAfterMoving(); + this.updateBoard(); + this.getStatus(); } - this.updateBoard(); return moved; } - getScore(moved, value) { - if (moved && value > 0) { - this.score += value; // додаємо значення плитки до рахунку - } - } /** * @returns {number[][]} */ @@ -366,6 +394,7 @@ class Game { } else { let hasEmptyCell = false; let has2048Cell = false; + let canMove = false; // Змінна для перевірки наявності можливих ходів for (let row = 0; row < this.board.length; row++) { for (let col = 0; col < this.board[row].length; col++) { @@ -376,15 +405,32 @@ class Game { if (this.board[row][col] === 2048) { has2048Cell = true; } + + // Перевірка на можливість злиття + if ( + row < this.board.length - 1 && + this.board[row][col] === this.board[row + 1][col] + ) { + canMove = true; // Якщо клітинки злиті по вертикалі + } + + if ( + col < this.board[row].length - 1 && + this.board[row][col] === this.board[row][col + 1] + ) { + canMove = true; // Якщо клітинки злиті по горизонталі + } } } if (has2048Cell) { this.status = WIN; - } else if (hasEmptyCell) { + this.winCallback(); + } else if (hasEmptyCell || canMove) { this.status = PLAYING; } else { this.status = LOSE; + this.loseCallback(); } } @@ -407,5 +453,3 @@ class Game { // Add your own methods here } - -module.exports = Game; diff --git a/src/scripts/main.js b/src/scripts/main.js index ceb598978..ec01b0aab 100644 --- a/src/scripts/main.js +++ b/src/scripts/main.js @@ -1,13 +1,65 @@ 'use strict'; -// Uncomment the next lines to use your game instance in the browser -const Game = require('../modules/Game.class'); -const game = new Game(); +// Ініціалізація гри +import { WIN, LOSE, Game } from '../modules/Game.class'; + +const game = new Game(null, showWinMessage, showLoseMessage); const startButton = document.querySelector('.start'); const cells = document.querySelectorAll('.field-cell'); +const score = document.querySelector('.game-score'); +const recordElement = document.querySelector('.best__score'); +const messageContainer = document.querySelector('.message-container'); + +function showWinMessage() { + messageContainer.classList.remove('hidden'); + messageContainer.classList.add('message-win'); + messageContainer.textContent = 'You Win!'; +} + +function showLoseMessage() { + messageContainer.classList.remove('hidden'); + messageContainer.classList.add('message-lose'); + messageContainer.textContent = 'You Lose!'; +} + +function hideMessage() { + messageContainer.classList.add('hidden'); +} + +function updateScore(value) { + score.textContent = value; +} + +function saveScore(sscore) { + const currentRecord = localStorage.getItem('highScore'); + + if (!currentRecord || sscore > currentRecord) { + localStorage.setItem('highScore', sscore); + displayRecord(); // Оновлюємо рекорд на екрані + } +} + +// Функція для відображення рекорду +function displayRecord() { + const highScore = localStorage.getItem('highScore') || 0; -startButton.addEventListener('click', (e) => { + recordElement.textContent = highScore; +} + +displayRecord(); + +// Оновлення рекорду, коли він збільшується +game.getScore = function (moved, value) { + if (moved && value > 0) { + this.score += value; // Додаємо до поточного рахунку + updateScore(this.score); // Оновлюємо відображення рахунку + saveScore(this.score); // Перевіряємо, чи це новий рекорд, і зберігаємо його + } +}; + +// Обробка натискання на кнопку старту +startButton.addEventListener('click', () => { startButton.textContent = 'Restart'; startButton.classList.remove('start'); startButton.classList.add('restart'); @@ -16,23 +68,26 @@ startButton.addEventListener('click', (e) => { cell.classList.remove('hidden'); }); + if (game.status === WIN || game.status === LOSE) { + hideMessage(); + } + game.start(); + displayRecord(); // Відображаємо рекорд при старті гри }); +// Обробка натискання клавіш document.addEventListener('keydown', (e) => { switch (e.key) { case 'ArrowLeft': game.moveLeft(); break; - case 'ArrowRight': game.moveRight(); break; - case 'ArrowUp': game.moveUp(); break; - case 'ArrowDown': game.moveDown(); break; diff --git a/src/styles/main.scss b/src/styles/main.scss index f1e8504ce..1a8f4de6f 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -31,51 +31,51 @@ body { } &--4 { - background: #ede0c8; + background: #e1d5c7; } &--8 { - background: #f2b179; + background: #5cb3bb; color: #f9f6f2; } &--16 { - background: #f59563; + background: #469299; color: #f9f6f2; } &--32 { - background: #f67c5f; + background: #349569; color: #f9f6f2; } &--64 { - background: #f65e3b; + background: #30ac64; color: #f9f6f2; } &--128 { - background: #edcf72; + background: #26b84d; color: #f9f6f2; } &--256 { - background: #edcc61; - color: #f9f6f2; + background: #0b7476; + color: #fbfbfb; } &--512 { - background: #edc850; + background: #5b8fd9; color: #f9f6f2; } &--1024 { - background: #edc53f; + background: #3b75c6; color: #f9f6f2; } &--2048 { - background: #edc22e; + background: #3b49c6; color: #f9f6f2; } } @@ -109,6 +109,21 @@ h1 { margin: 0; } +.best { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + background: #d6cdc4; + width: 75px; + height: 75px; + border-radius: 5px; + color: #776e65; + box-sizing: border-box; + font-size: 16px; + margin: 0 8px 0 0; +} + .info { display: flex; flex-direction: column; @@ -155,7 +170,7 @@ h1 { background: #eb5b7d; &:hover { - background: #d45271;; + background: #d45271; } } @@ -183,11 +198,63 @@ h1 { } .message-win { - background: #edc22e; + background: #2669b5; + color: #f9f6f2; +} + +.message-lose { + width: 100%; + box-sizing: border-box; + height: 50px !important; + padding: 10px; + background: #bf687c; color: #f9f6f2; + text-align: center; + border-radius: 5px; + font-size: 20px; } .message-container { width: 100%; height: 150px; } + +.field-cell { + transition: transform 0.2s ease, background-color 0.2s ease; + position: relative; +} + +.moving { + animation: moveTile 0.5s forwards; +} + +@keyframes moveTile { + from { + transform: translate(var(--x-offset), var(--y-offset)); + } + to { + transform: translate(0, 0); + } +} + +.field-cell--merged { + animation: mergeTile 0.2s ease; +} + +@keyframes mergeTile { + 0% { + transform: scale(1); + opacity: 1; + box-shadow: 0 0 0 rgba(0, 0, 0, 0); + } + 50% { + transform: scale(1.2); + opacity: 0.7; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); + } + 100% { + transform: scale(1); + opacity: 1; + box-shadow: 0 0 0 rgba(0, 0, 0, 0); + } +} From 835cb82c92c8179f3916e7cf55d5c229b233c2f9 Mon Sep 17 00:00:00 2001 From: Iryna Mariiko Date: Mon, 11 Nov 2024 19:36:42 +0200 Subject: [PATCH 05/14] DONE --- src/styles/main.scss | 138 ++++++++++++++++++------------------------- 1 file changed, 57 insertions(+), 81 deletions(-) diff --git a/src/styles/main.scss b/src/styles/main.scss index 1a8f4de6f..c0cf92e31 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -18,66 +18,67 @@ body { color: #776e65; box-sizing: border-box; text-align: center; - vertical-align: middle; /* змінено на 'middle' замість 'center' */ + vertical-align: middle; user-select: none; - position: relative; /* забезпечує правильне відображення фону */ + position: relative; + transition: transform 0.2s ease, background-color 0.2s ease; +} -/* Це для порожніх клітинок */ .field-cell:empty { - background: #d6cdc4; /* фон клітинки */ + background: #d6cdc4; } - &--2 { - background: #eee4da; - } - &--4 { - background: #e1d5c7; - } +.field-cell--2 { + background: #eee4da; +} - &--8 { - background: #5cb3bb; - color: #f9f6f2; - } +.field-cell--4 { + background: #e1d5c7; +} - &--16 { - background: #469299; - color: #f9f6f2; - } +.field-cell--8 { + background: #5cb3bb; + color: #f9f6f2; +} - &--32 { - background: #349569; - color: #f9f6f2; - } +.field-cell--16 { + background: #469299; + color: #f9f6f2; +} - &--64 { - background: #30ac64; - color: #f9f6f2; - } +.field-cell--32 { + background: #349569; + color: #f9f6f2; +} - &--128 { - background: #26b84d; - color: #f9f6f2; - } +.field-cell--64 { + background: #30ac64; + color: #f9f6f2; +} - &--256 { - background: #0b7476; - color: #fbfbfb; - } +.field-cell--128 { + background: #26b84d; + color: #f9f6f2; +} - &--512 { - background: #5b8fd9; - color: #f9f6f2; - } +.field-cell--256 { + background: #0b7476; + color: #fbfbfb; +} - &--1024 { - background: #3b75c6; - color: #f9f6f2; - } +.field-cell--512 { + background: #5b8fd9; + color: #f9f6f2; +} - &--2048 { - background: #3b49c6; - color: #f9f6f2; - } +.field-cell--1024 { + background: #3b75c6; + color: #f9f6f2; +} + +.field-cell--2048 { + background: #3b49c6; + color: #f9f6f2; } .game-field { @@ -109,21 +110,7 @@ h1 { margin: 0; } -.best { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - background: #d6cdc4; - width: 75px; - height: 75px; - border-radius: 5px; - color: #776e65; - box-sizing: border-box; - font-size: 16px; - margin: 0 8px 0 0; -} - +.best, .info { display: flex; flex-direction: column; @@ -153,7 +140,6 @@ h1 { font-size: 16px; width: 75px; height: 75px; - transition: 0.25s ease background; } @@ -174,7 +160,6 @@ h1 { } } - .message { box-sizing: border-box; width: 100%; @@ -219,29 +204,16 @@ h1 { height: 150px; } -.field-cell { - transition: transform 0.2s ease, background-color 0.2s ease; - position: relative; -} - .moving { - animation: moveTile 0.5s forwards; + animation: move-tile 0.5s forwards; } -@keyframes moveTile { - from { - transform: translate(var(--x-offset), var(--y-offset)); - } - to { - transform: translate(0, 0); - } -} - -.field-cell--merged { - animation: mergeTile 0.2s ease; +@keyframes move-tile { + from { transform: translate(var(--x-offset), var(--y-offset)); } + to { transform: translate(0, 0); } } -@keyframes mergeTile { +@keyframes merge-tile { 0% { transform: scale(1); opacity: 1; @@ -258,3 +230,7 @@ h1 { box-shadow: 0 0 0 rgba(0, 0, 0, 0); } } + +.field-cell--merged { + animation: merge-tile 0.2s ease; +} From 195f7571474f7bda632d840dd32fde63949d5499 Mon Sep 17 00:00:00 2001 From: Iryna Mariiko Date: Mon, 11 Nov 2024 19:49:20 +0200 Subject: [PATCH 06/14] add favicon --- src/images/Untitled.png | Bin 0 -> 4033 bytes src/index.html | 2 ++ 2 files changed, 2 insertions(+) create mode 100644 src/images/Untitled.png diff --git a/src/images/Untitled.png b/src/images/Untitled.png new file mode 100644 index 0000000000000000000000000000000000000000..448d52e275fe1c47a4a42a95b14e6896249078ca GIT binary patch literal 4033 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 literal 0 HcmV?d00001 diff --git a/src/index.html b/src/index.html index f91a066cd..8469f09c6 100644 --- a/src/index.html +++ b/src/index.html @@ -7,6 +7,8 @@ content="width=device-width, initial-scale=1.0" /> 2048 + Date: Mon, 11 Nov 2024 22:50:06 +0200 Subject: [PATCH 07/14] Solution --- src/modules/Game.class.js | 94 +++++++-------------------------------- src/scripts/main.js | 16 +++---- src/styles/main.scss | 7 ++- 3 files changed, 27 insertions(+), 90 deletions(-) diff --git a/src/modules/Game.class.js b/src/modules/Game.class.js index f2f3d7cec..1dbcf9e14 100644 --- a/src/modules/Game.class.js +++ b/src/modules/Game.class.js @@ -1,10 +1,5 @@ 'use strict'; -/** - * This class represents the game. - * Now it has a basic structure, that is needed for testing. - * Feel free to add more props and methods if needed. - */ const IDLE = 'idle'; const PLAYING = 'playing'; @@ -12,20 +7,6 @@ export const WIN = 'win'; export const LOSE = 'lose'; export class Game { - /** - * Creates a new game instance. - * - * @param {number[][]} initialState - * The initial state of the board. - * @default - * [[0, 0, 0, 0], - * [0, 0, 0, 0], - * [0, 0, 0, 0], - * [0, 0, 0, 0]] - * - * If passed, the board will be initialized with the provided - * initial state. - */ constructor(initialState, winCallback, loseCallback) { this.board = initialState || [ [0, 0, 0, 0], @@ -43,36 +24,20 @@ export class Game { } moveTile(fromCell, toCell) { - // Отримуємо координати клітинок const fromCellRect = fromCell.getBoundingClientRect(); const toCellRect = toCell.getBoundingClientRect(); - // Вираховуємо зміщення const xOffset = toCellRect.left - fromCellRect.left; const yOffset = toCellRect.top - fromCellRect.top; - // Встановлюємо зміщення через CSS перемінні fromCell.style.setProperty('--x-offset', `${xOffset}px`); fromCell.style.setProperty('--y-offset', `${yOffset}px`); - // Додаємо клас для запуску анімації fromCell.classList.add('moving'); - - // Затримка для застосування анімації збільшення - setTimeout(() => { - // Додаємо клас 'merged' для анімації збільшення - toCell.classList.add('merged'); - - // Затримка для видалення класу 'merged' після завершення анімації - setTimeout(() => { - toCell.classList.remove('merged'); - }, 300); // Час анімації (300ms) - }, 120); // Затримка до початку анімації } updateBoard() { const cells = document.querySelectorAll('.field-cell'); - // всі клітинки дошки let cellIndex = 0; @@ -88,7 +53,7 @@ export class Game { cell.textContent = ''; } else { cell.classList.add(`field-cell--${value}`); - cell.textContent = value; // оновлюємо текст + cell.textContent = value; } } } @@ -110,9 +75,9 @@ export class Game { emptyCells[Math.floor(Math.random() * emptyCells.length)]; if (this.score === 0) { - this.board[row][col] = 2; // Додаємо плитку 2 лише один раз на старті + this.board[row][col] = 2; } - this.updateBoard(); // оновлюємо DOM після додавання плитки + this.updateBoard(); } } @@ -132,7 +97,7 @@ export class Game { emptyCells[Math.floor(Math.random() * emptyCells.length)]; this.board[row][col] = Math.random() < 0.9 ? 2 : 4; - this.updateBoard(); // оновлюємо DOM після додавання плитки + this.updateBoard(); } } @@ -177,14 +142,14 @@ export class Game { } mergeTitles(newRow, canMerge) { - const mergedThisMove = []; // масив для відслідковування злитих плиток + const mergedThisMove = []; for (let i = 0; i < newRow.length - 1; i++) { if (newRow[i] === newRow[i + 1]) { newRow[i] *= 2; newRow.splice(i + 1, 1); - canMerge[i] = false; // вказуємо, що плитка вже злилася - mergedThisMove.push(i); // зберігаємо індекс злитої плитки + canMerge[i] = false; + mergedThisMove.push(i); } } @@ -196,7 +161,6 @@ export class Game { for (let row = 0; row < this.board.length; row++) { const currentRow = this.board[row].filter((val) => val !== 0); - // Відфільтровуємо нулі для зміщення плиток вліво const mergedRow = []; let skip = false; @@ -207,10 +171,9 @@ export class Game { continue; } - // Якщо плитки однакові, зливаємо їх if (currentRow[i] === currentRow[i + 1]) { mergedRow.push(currentRow[i] * 2); - this.getScore(true, currentRow[i] * 2); // Оновлюємо рахунок за злиття + this.getScore(true, currentRow[i] * 2); skip = true; moved = true; } else { @@ -218,12 +181,10 @@ export class Game { } } - // Заповнюємо ряд до повної довжини, додаючи нулі while (mergedRow.length < this.board[row].length) { mergedRow.push(0); } - // Перевіряємо, чи відбулася зміна в ряду if (!moved) { for (let i = 0; i < this.board[row].length; i++) { if (this.board[row][i] !== mergedRow[i]) { @@ -233,7 +194,7 @@ export class Game { } } - this.board[row] = mergedRow; // Оновлюємо ряд + this.board[row] = mergedRow; } if (moved) { @@ -249,13 +210,11 @@ export class Game { let moved = false; for (let row = 0; row < this.board.length; row++) { - // Фільтруємо нулі й залишаємо лише ненульові значення const currentRow = this.board[row].filter((val) => val !== 0); const mergedRow = []; let skip = false; - // Зливаємо плитки, якщо вони однакові for (let i = 0; i < currentRow.length; i++) { if (skip) { skip = false; @@ -263,21 +222,19 @@ export class Game { } if (currentRow[i] === currentRow[i + 1]) { - mergedRow.push(currentRow[i] * 2); // Зливаємо плитки - this.getScore(true, currentRow[i] * 2); // Оновлюємо рахунок - skip = true; // Пропускаємо наступну плитку + mergedRow.push(currentRow[i] * 2); + this.getScore(true, currentRow[i] * 2); + skip = true; moved = true; } else { mergedRow.push(currentRow[i]); } } - // Додаємо нулі на початок для вирівнювання ряду вправо while (mergedRow.length < this.board[row].length) { mergedRow.unshift(0); } - // Перевіряємо, чи відбулись зміни в ряду for (let i = 0; i < this.board[row].length; i++) { if (this.board[row][i] !== mergedRow[i]) { moved = true; @@ -285,7 +242,6 @@ export class Game { } } - // Оновлюємо ряд у дошці без додаткового реверсу this.board[row] = mergedRow; } @@ -378,23 +334,14 @@ export class Game { getState() { return this.board; } - /** - * Returns the current game status. - * - * @returns {string} One of: 'idle', 'playing', 'win', 'lose' - * - * `idle` - the game has not started yet (the initial state); - * `playing` - the game is in progress; - * `win` - the game is won; - * `lose` - the game is lost - */ + getStatus() { if (this.score === 0) { this.status = IDLE; } else { let hasEmptyCell = false; let has2048Cell = false; - let canMove = false; // Змінна для перевірки наявності можливих ходів + let canMove = false; for (let row = 0; row < this.board.length; row++) { for (let col = 0; col < this.board[row].length; col++) { @@ -406,19 +353,18 @@ export class Game { has2048Cell = true; } - // Перевірка на можливість злиття if ( row < this.board.length - 1 && this.board[row][col] === this.board[row + 1][col] ) { - canMove = true; // Якщо клітинки злиті по вертикалі + canMove = true; } if ( col < this.board[row].length - 1 && this.board[row][col] === this.board[row][col + 1] ) { - canMove = true; // Якщо клітинки злиті по горизонталі + canMove = true; } } } @@ -437,19 +383,11 @@ export class Game { return this.status; } - /** - * Starts the game. - */ start() { this.resetGameStart(); } - /** - * Resets the game. - */ restart() { this.resetGameStart(); } - - // Add your own methods here } diff --git a/src/scripts/main.js b/src/scripts/main.js index ec01b0aab..6f706082c 100644 --- a/src/scripts/main.js +++ b/src/scripts/main.js @@ -1,6 +1,5 @@ 'use strict'; -// Ініціалізація гри import { WIN, LOSE, Game } from '../modules/Game.class'; const game = new Game(null, showWinMessage, showLoseMessage); @@ -36,11 +35,10 @@ function saveScore(sscore) { if (!currentRecord || sscore > currentRecord) { localStorage.setItem('highScore', sscore); - displayRecord(); // Оновлюємо рекорд на екрані + displayRecord(); } } -// Функція для відображення рекорду function displayRecord() { const highScore = localStorage.getItem('highScore') || 0; @@ -49,16 +47,14 @@ function displayRecord() { displayRecord(); -// Оновлення рекорду, коли він збільшується game.getScore = function (moved, value) { if (moved && value > 0) { - this.score += value; // Додаємо до поточного рахунку - updateScore(this.score); // Оновлюємо відображення рахунку - saveScore(this.score); // Перевіряємо, чи це новий рекорд, і зберігаємо його + this.score += value; + updateScore(this.score); + saveScore(this.score); } }; -// Обробка натискання на кнопку старту startButton.addEventListener('click', () => { startButton.textContent = 'Restart'; startButton.classList.remove('start'); @@ -73,10 +69,10 @@ startButton.addEventListener('click', () => { } game.start(); - displayRecord(); // Відображаємо рекорд при старті гри + hideMessage(); + displayRecord(); }); -// Обробка натискання клавіш document.addEventListener('keydown', (e) => { switch (e.key) { case 'ArrowLeft': diff --git a/src/styles/main.scss b/src/styles/main.scss index c0cf92e31..ff2145119 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -188,15 +188,17 @@ h1 { } .message-lose { + padding-top: 5px; width: 100%; box-sizing: border-box; - height: 50px !important; - padding: 10px; + height: 60px !important; + padding-top: 12px; background: #bf687c; color: #f9f6f2; text-align: center; border-radius: 5px; font-size: 20px; + margin-top: 35px; } .message-container { @@ -233,4 +235,5 @@ h1 { .field-cell--merged { animation: merge-tile 0.2s ease; + transition: transform 0.2s ease, opacity 0.4s ease; } From 5772247f134e82869991e939030155a32f7e41bf Mon Sep 17 00:00:00 2001 From: Iryna Mariiko Date: Mon, 11 Nov 2024 22:51:36 +0200 Subject: [PATCH 08/14] Solution --- src/styles/main.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/src/styles/main.scss b/src/styles/main.scss index ff2145119..d44d69e04 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -188,7 +188,6 @@ h1 { } .message-lose { - padding-top: 5px; width: 100%; box-sizing: border-box; height: 60px !important; From df1ba8047ce0679dcb8dcf86f2c00c464d1b2b0b Mon Sep 17 00:00:00 2001 From: Iryna Mariiko Date: Tue, 12 Nov 2024 09:13:17 +0200 Subject: [PATCH 09/14] Fixed --- src/scripts/main.js | 1 + src/styles/main.scss | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/scripts/main.js b/src/scripts/main.js index 6f706082c..429b4c0b2 100644 --- a/src/scripts/main.js +++ b/src/scripts/main.js @@ -59,6 +59,7 @@ startButton.addEventListener('click', () => { startButton.textContent = 'Restart'; startButton.classList.remove('start'); startButton.classList.add('restart'); + score.textContent = '0'; cells.forEach((cell) => { cell.classList.remove('hidden'); diff --git a/src/styles/main.scss b/src/styles/main.scss index d44d69e04..ce1749bc6 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -191,7 +191,7 @@ h1 { width: 100%; box-sizing: border-box; height: 60px !important; - padding-top: 12px; + padding-top: 14px; background: #bf687c; color: #f9f6f2; text-align: center; From b3cea2e308ad7088af3e2f2024ce7625c63e120c Mon Sep 17 00:00:00 2001 From: Iryna Mariiko Date: Tue, 12 Nov 2024 09:14:21 +0200 Subject: [PATCH 10/14] make build --- dist/Untitled.be14dc54.png | Bin 0 -> 1825 bytes dist/index.1ca8bb72.js | 2 ++ dist/index.1ca8bb72.js.map | 1 + dist/index.eaaf36ec.css | 2 ++ dist/index.eaaf36ec.css.map | 1 + dist/index.edb5a6b7.js | 2 ++ dist/index.edb5a6b7.js.map | 1 + dist/index.html | 1 + 8 files changed, 10 insertions(+) create mode 100644 dist/Untitled.be14dc54.png create mode 100644 dist/index.1ca8bb72.js create mode 100644 dist/index.1ca8bb72.js.map create mode 100644 dist/index.eaaf36ec.css create mode 100644 dist/index.eaaf36ec.css.map create mode 100644 dist/index.edb5a6b7.js create mode 100644 dist/index.edb5a6b7.js.map create mode 100644 dist/index.html diff --git a/dist/Untitled.be14dc54.png b/dist/Untitled.be14dc54.png new file mode 100644 index 0000000000000000000000000000000000000000..b696a183f518874bb2eaa65dc90e1d9cd8b70f4d GIT binary patch literal 1825 zcmV++2j2LJP)Px#32;bRa{vGf6951U69E94oEQKA0MbxQR7L;)|MK$q=H~I)+UnWa>dejKzrozU zz}&O6)u*V=rl`)Rr_QFQ&YGLYnVZLrkHCzNz>SW;jE=y7g1K~dvUGK_b9J(3X{%aY zq*`30PEegqP@O?UmO(?7G&heeFnua5bSf-#Cn;+rCSoKdVk0GDAR<{EA5a<`NE#eR z8XHI&8%G`<9u^rt7Z^Vm7(NylKNc508X6iH7#J2778Mm05D_g95iAoE6A=*+4Gts? z4I~c_4-E|s3kwSe2NDPf2nGid1qKTR1q%cO1OfsAX*`W6000H(NklZNnoKXA?eKj|4Tc;IEwXx61KBr_4xV1%aNr=SNGa- za*m*AFqz+eZ5OxK)1muAg3;-_zwGE~CvvHiSXD_6#o@&m@ec{zD9Ui^x2@Nrog z&sP`=tJ$M*d4aKTzFZs6;t4V0U$X*=MLZ!!yu2%*DBJmHc60Vnz%-_$K)j#8^`96M zH*>gc`-Y;)$6NS%g)wpUwKMk78OK9s?58u1htAkfXB-cmv7gR39y((`opC&L#(p~E zc<7A%{Ex;t{%bOs;jZLL`9=&IXM-LE07&>TddVeE2moQJw-EyXs<37#1`1uM0jIEr z^rU)$v1Fj3(&H-#Y#>}YJAySFpXdVs9DByoaJ8rLm_ZYoq0KRYCQP9PZy1lOc4#nS zU_g%cGR_EC2s9C(@y8}wd#$yUj zq)(Vo;vFYz{#Q5}jq9svDznij=^c=`+Sdc%+Y8^c$5EGS2L*JtcQWlS8#%I@eSU~CkNH+XujxhJ7= zGbyBDOzn7ru*Xxo8fQ8~J=w^N9*ulIvEpawF~>BCPQ#owZZKhE91msgxZhDDZ+eLC zM{=qgnu5|cMg|o}#_d>oje`gy35MPtd2=e#YAAIB`6jlRaMdd9t zNpgItah^bhGz+m8G=8mBKD=BjIL$%~`AjGlzjgjeJiQLzCTnm%tY!fq&?cK0$ zMue17q`a3<@7u0uq_3pl95-w{rk)GAafkQRBm^1N!p%8oXBsdL3)?Tm{_W-%f`~fb zD|)$=)-r5t3)4|x&+pkWz1!8e9_Y|sM_^%NTUeoIi^e=@47yc-ldWljbd5m*#$jRq zZc|6K_sp~R=?7zUlckA{uw#sXu`Qe^bTD);88?G9Oj$xHWj!wBP^qMaD<&q!7CqClDN)K}BDg zk1eY9Gd?x80rux1VPgRmgr`D?lylA)UBjf~vofA3L?sy*CGW-&xw;xpa6^{pMGhE; z?)*Y`3T`;=Yb@Z2WH3U^)p1I}*nb6#1w2FM`OMclM%eh2f`yS_0b>r&kQ(*rA0uq6 zI|>Mgj0aE=T=X#q1Ew$l(Z)tc7H@J47zbC$uB(i}7UU3v2zPa6J!nGGz22H+${6c$ zF60^^c#kEN01%d;!H6eN!47iVfw!L9{8;vq+BQjtIbz88<>Xl=vr)ct^JkhWl{vqG z{La7S{g3F3(rL}?t~X%O?sPTaVL zNnEFztfo*rM0IjZSwL}jiScl;D4>{q!FX8B3Mh(Y`_Fc(xhRVQikOa>TFoDgi{T`lcwT7VXCugHm%bl P00000NkvXXu0mjfxxh|N literal 0 HcmV?d00001 diff --git a/dist/index.1ca8bb72.js b/dist/index.1ca8bb72.js new file mode 100644 index 000000000..15f89ab8b --- /dev/null +++ b/dist/index.1ca8bb72.js @@ -0,0 +1,2 @@ +!function(){var t="idle",e="playing",o="lose",r=new(function(){var r;function a(e,o,r){!function(t,e){if(!(t instanceof e))throw TypeError("Cannot call a class as a function")}(this,a),this.board=e||[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],this.score=0,this.status=t,this.isStarted=!1,this.winCallback=o,this.loseCallback=r}return r=[{key:"moveTile",value:function(t,e){var o=t.getBoundingClientRect(),r=e.getBoundingClientRect(),a=r.left-o.left,n=r.top-o.top;t.style.setProperty("--x-offset","".concat(a,"px")),t.style.setProperty("--y-offset","".concat(n,"px")),t.classList.add("moving")}},{key:"updateBoard",value:function(){for(var t=document.querySelectorAll(".field-cell"),e=0,o=0;o0){var r=t[Math.floor(Math.random()*t.length)],a=r.row,n=r.col;0===this.score&&(this.board[a][n]=2),this.updateBoard()}}},{key:"addRandomCellAfterMoving",value:function(){for(var t=[],e=0;e<4;e++)for(var o=0;o<4;o++)0===this.board[e][o]&&t.push({row:e,col:o});if(t.length>0){var r=t[Math.floor(Math.random()*t.length)],a=r.row,n=r.col;this.board[a][n]=.9>Math.random()?2:4,this.updateBoard()}}},{key:"createColumn",value:function(t){for(var e=[],o=0;o0;a--)o[a]===o[a-1]&&r[a]&&r[a-1]&&(o[a]*=2,o.splice(a-1,1),t=!0,r[a]=!1,this.getScore(t,o[a]));for(;o.length0){var o,r,a;this.score+=e,o=this.score,s.textContent=o,r=this.score,(a=localStorage.getItem("highScore"))&&!(r>a)||(localStorage.setItem("highScore",r),u())}},a.addEventListener("click",function(){a.textContent="Restart",a.classList.remove("start"),a.classList.add("restart"),s.textContent="0",n.forEach(function(t){t.classList.remove("hidden")}),("win"===r.status||r.status===o)&&h(),r.start(),h(),u()}),document.addEventListener("keydown",function(t){switch(t.key){case"ArrowLeft":r.moveLeft();break;case"ArrowRight":r.moveRight();break;case"ArrowUp":r.moveUp();break;case"ArrowDown":r.moveDown()}})}(); +//# sourceMappingURL=index.1ca8bb72.js.map diff --git a/dist/index.1ca8bb72.js.map b/dist/index.1ca8bb72.js.map new file mode 100644 index 000000000..e0d3366b6 --- /dev/null +++ b/dist/index.1ca8bb72.js.map @@ -0,0 +1 @@ +{"mappings":"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","sources":["","src/scripts/main.js","src/modules/Game.class.js","node_modules/@swc/helpers/esm/_class_call_check.js","node_modules/@swc/helpers/esm/_create_class.js"],"sourcesContent":["(function () {\nfunction $8713978b2328d32b$export$71511d61b312f219(instance, Constructor) {\n if (!(instance instanceof Constructor)) throw new TypeError(\"Cannot call a class as a function\");\n}\n\n\nfunction $4fc75ccb937ab1df$var$_defineProperties(target, props) {\n for(var i = 0; i < props.length; i++){\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n}\nfunction $4fc75ccb937ab1df$export$71511d61b312f219(Constructor, protoProps, staticProps) {\n if (protoProps) $4fc75ccb937ab1df$var$_defineProperties(Constructor.prototype, protoProps);\n if (staticProps) $4fc75ccb937ab1df$var$_defineProperties(Constructor, staticProps);\n return Constructor;\n}\n\n\n\"use strict\";\nvar $3d28d7f1aac198f5$var$IDLE = \"idle\";\nvar $3d28d7f1aac198f5$var$PLAYING = \"playing\";\nvar $3d28d7f1aac198f5$export$eb2b832b8b9fda85 = \"win\";\nvar $3d28d7f1aac198f5$export$43a03cf66b318012 = \"lose\";\nvar $3d28d7f1aac198f5$export$985739bfa5723e08 = /*#__PURE__*/ function() {\n function Game(initialState, winCallback, loseCallback) {\n (0, $8713978b2328d32b$export$71511d61b312f219)(this, Game);\n this.board = initialState || [\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ]\n ];\n this.score = 0;\n this.status = $3d28d7f1aac198f5$var$IDLE;\n this.isStarted = false;\n this.winCallback = winCallback;\n this.loseCallback = loseCallback;\n }\n (0, $4fc75ccb937ab1df$export$71511d61b312f219)(Game, [\n {\n key: \"moveTile\",\n value: function moveTile(fromCell, toCell) {\n var fromCellRect = fromCell.getBoundingClientRect();\n var toCellRect = toCell.getBoundingClientRect();\n var xOffset = toCellRect.left - fromCellRect.left;\n var yOffset = toCellRect.top - fromCellRect.top;\n fromCell.style.setProperty(\"--x-offset\", \"\".concat(xOffset, \"px\"));\n fromCell.style.setProperty(\"--y-offset\", \"\".concat(yOffset, \"px\"));\n fromCell.classList.add(\"moving\");\n }\n },\n {\n key: \"updateBoard\",\n value: function updateBoard() {\n var cells = document.querySelectorAll(\".field-cell\");\n var cellIndex = 0;\n for(var row = 0; row < this.board.length; row++)for(var col = 0; col < this.board[row].length; col++){\n var cell = cells[cellIndex++];\n var value = this.board[row][col];\n var previousValue = cell.textContent;\n cell.classList.remove(\"field-cell--\".concat(previousValue));\n if (value === 0) cell.textContent = \"\";\n else {\n cell.classList.add(\"field-cell--\".concat(value));\n cell.textContent = value;\n }\n }\n }\n },\n {\n key: \"addRandomTile\",\n value: function addRandomTile() {\n var emptyCells = [];\n for(var row = 0; row < 4; row++){\n for(var col = 0; col < 4; col++)if (this.board[row][col] === 0) emptyCells.push({\n row: row,\n col: col\n });\n }\n if (emptyCells.length > 0) {\n var _emptyCells_Math_floor = emptyCells[Math.floor(Math.random() * emptyCells.length)], row1 = _emptyCells_Math_floor.row, col1 = _emptyCells_Math_floor.col;\n if (this.score === 0) this.board[row1][col1] = 2;\n this.updateBoard();\n }\n }\n },\n {\n key: \"addRandomCellAfterMoving\",\n value: function addRandomCellAfterMoving() {\n var emptyCells = [];\n for(var row = 0; row < 4; row++){\n for(var col = 0; col < 4; col++)if (this.board[row][col] === 0) emptyCells.push({\n row: row,\n col: col\n });\n }\n if (emptyCells.length > 0) {\n var _emptyCells_Math_floor = emptyCells[Math.floor(Math.random() * emptyCells.length)], row1 = _emptyCells_Math_floor.row, col1 = _emptyCells_Math_floor.col;\n this.board[row1][col1] = Math.random() < 0.9 ? 2 : 4;\n this.updateBoard();\n }\n }\n },\n {\n key: \"createColumn\",\n value: function createColumn(col) {\n var newColumn = [];\n for(var row = 0; row < this.board.length; row++)if (this.board[row][col] !== 0) newColumn.push(this.board[row][col]);\n return newColumn;\n }\n },\n {\n key: \"updateColumn\",\n value: function updateColumn(col, newColumn) {\n var moved = false;\n for(var row = 0; row < this.board.length; row++)if (this.board[row][col] !== newColumn[row]) {\n this.board[row][col] = newColumn[row];\n moved = true;\n }\n return moved;\n }\n },\n {\n key: \"resetGameStart\",\n value: function resetGameStart() {\n this.score = 0;\n this.status = $3d28d7f1aac198f5$var$PLAYING;\n this.board = [\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ]\n ];\n this.addRandomTile();\n this.addRandomTile();\n }\n },\n {\n key: \"mergeTitles\",\n value: function mergeTitles(newRow, canMerge) {\n var mergedThisMove = [];\n for(var i = 0; i < newRow.length - 1; i++)if (newRow[i] === newRow[i + 1]) {\n newRow[i] *= 2;\n newRow.splice(i + 1, 1);\n canMerge[i] = false;\n mergedThisMove.push(i);\n }\n return mergedThisMove;\n }\n },\n {\n key: \"moveLeft\",\n value: function moveLeft() {\n var _this = this, _loop = function(row) {\n var currentRow = _this.board[row].filter(function(val) {\n return val !== 0;\n });\n var mergedRow = [];\n var skip = false;\n for(var i = 0; i < currentRow.length; i++){\n if (skip) {\n skip = false;\n continue;\n }\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n _this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else mergedRow.push(currentRow[i]);\n }\n while(mergedRow.length < _this.board[row].length)mergedRow.push(0);\n if (!moved) {\n for(var i1 = 0; i1 < _this.board[row].length; i1++)if (_this.board[row][i1] !== mergedRow[i1]) {\n moved = true;\n break;\n }\n }\n _this.board[row] = mergedRow;\n };\n var moved = false;\n for(var row = 0; row < this.board.length; row++)_loop(row);\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n },\n {\n key: \"moveRight\",\n value: function moveRight() {\n var _this = this, _loop = function(row) {\n var currentRow = _this.board[row].filter(function(val) {\n return val !== 0;\n });\n var mergedRow = [];\n var skip = false;\n for(var i = 0; i < currentRow.length; i++){\n if (skip) {\n skip = false;\n continue;\n }\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n _this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else mergedRow.push(currentRow[i]);\n }\n while(mergedRow.length < _this.board[row].length)mergedRow.unshift(0);\n for(var i1 = 0; i1 < _this.board[row].length; i1++)if (_this.board[row][i1] !== mergedRow[i1]) {\n moved = true;\n break;\n }\n _this.board[row] = mergedRow;\n };\n var moved = false;\n for(var row = 0; row < this.board.length; row++)_loop(row);\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n },\n {\n key: \"moveUp\",\n value: function moveUp() {\n var moved = false;\n for(var col = 0; col < this.board.length; col++){\n var newColumn = this.createColumn(col);\n var canMerge = new Array(newColumn.length).fill(true);\n for(var i = 0; i < newColumn.length - 1; i++)if (newColumn[i] === newColumn[i + 1] && canMerge[i] && canMerge[i + 1]) {\n newColumn[i] *= 2;\n newColumn.splice(i + 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n while(newColumn.length < this.board.length)newColumn.push(0);\n moved = this.updateColumn(col, newColumn) || moved;\n }\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n },\n {\n key: \"moveDown\",\n value: function moveDown() {\n var moved = false;\n for(var col = 0; col < this.board.length; col++){\n var newColumn = this.createColumn(col);\n var canMerge = new Array(newColumn.length).fill(true);\n for(var i = newColumn.length - 1; i > 0; i--)if (newColumn[i] === newColumn[i - 1] && canMerge[i] && canMerge[i - 1]) {\n newColumn[i] *= 2;\n newColumn.splice(i - 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n while(newColumn.length < this.board.length)newColumn.unshift(0);\n moved = this.updateColumn(col, newColumn) || moved;\n }\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n },\n {\n /**\n * @returns {number[][]}\n */ key: \"getState\",\n value: function getState() {\n return this.board;\n }\n },\n {\n key: \"getStatus\",\n value: function getStatus() {\n if (this.score === 0) this.status = $3d28d7f1aac198f5$var$IDLE;\n else {\n var hasEmptyCell = false;\n var has2048Cell = false;\n var canMove = false;\n for(var row = 0; row < this.board.length; row++)for(var col = 0; col < this.board[row].length; col++){\n if (this.board[row][col] === 0) hasEmptyCell = true;\n if (this.board[row][col] === 2048) has2048Cell = true;\n if (row < this.board.length - 1 && this.board[row][col] === this.board[row + 1][col]) canMove = true;\n if (col < this.board[row].length - 1 && this.board[row][col] === this.board[row][col + 1]) canMove = true;\n }\n if (has2048Cell) {\n this.status = $3d28d7f1aac198f5$export$eb2b832b8b9fda85;\n this.winCallback();\n } else if (hasEmptyCell || canMove) this.status = $3d28d7f1aac198f5$var$PLAYING;\n else {\n this.status = $3d28d7f1aac198f5$export$43a03cf66b318012;\n this.loseCallback();\n }\n }\n return this.status;\n }\n },\n {\n key: \"start\",\n value: function start() {\n this.resetGameStart();\n }\n },\n {\n key: \"restart\",\n value: function restart() {\n this.resetGameStart();\n }\n }\n ]);\n return Game;\n}();\n\n\n\"use strict\";\nvar $197cd56b15c33885$var$game = new (0, $3d28d7f1aac198f5$export$985739bfa5723e08)(null, $197cd56b15c33885$var$showWinMessage, $197cd56b15c33885$var$showLoseMessage);\nvar $197cd56b15c33885$var$startButton = document.querySelector(\".start\");\nvar $197cd56b15c33885$var$cells = document.querySelectorAll(\".field-cell\");\nvar $197cd56b15c33885$var$score = document.querySelector(\".game-score\");\nvar $197cd56b15c33885$var$recordElement = document.querySelector(\".best__score\");\nvar $197cd56b15c33885$var$messageContainer = document.querySelector(\".message-container\");\nfunction $197cd56b15c33885$var$showWinMessage() {\n $197cd56b15c33885$var$messageContainer.classList.remove(\"hidden\");\n $197cd56b15c33885$var$messageContainer.classList.add(\"message-win\");\n $197cd56b15c33885$var$messageContainer.textContent = \"You Win!\";\n}\nfunction $197cd56b15c33885$var$showLoseMessage() {\n $197cd56b15c33885$var$messageContainer.classList.remove(\"hidden\");\n $197cd56b15c33885$var$messageContainer.classList.add(\"message-lose\");\n $197cd56b15c33885$var$messageContainer.textContent = \"You Lose!\";\n}\nfunction $197cd56b15c33885$var$hideMessage() {\n $197cd56b15c33885$var$messageContainer.classList.add(\"hidden\");\n}\nfunction $197cd56b15c33885$var$updateScore(value) {\n $197cd56b15c33885$var$score.textContent = value;\n}\nfunction $197cd56b15c33885$var$saveScore(sscore) {\n var currentRecord = localStorage.getItem(\"highScore\");\n if (!currentRecord || sscore > currentRecord) {\n localStorage.setItem(\"highScore\", sscore);\n $197cd56b15c33885$var$displayRecord();\n }\n}\nfunction $197cd56b15c33885$var$displayRecord() {\n var highScore = localStorage.getItem(\"highScore\") || 0;\n $197cd56b15c33885$var$recordElement.textContent = highScore;\n}\n$197cd56b15c33885$var$displayRecord();\n$197cd56b15c33885$var$game.getScore = function(moved, value) {\n if (moved && value > 0) {\n this.score += value;\n $197cd56b15c33885$var$updateScore(this.score);\n $197cd56b15c33885$var$saveScore(this.score);\n }\n};\n$197cd56b15c33885$var$startButton.addEventListener(\"click\", function() {\n $197cd56b15c33885$var$startButton.textContent = \"Restart\";\n $197cd56b15c33885$var$startButton.classList.remove(\"start\");\n $197cd56b15c33885$var$startButton.classList.add(\"restart\");\n $197cd56b15c33885$var$score.textContent = \"0\";\n $197cd56b15c33885$var$cells.forEach(function(cell) {\n cell.classList.remove(\"hidden\");\n });\n if ($197cd56b15c33885$var$game.status === (0, $3d28d7f1aac198f5$export$eb2b832b8b9fda85) || $197cd56b15c33885$var$game.status === (0, $3d28d7f1aac198f5$export$43a03cf66b318012)) $197cd56b15c33885$var$hideMessage();\n $197cd56b15c33885$var$game.start();\n $197cd56b15c33885$var$hideMessage();\n $197cd56b15c33885$var$displayRecord();\n});\ndocument.addEventListener(\"keydown\", function(e) {\n switch(e.key){\n case \"ArrowLeft\":\n $197cd56b15c33885$var$game.moveLeft();\n break;\n case \"ArrowRight\":\n $197cd56b15c33885$var$game.moveRight();\n break;\n case \"ArrowUp\":\n $197cd56b15c33885$var$game.moveUp();\n break;\n case \"ArrowDown\":\n $197cd56b15c33885$var$game.moveDown();\n break;\n }\n});\n\n})();\n//# sourceMappingURL=index.1ca8bb72.js.map\n","'use strict';\n\nimport { WIN, LOSE, Game } from '../modules/Game.class';\n\nconst game = new Game(null, showWinMessage, showLoseMessage);\n\nconst startButton = document.querySelector('.start');\nconst cells = document.querySelectorAll('.field-cell');\nconst score = document.querySelector('.game-score');\nconst recordElement = document.querySelector('.best__score');\nconst messageContainer = document.querySelector('.message-container');\n\nfunction showWinMessage() {\n messageContainer.classList.remove('hidden');\n messageContainer.classList.add('message-win');\n messageContainer.textContent = 'You Win!';\n}\n\nfunction showLoseMessage() {\n messageContainer.classList.remove('hidden');\n messageContainer.classList.add('message-lose');\n messageContainer.textContent = 'You Lose!';\n}\n\nfunction hideMessage() {\n messageContainer.classList.add('hidden');\n}\n\nfunction updateScore(value) {\n score.textContent = value;\n}\n\nfunction saveScore(sscore) {\n const currentRecord = localStorage.getItem('highScore');\n\n if (!currentRecord || sscore > currentRecord) {\n localStorage.setItem('highScore', sscore);\n displayRecord();\n }\n}\n\nfunction displayRecord() {\n const highScore = localStorage.getItem('highScore') || 0;\n\n recordElement.textContent = highScore;\n}\n\ndisplayRecord();\n\ngame.getScore = function (moved, value) {\n if (moved && value > 0) {\n this.score += value;\n updateScore(this.score);\n saveScore(this.score);\n }\n};\n\nstartButton.addEventListener('click', () => {\n startButton.textContent = 'Restart';\n startButton.classList.remove('start');\n startButton.classList.add('restart');\n score.textContent = '0';\n\n cells.forEach((cell) => {\n cell.classList.remove('hidden');\n });\n\n if (game.status === WIN || game.status === LOSE) {\n hideMessage();\n }\n\n game.start();\n hideMessage();\n displayRecord();\n});\n\ndocument.addEventListener('keydown', (e) => {\n switch (e.key) {\n case 'ArrowLeft':\n game.moveLeft();\n break;\n case 'ArrowRight':\n game.moveRight();\n break;\n case 'ArrowUp':\n game.moveUp();\n break;\n case 'ArrowDown':\n game.moveDown();\n break;\n }\n});\n","'use strict';\n\nconst IDLE = 'idle';\nconst PLAYING = 'playing';\n\nexport const WIN = 'win';\nexport const LOSE = 'lose';\n\nexport class Game {\n constructor(initialState, winCallback, loseCallback) {\n this.board = initialState || [\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n ];\n\n this.score = 0;\n\n this.status = IDLE;\n this.isStarted = false;\n this.winCallback = winCallback;\n this.loseCallback = loseCallback;\n }\n\n moveTile(fromCell, toCell) {\n const fromCellRect = fromCell.getBoundingClientRect();\n const toCellRect = toCell.getBoundingClientRect();\n\n const xOffset = toCellRect.left - fromCellRect.left;\n const yOffset = toCellRect.top - fromCellRect.top;\n\n fromCell.style.setProperty('--x-offset', `${xOffset}px`);\n fromCell.style.setProperty('--y-offset', `${yOffset}px`);\n\n fromCell.classList.add('moving');\n }\n\n updateBoard() {\n const cells = document.querySelectorAll('.field-cell');\n\n let cellIndex = 0;\n\n for (let row = 0; row < this.board.length; row++) {\n for (let col = 0; col < this.board[row].length; col++) {\n const cell = cells[cellIndex++];\n const value = this.board[row][col];\n const previousValue = cell.textContent;\n\n cell.classList.remove(`field-cell--${previousValue}`);\n\n if (value === 0) {\n cell.textContent = '';\n } else {\n cell.classList.add(`field-cell--${value}`);\n cell.textContent = value;\n }\n }\n }\n }\n\n addRandomTile() {\n const emptyCells = [];\n\n for (let row = 0; row < 4; row++) {\n for (let col = 0; col < 4; col++) {\n if (this.board[row][col] === 0) {\n emptyCells.push({ row, col });\n }\n }\n }\n\n if (emptyCells.length > 0) {\n const { row, col } =\n emptyCells[Math.floor(Math.random() * emptyCells.length)];\n\n if (this.score === 0) {\n this.board[row][col] = 2;\n }\n this.updateBoard();\n }\n }\n\n addRandomCellAfterMoving() {\n const emptyCells = [];\n\n for (let row = 0; row < 4; row++) {\n for (let col = 0; col < 4; col++) {\n if (this.board[row][col] === 0) {\n emptyCells.push({ row, col });\n }\n }\n }\n\n if (emptyCells.length > 0) {\n const { row, col } =\n emptyCells[Math.floor(Math.random() * emptyCells.length)];\n\n this.board[row][col] = Math.random() < 0.9 ? 2 : 4;\n this.updateBoard();\n }\n }\n\n createColumn(col) {\n const newColumn = [];\n\n for (let row = 0; row < this.board.length; row++) {\n if (this.board[row][col] !== 0) {\n newColumn.push(this.board[row][col]);\n }\n }\n\n return newColumn;\n }\n\n updateColumn(col, newColumn) {\n let moved = false;\n\n for (let row = 0; row < this.board.length; row++) {\n if (this.board[row][col] !== newColumn[row]) {\n this.board[row][col] = newColumn[row];\n moved = true;\n }\n }\n\n return moved;\n }\n\n resetGameStart() {\n this.score = 0;\n this.status = PLAYING;\n\n this.board = [\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n ];\n\n this.addRandomTile();\n this.addRandomTile();\n }\n\n mergeTitles(newRow, canMerge) {\n const mergedThisMove = [];\n\n for (let i = 0; i < newRow.length - 1; i++) {\n if (newRow[i] === newRow[i + 1]) {\n newRow[i] *= 2;\n newRow.splice(i + 1, 1);\n canMerge[i] = false;\n mergedThisMove.push(i);\n }\n }\n\n return mergedThisMove;\n }\n\n moveLeft() {\n let moved = false;\n\n for (let row = 0; row < this.board.length; row++) {\n const currentRow = this.board[row].filter((val) => val !== 0);\n const mergedRow = [];\n\n let skip = false;\n\n for (let i = 0; i < currentRow.length; i++) {\n if (skip) {\n skip = false;\n continue;\n }\n\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else {\n mergedRow.push(currentRow[i]);\n }\n }\n\n while (mergedRow.length < this.board[row].length) {\n mergedRow.push(0);\n }\n\n if (!moved) {\n for (let i = 0; i < this.board[row].length; i++) {\n if (this.board[row][i] !== mergedRow[i]) {\n moved = true;\n break;\n }\n }\n }\n\n this.board[row] = mergedRow;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n moveRight() {\n let moved = false;\n\n for (let row = 0; row < this.board.length; row++) {\n const currentRow = this.board[row].filter((val) => val !== 0);\n\n const mergedRow = [];\n let skip = false;\n\n for (let i = 0; i < currentRow.length; i++) {\n if (skip) {\n skip = false;\n continue;\n }\n\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else {\n mergedRow.push(currentRow[i]);\n }\n }\n\n while (mergedRow.length < this.board[row].length) {\n mergedRow.unshift(0);\n }\n\n for (let i = 0; i < this.board[row].length; i++) {\n if (this.board[row][i] !== mergedRow[i]) {\n moved = true;\n break;\n }\n }\n\n this.board[row] = mergedRow;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n moveUp() {\n let moved = false;\n\n for (let col = 0; col < this.board.length; col++) {\n const newColumn = this.createColumn(col);\n const canMerge = new Array(newColumn.length).fill(true);\n\n for (let i = 0; i < newColumn.length - 1; i++) {\n if (\n newColumn[i] === newColumn[i + 1] &&\n canMerge[i] &&\n canMerge[i + 1]\n ) {\n newColumn[i] *= 2;\n newColumn.splice(i + 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n }\n\n while (newColumn.length < this.board.length) {\n newColumn.push(0);\n }\n\n moved = this.updateColumn(col, newColumn) || moved;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n moveDown() {\n let moved = false;\n\n for (let col = 0; col < this.board.length; col++) {\n const newColumn = this.createColumn(col);\n const canMerge = new Array(newColumn.length).fill(true);\n\n for (let i = newColumn.length - 1; i > 0; i--) {\n if (\n newColumn[i] === newColumn[i - 1] &&\n canMerge[i] &&\n canMerge[i - 1]\n ) {\n newColumn[i] *= 2;\n newColumn.splice(i - 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n }\n\n while (newColumn.length < this.board.length) {\n newColumn.unshift(0);\n }\n\n moved = this.updateColumn(col, newColumn) || moved;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n /**\n * @returns {number[][]}\n */\n getState() {\n return this.board;\n }\n\n getStatus() {\n if (this.score === 0) {\n this.status = IDLE;\n } else {\n let hasEmptyCell = false;\n let has2048Cell = false;\n let canMove = false;\n\n for (let row = 0; row < this.board.length; row++) {\n for (let col = 0; col < this.board[row].length; col++) {\n if (this.board[row][col] === 0) {\n hasEmptyCell = true;\n }\n\n if (this.board[row][col] === 2048) {\n has2048Cell = true;\n }\n\n if (\n row < this.board.length - 1 &&\n this.board[row][col] === this.board[row + 1][col]\n ) {\n canMove = true;\n }\n\n if (\n col < this.board[row].length - 1 &&\n this.board[row][col] === this.board[row][col + 1]\n ) {\n canMove = true;\n }\n }\n }\n\n if (has2048Cell) {\n this.status = WIN;\n this.winCallback();\n } else if (hasEmptyCell || canMove) {\n this.status = PLAYING;\n } else {\n this.status = LOSE;\n this.loseCallback();\n }\n }\n\n return this.status;\n }\n\n start() {\n this.resetGameStart();\n }\n\n restart() {\n this.resetGameStart();\n }\n}\n","function _class_call_check(instance, Constructor) {\n if (!(instance instanceof Constructor)) throw new TypeError(\"Cannot call a class as a function\");\n}\nexport { _class_call_check as _ };\n","function _defineProperties(target, props) {\n for (var i = 0; i < props.length; i++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n\n if (\"value\" in descriptor) descriptor.writable = true;\n\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n}\nfunction _create_class(Constructor, protoProps, staticProps) {\n if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n if (staticProps) _defineProperties(Constructor, staticProps);\n\n return Constructor;\n}\nexport { _create_class as _ };\n"],"names":["$3d28d7f1aac198f5$var$IDLE","$3d28d7f1aac198f5$var$PLAYING","$3d28d7f1aac198f5$export$43a03cf66b318012","$197cd56b15c33885$var$game","protoProps","Game","initialState","winCallback","loseCallback","instance","Constructor","TypeError","board","score","status","isStarted","key","value","fromCell","toCell","fromCellRect","getBoundingClientRect","toCellRect","xOffset","left","yOffset","top","style","setProperty","concat","classList","add","cells","document","querySelectorAll","cellIndex","row","length","col","cell","previousValue","textContent","remove","emptyCells","push","_emptyCells_Math_floor","Math","floor","random","row1","col1","updateBoard","newColumn","moved","addRandomTile","newRow","canMerge","mergedThisMove","i","splice","_this","_loop","currentRow","filter","val","mergedRow","skip","getScore","i1","addRandomCellAfterMoving","getStatus","unshift","createColumn","Array","fill","updateColumn","hasEmptyCell","has2048Cell","canMove","resetGameStart","$4fc75ccb937ab1df$var$_defineProperties","target","props","descriptor","enumerable","configurable","writable","Object","defineProperty","prototype","$197cd56b15c33885$var$messageContainer","$197cd56b15c33885$var$startButton","querySelector","$197cd56b15c33885$var$cells","$197cd56b15c33885$var$score","$197cd56b15c33885$var$recordElement","$197cd56b15c33885$var$hideMessage","$197cd56b15c33885$var$displayRecord","highScore","localStorage","getItem","sscore","currentRecord","setItem","addEventListener","forEach","start","e","moveLeft","moveRight","moveUp","moveDown"],"version":3,"file":"index.1ca8bb72.js.map"} \ No newline at end of file diff --git a/dist/index.eaaf36ec.css b/dist/index.eaaf36ec.css new file mode 100644 index 000000000..7ce3022c5 --- /dev/null +++ b/dist/index.eaaf36ec.css @@ -0,0 +1,2 @@ +body{background:#fbf8ef;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center;min-height:100vh;margin:0;font-family:sans-serif;font-size:24px;font-weight:900;display:-ms-flexbox;display:flex}.field-cell{color:#776e65;box-sizing:border-box;text-align:center;vertical-align:middle;-webkit-user-select:none;-ms-user-select:none;user-select:none;background:#d6cdc4;border-radius:5px;width:75px;height:75px;transition:transform .2s,background-color .2s;position:relative}.field-cell:empty{background:#d6cdc4}.field-cell--2{background:#eee4da}.field-cell--4{background:#e1d5c7}.field-cell--8{color:#f9f6f2;background:#5cb3bb}.field-cell--16{color:#f9f6f2;background:#469299}.field-cell--32{color:#f9f6f2;background:#349569}.field-cell--64{color:#f9f6f2;background:#30ac64}.field-cell--128{color:#f9f6f2;background:#26b84d}.field-cell--256{color:#fbfbfb;background:#0b7476}.field-cell--512{color:#f9f6f2;background:#5b8fd9}.field-cell--1024{color:#f9f6f2;background:#3b75c6}.field-cell--2048{color:#f9f6f2;background:#3b49c6}.game-field{border-spacing:10px;background:#bbada0;border-radius:5px}.game-header{box-sizing:border-box;-ms-flex-pack:justify;justify-content:space-between;width:100%;margin-bottom:24px;padding:10px;display:-ms-flexbox;display:flex}h1{color:#f9f6f2;box-sizing:border-box;background:#3a6ed6;border-radius:5px;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center;width:75px;height:75px;margin:0;font-size:24px;display:-ms-flexbox;display:flex}.best,.info{color:#776e65;box-sizing:border-box;background:#d6cdc4;border-radius:5px;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center;width:75px;height:75px;margin:0 8px 0 0;font-size:16px;display:-ms-flexbox;display:flex}.controls{display:-ms-flexbox;display:flex}.button{cursor:pointer;color:#f9f6f2;border:none;border-radius:5px;width:75px;height:75px;font-family:sans-serif;font-size:16px;font-weight:700;transition:background .25s}.start{background:#0aca6d;font-size:20px}.start:hover{background:#10b96a}.restart{background:#eb5b7d}.restart:hover{background:#d45271}.message{box-sizing:border-box;color:#776e65;text-align:center;background:#d6cdc4;border-radius:5px;width:100%;padding:10px;font-size:20px}.hidden{display:none}.container{-ms-flex-direction:column;flex-direction:column;-ms-flex-align:center;align-items:center;width:350px;display:-ms-flexbox;display:flex}.message-win{color:#f9f6f2;background:#2669b5}.message-lose{box-sizing:border-box;color:#f9f6f2;text-align:center;background:#bf687c;border-radius:5px;width:100%;margin-top:35px;padding-top:14px;font-size:20px;height:60px!important}.message-container{width:100%;height:150px}.moving{animation:.5s forwards move-tile}@keyframes move-tile{0%{transform:translate(var(--x-offset),var(--y-offset))}to{transform:translate(0)}}@keyframes merge-tile{0%{opacity:1;transform:scale(1);box-shadow:0 0 transparent}50%{opacity:.7;transform:scale(1.2);box-shadow:0 0 10px rgba(0,0,0,.3)}to{opacity:1;transform:scale(1);box-shadow:0 0 transparent}}.field-cell--merged{transition:transform .2s,opacity .4s;animation:.2s merge-tile} +/*# sourceMappingURL=index.eaaf36ec.css.map */ diff --git a/dist/index.eaaf36ec.css.map b/dist/index.eaaf36ec.css.map new file mode 100644 index 000000000..e5dc23ddd --- /dev/null +++ b/dist/index.eaaf36ec.css.map @@ -0,0 +1 @@ +{"mappings":"ACAA,8NAYA,mRAcA,qCAIA,kCAIA,kCAIA,gDAKA,iDAKA,iDAKA,iDAKA,kDAKA,kDAKA,kDAKA,mDAKA,mDAKA,qEAMA,mKASA,iPAcA,kTAgBA,2CAIA,2KAaA,yCAIE,gCAKF,4BAGE,kCAKF,2IAWA,qBAIA,iJAOA,8CAKA,0LAaA,2CAKA,yCAIA,wGAKA,oNAkBA","sources":["index.eaaf36ec.css","src/styles/main.scss"],"sourcesContent":["body {\n background: #fbf8ef;\n justify-content: center;\n align-items: center;\n min-height: 100vh;\n margin: 0;\n font-family: sans-serif;\n font-size: 24px;\n font-weight: 900;\n display: -ms-flexbox;\n display: flex;\n}\n\n.field-cell {\n color: #776e65;\n box-sizing: border-box;\n text-align: center;\n vertical-align: middle;\n -webkit-user-select: none;\n -ms-user-select: none;\n user-select: none;\n background: #d6cdc4;\n border-radius: 5px;\n width: 75px;\n height: 75px;\n transition: transform .2s, background-color .2s;\n position: relative;\n}\n\n.field-cell:empty {\n background: #d6cdc4;\n}\n\n.field-cell--2 {\n background: #eee4da;\n}\n\n.field-cell--4 {\n background: #e1d5c7;\n}\n\n.field-cell--8 {\n color: #f9f6f2;\n background: #5cb3bb;\n}\n\n.field-cell--16 {\n color: #f9f6f2;\n background: #469299;\n}\n\n.field-cell--32 {\n color: #f9f6f2;\n background: #349569;\n}\n\n.field-cell--64 {\n color: #f9f6f2;\n background: #30ac64;\n}\n\n.field-cell--128 {\n color: #f9f6f2;\n background: #26b84d;\n}\n\n.field-cell--256 {\n color: #fbfbfb;\n background: #0b7476;\n}\n\n.field-cell--512 {\n color: #f9f6f2;\n background: #5b8fd9;\n}\n\n.field-cell--1024 {\n color: #f9f6f2;\n background: #3b75c6;\n}\n\n.field-cell--2048 {\n color: #f9f6f2;\n background: #3b49c6;\n}\n\n.game-field {\n border-spacing: 10px;\n background: #bbada0;\n border-radius: 5px;\n}\n\n.game-header {\n box-sizing: border-box;\n justify-content: space-between;\n width: 100%;\n margin-bottom: 24px;\n padding: 10px;\n display: -ms-flexbox;\n display: flex;\n}\n\nh1 {\n color: #f9f6f2;\n box-sizing: border-box;\n background: #3a6ed6;\n border-radius: 5px;\n justify-content: center;\n align-items: center;\n width: 75px;\n height: 75px;\n margin: 0;\n font-size: 24px;\n display: -ms-flexbox;\n display: flex;\n}\n\n.best, .info {\n color: #776e65;\n box-sizing: border-box;\n background: #d6cdc4;\n border-radius: 5px;\n -ms-flex-direction: column;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n width: 75px;\n height: 75px;\n margin: 0 8px 0 0;\n font-size: 16px;\n display: -ms-flexbox;\n display: flex;\n}\n\n.controls {\n display: -ms-flexbox;\n display: flex;\n}\n\n.button {\n cursor: pointer;\n color: #f9f6f2;\n border: none;\n border-radius: 5px;\n width: 75px;\n height: 75px;\n font-family: sans-serif;\n font-size: 16px;\n font-weight: 700;\n transition: background .25s;\n}\n\n.start {\n background: #0aca6d;\n font-size: 20px;\n}\n\n.start:hover {\n background: #10b96a;\n}\n\n.restart {\n background: #eb5b7d;\n}\n\n.restart:hover {\n background: #d45271;\n}\n\n.message {\n box-sizing: border-box;\n color: #776e65;\n text-align: center;\n background: #d6cdc4;\n border-radius: 5px;\n width: 100%;\n padding: 10px;\n font-size: 20px;\n}\n\n.hidden {\n display: none;\n}\n\n.container {\n -ms-flex-direction: column;\n flex-direction: column;\n align-items: center;\n width: 350px;\n display: -ms-flexbox;\n display: flex;\n}\n\n.message-win {\n color: #f9f6f2;\n background: #2669b5;\n}\n\n.message-lose {\n box-sizing: border-box;\n color: #f9f6f2;\n text-align: center;\n background: #bf687c;\n border-radius: 5px;\n width: 100%;\n margin-top: 35px;\n padding-top: 14px;\n font-size: 20px;\n height: 60px !important;\n}\n\n.message-container {\n width: 100%;\n height: 150px;\n}\n\n.moving {\n animation: .5s forwards move-tile;\n}\n\n@keyframes move-tile {\n from {\n transform: translate(var(--x-offset), var(--y-offset));\n }\n\n to {\n transform: translate(0);\n }\n}\n\n@keyframes merge-tile {\n 0% {\n opacity: 1;\n transform: scale(1);\n box-shadow: 0 0 #0000;\n }\n\n 50% {\n opacity: .7;\n transform: scale(1.2);\n box-shadow: 0 0 10px #0000004d;\n }\n\n 100% {\n opacity: 1;\n transform: scale(1);\n box-shadow: 0 0 #0000;\n }\n}\n\n.field-cell--merged {\n transition: transform .2s, opacity .4s;\n animation: .2s merge-tile;\n}\n/*# sourceMappingURL=index.eaaf36ec.css.map */\n","body {\n margin: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n background: #fbf8ef;\n font-family: sans-serif;\n font-size: 24px;\n font-weight: 900;\n}\n\n.field-cell {\n background: #d6cdc4;\n width: 75px;\n height: 75px;\n border-radius: 5px;\n color: #776e65;\n box-sizing: border-box;\n text-align: center;\n vertical-align: middle;\n user-select: none;\n position: relative;\n transition: transform 0.2s ease, background-color 0.2s ease;\n}\n\n.field-cell:empty {\n background: #d6cdc4;\n}\n\n.field-cell--2 {\n background: #eee4da;\n}\n\n.field-cell--4 {\n background: #e1d5c7;\n}\n\n.field-cell--8 {\n background: #5cb3bb;\n color: #f9f6f2;\n}\n\n.field-cell--16 {\n background: #469299;\n color: #f9f6f2;\n}\n\n.field-cell--32 {\n background: #349569;\n color: #f9f6f2;\n}\n\n.field-cell--64 {\n background: #30ac64;\n color: #f9f6f2;\n}\n\n.field-cell--128 {\n background: #26b84d;\n color: #f9f6f2;\n}\n\n.field-cell--256 {\n background: #0b7476;\n color: #fbfbfb;\n}\n\n.field-cell--512 {\n background: #5b8fd9;\n color: #f9f6f2;\n}\n\n.field-cell--1024 {\n background: #3b75c6;\n color: #f9f6f2;\n}\n\n.field-cell--2048 {\n background: #3b49c6;\n color: #f9f6f2;\n}\n\n.game-field {\n background: #bbada0;\n border-spacing: 10px;\n border-radius: 5px;\n}\n\n.game-header {\n display: flex;\n width: 100%;\n justify-content: space-between;\n margin-bottom: 24px;\n padding: 10px;\n box-sizing: border-box;\n}\n\nh1 {\n background: #3a6ed6;\n color: #f9f6f2;\n width: 75px;\n height: 75px;\n font-size: 24px;\n border-radius: 5px;\n display: flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n margin: 0;\n}\n\n.best,\n.info {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background: #d6cdc4;\n width: 75px;\n height: 75px;\n border-radius: 5px;\n color: #776e65;\n box-sizing: border-box;\n font-size: 16px;\n margin: 0 8px 0 0;\n}\n\n.controls {\n display: flex;\n}\n\n.button {\n border: none;\n border-radius: 5px;\n cursor: pointer;\n color: #f9f6f2;\n font-family: sans-serif;\n font-weight: 700;\n font-size: 16px;\n width: 75px;\n height: 75px;\n transition: 0.25s ease background;\n}\n\n.start {\n background: #0aca6d;\n font-size: 20px;\n\n &:hover {\n background: #10b96a;\n }\n}\n\n.restart {\n background: #eb5b7d;\n\n &:hover {\n background: #d45271;\n }\n}\n\n.message {\n box-sizing: border-box;\n width: 100%;\n background: #d6cdc4;\n color: #776e65;\n padding: 10px;\n text-align: center;\n border-radius: 5px;\n font-size: 20px;\n}\n\n.hidden {\n display: none;\n}\n\n.container {\n display: flex;\n flex-direction: column;\n align-items: center;\n width: 350px;\n}\n\n.message-win {\n background: #2669b5;\n color: #f9f6f2;\n}\n\n.message-lose {\n width: 100%;\n box-sizing: border-box;\n height: 60px !important;\n padding-top: 14px;\n background: #bf687c;\n color: #f9f6f2;\n text-align: center;\n border-radius: 5px;\n font-size: 20px;\n margin-top: 35px;\n}\n\n.message-container {\n width: 100%;\n height: 150px;\n}\n\n.moving {\n animation: move-tile 0.5s forwards;\n}\n\n@keyframes move-tile {\n from { transform: translate(var(--x-offset), var(--y-offset)); }\n to { transform: translate(0, 0); }\n}\n\n@keyframes merge-tile {\n 0% {\n transform: scale(1);\n opacity: 1;\n box-shadow: 0 0 0 rgba(0, 0, 0, 0);\n }\n 50% {\n transform: scale(1.2);\n opacity: 0.7;\n box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);\n }\n 100% {\n transform: scale(1);\n opacity: 1;\n box-shadow: 0 0 0 rgba(0, 0, 0, 0);\n }\n}\n\n.field-cell--merged {\n animation: merge-tile 0.2s ease;\n transition: transform 0.2s ease, opacity 0.4s ease;\n}\n"],"names":[],"version":3,"file":"index.eaaf36ec.css.map"} \ No newline at end of file diff --git a/dist/index.edb5a6b7.js b/dist/index.edb5a6b7.js new file mode 100644 index 000000000..e658eafdf --- /dev/null +++ b/dist/index.edb5a6b7.js @@ -0,0 +1,2 @@ +const t="idle",e="playing",s="lose",o=new class{constructor(e,s,o){this.board=e||[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],this.score=0,this.status=t,this.isStarted=!1,this.winCallback=s,this.loseCallback=o}moveTile(t,e){let s=t.getBoundingClientRect(),o=e.getBoundingClientRect(),r=o.left-s.left,l=o.top-s.top;t.style.setProperty("--x-offset",`${r}px`),t.style.setProperty("--y-offset",`${l}px`),t.classList.add("moving")}updateBoard(){let t=document.querySelectorAll(".field-cell"),e=0;for(let s=0;s0){let{row:e,col:s}=t[Math.floor(Math.random()*t.length)];0===this.score&&(this.board[e][s]=2),this.updateBoard()}}addRandomCellAfterMoving(){let t=[];for(let e=0;e<4;e++)for(let s=0;s<4;s++)0===this.board[e][s]&&t.push({row:e,col:s});if(t.length>0){let{row:e,col:s}=t[Math.floor(Math.random()*t.length)];this.board[e][s]=.9>Math.random()?2:4,this.updateBoard()}}createColumn(t){let e=[];for(let s=0;s0!==t),o=[],r=!1;for(let e=0;e0!==t),o=[],r=!1;for(let e=0;e0;e--)s[e]===s[e-1]&&o[e]&&o[e-1]&&(s[e]*=2,s.splice(e-1,1),t=!0,o[e]=!1,this.getScore(t,s[e]));for(;s.length0){var s;this.score+=e,s=this.score,a.textContent=s,function(t){let e=localStorage.getItem("highScore");(!e||t>e)&&(localStorage.setItem("highScore",t),d())}(this.score)}},r.addEventListener("click",()=>{r.textContent="Restart",r.classList.remove("start"),r.classList.add("restart"),a.textContent="0",l.forEach(t=>{t.classList.remove("hidden")}),("win"===o.status||o.status===s)&&n(),o.start(),n(),d()}),document.addEventListener("keydown",t=>{switch(t.key){case"ArrowLeft":o.moveLeft();break;case"ArrowRight":o.moveRight();break;case"ArrowUp":o.moveUp();break;case"ArrowDown":o.moveDown()}}); +//# sourceMappingURL=index.edb5a6b7.js.map diff --git a/dist/index.edb5a6b7.js.map b/dist/index.edb5a6b7.js.map new file mode 100644 index 000000000..12e5a341d --- /dev/null +++ b/dist/index.edb5a6b7.js.map @@ -0,0 +1 @@ +{"mappings":"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","sources":["","src/scripts/main.js","src/modules/Game.class.js"],"sourcesContent":["\"use strict\";\nconst $a5fd07fa01589658$var$IDLE = \"idle\";\nconst $a5fd07fa01589658$var$PLAYING = \"playing\";\nconst $a5fd07fa01589658$export$eb2b832b8b9fda85 = \"win\";\nconst $a5fd07fa01589658$export$43a03cf66b318012 = \"lose\";\nclass $a5fd07fa01589658$export$985739bfa5723e08 {\n constructor(initialState, winCallback, loseCallback){\n this.board = initialState || [\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ]\n ];\n this.score = 0;\n this.status = $a5fd07fa01589658$var$IDLE;\n this.isStarted = false;\n this.winCallback = winCallback;\n this.loseCallback = loseCallback;\n }\n moveTile(fromCell, toCell) {\n const fromCellRect = fromCell.getBoundingClientRect();\n const toCellRect = toCell.getBoundingClientRect();\n const xOffset = toCellRect.left - fromCellRect.left;\n const yOffset = toCellRect.top - fromCellRect.top;\n fromCell.style.setProperty(\"--x-offset\", `${xOffset}px`);\n fromCell.style.setProperty(\"--y-offset\", `${yOffset}px`);\n fromCell.classList.add(\"moving\");\n }\n updateBoard() {\n const cells = document.querySelectorAll(\".field-cell\");\n let cellIndex = 0;\n for(let row = 0; row < this.board.length; row++)for(let col = 0; col < this.board[row].length; col++){\n const cell = cells[cellIndex++];\n const value = this.board[row][col];\n const previousValue = cell.textContent;\n cell.classList.remove(`field-cell--${previousValue}`);\n if (value === 0) cell.textContent = \"\";\n else {\n cell.classList.add(`field-cell--${value}`);\n cell.textContent = value;\n }\n }\n }\n addRandomTile() {\n const emptyCells = [];\n for(let row = 0; row < 4; row++){\n for(let col = 0; col < 4; col++)if (this.board[row][col] === 0) emptyCells.push({\n row: row,\n col: col\n });\n }\n if (emptyCells.length > 0) {\n const { row: row, col: col } = emptyCells[Math.floor(Math.random() * emptyCells.length)];\n if (this.score === 0) this.board[row][col] = 2;\n this.updateBoard();\n }\n }\n addRandomCellAfterMoving() {\n const emptyCells = [];\n for(let row = 0; row < 4; row++){\n for(let col = 0; col < 4; col++)if (this.board[row][col] === 0) emptyCells.push({\n row: row,\n col: col\n });\n }\n if (emptyCells.length > 0) {\n const { row: row, col: col } = emptyCells[Math.floor(Math.random() * emptyCells.length)];\n this.board[row][col] = Math.random() < 0.9 ? 2 : 4;\n this.updateBoard();\n }\n }\n createColumn(col) {\n const newColumn = [];\n for(let row = 0; row < this.board.length; row++)if (this.board[row][col] !== 0) newColumn.push(this.board[row][col]);\n return newColumn;\n }\n updateColumn(col, newColumn) {\n let moved = false;\n for(let row = 0; row < this.board.length; row++)if (this.board[row][col] !== newColumn[row]) {\n this.board[row][col] = newColumn[row];\n moved = true;\n }\n return moved;\n }\n resetGameStart() {\n this.score = 0;\n this.status = $a5fd07fa01589658$var$PLAYING;\n this.board = [\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ]\n ];\n this.addRandomTile();\n this.addRandomTile();\n }\n mergeTitles(newRow, canMerge) {\n const mergedThisMove = [];\n for(let i = 0; i < newRow.length - 1; i++)if (newRow[i] === newRow[i + 1]) {\n newRow[i] *= 2;\n newRow.splice(i + 1, 1);\n canMerge[i] = false;\n mergedThisMove.push(i);\n }\n return mergedThisMove;\n }\n moveLeft() {\n let moved = false;\n for(let row = 0; row < this.board.length; row++){\n const currentRow = this.board[row].filter((val)=>val !== 0);\n const mergedRow = [];\n let skip = false;\n for(let i = 0; i < currentRow.length; i++){\n if (skip) {\n skip = false;\n continue;\n }\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else mergedRow.push(currentRow[i]);\n }\n while(mergedRow.length < this.board[row].length)mergedRow.push(0);\n if (!moved) {\n for(let i = 0; i < this.board[row].length; i++)if (this.board[row][i] !== mergedRow[i]) {\n moved = true;\n break;\n }\n }\n this.board[row] = mergedRow;\n }\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n moveRight() {\n let moved = false;\n for(let row = 0; row < this.board.length; row++){\n const currentRow = this.board[row].filter((val)=>val !== 0);\n const mergedRow = [];\n let skip = false;\n for(let i = 0; i < currentRow.length; i++){\n if (skip) {\n skip = false;\n continue;\n }\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else mergedRow.push(currentRow[i]);\n }\n while(mergedRow.length < this.board[row].length)mergedRow.unshift(0);\n for(let i = 0; i < this.board[row].length; i++)if (this.board[row][i] !== mergedRow[i]) {\n moved = true;\n break;\n }\n this.board[row] = mergedRow;\n }\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n moveUp() {\n let moved = false;\n for(let col = 0; col < this.board.length; col++){\n const newColumn = this.createColumn(col);\n const canMerge = new Array(newColumn.length).fill(true);\n for(let i = 0; i < newColumn.length - 1; i++)if (newColumn[i] === newColumn[i + 1] && canMerge[i] && canMerge[i + 1]) {\n newColumn[i] *= 2;\n newColumn.splice(i + 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n while(newColumn.length < this.board.length)newColumn.push(0);\n moved = this.updateColumn(col, newColumn) || moved;\n }\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n moveDown() {\n let moved = false;\n for(let col = 0; col < this.board.length; col++){\n const newColumn = this.createColumn(col);\n const canMerge = new Array(newColumn.length).fill(true);\n for(let i = newColumn.length - 1; i > 0; i--)if (newColumn[i] === newColumn[i - 1] && canMerge[i] && canMerge[i - 1]) {\n newColumn[i] *= 2;\n newColumn.splice(i - 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n while(newColumn.length < this.board.length)newColumn.unshift(0);\n moved = this.updateColumn(col, newColumn) || moved;\n }\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n /**\n * @returns {number[][]}\n */ getState() {\n return this.board;\n }\n getStatus() {\n if (this.score === 0) this.status = $a5fd07fa01589658$var$IDLE;\n else {\n let hasEmptyCell = false;\n let has2048Cell = false;\n let canMove = false;\n for(let row = 0; row < this.board.length; row++)for(let col = 0; col < this.board[row].length; col++){\n if (this.board[row][col] === 0) hasEmptyCell = true;\n if (this.board[row][col] === 2048) has2048Cell = true;\n if (row < this.board.length - 1 && this.board[row][col] === this.board[row + 1][col]) canMove = true;\n if (col < this.board[row].length - 1 && this.board[row][col] === this.board[row][col + 1]) canMove = true;\n }\n if (has2048Cell) {\n this.status = $a5fd07fa01589658$export$eb2b832b8b9fda85;\n this.winCallback();\n } else if (hasEmptyCell || canMove) this.status = $a5fd07fa01589658$var$PLAYING;\n else {\n this.status = $a5fd07fa01589658$export$43a03cf66b318012;\n this.loseCallback();\n }\n }\n return this.status;\n }\n start() {\n this.resetGameStart();\n }\n restart() {\n this.resetGameStart();\n }\n}\n\n\n\"use strict\";\nconst $09e991522ca7e64e$var$game = new (0, $a5fd07fa01589658$export$985739bfa5723e08)(null, $09e991522ca7e64e$var$showWinMessage, $09e991522ca7e64e$var$showLoseMessage);\nconst $09e991522ca7e64e$var$startButton = document.querySelector(\".start\");\nconst $09e991522ca7e64e$var$cells = document.querySelectorAll(\".field-cell\");\nconst $09e991522ca7e64e$var$score = document.querySelector(\".game-score\");\nconst $09e991522ca7e64e$var$recordElement = document.querySelector(\".best__score\");\nconst $09e991522ca7e64e$var$messageContainer = document.querySelector(\".message-container\");\nfunction $09e991522ca7e64e$var$showWinMessage() {\n $09e991522ca7e64e$var$messageContainer.classList.remove(\"hidden\");\n $09e991522ca7e64e$var$messageContainer.classList.add(\"message-win\");\n $09e991522ca7e64e$var$messageContainer.textContent = \"You Win!\";\n}\nfunction $09e991522ca7e64e$var$showLoseMessage() {\n $09e991522ca7e64e$var$messageContainer.classList.remove(\"hidden\");\n $09e991522ca7e64e$var$messageContainer.classList.add(\"message-lose\");\n $09e991522ca7e64e$var$messageContainer.textContent = \"You Lose!\";\n}\nfunction $09e991522ca7e64e$var$hideMessage() {\n $09e991522ca7e64e$var$messageContainer.classList.add(\"hidden\");\n}\nfunction $09e991522ca7e64e$var$updateScore(value) {\n $09e991522ca7e64e$var$score.textContent = value;\n}\nfunction $09e991522ca7e64e$var$saveScore(sscore) {\n const currentRecord = localStorage.getItem(\"highScore\");\n if (!currentRecord || sscore > currentRecord) {\n localStorage.setItem(\"highScore\", sscore);\n $09e991522ca7e64e$var$displayRecord();\n }\n}\nfunction $09e991522ca7e64e$var$displayRecord() {\n const highScore = localStorage.getItem(\"highScore\") || 0;\n $09e991522ca7e64e$var$recordElement.textContent = highScore;\n}\n$09e991522ca7e64e$var$displayRecord();\n$09e991522ca7e64e$var$game.getScore = function(moved, value) {\n if (moved && value > 0) {\n this.score += value;\n $09e991522ca7e64e$var$updateScore(this.score);\n $09e991522ca7e64e$var$saveScore(this.score);\n }\n};\n$09e991522ca7e64e$var$startButton.addEventListener(\"click\", ()=>{\n $09e991522ca7e64e$var$startButton.textContent = \"Restart\";\n $09e991522ca7e64e$var$startButton.classList.remove(\"start\");\n $09e991522ca7e64e$var$startButton.classList.add(\"restart\");\n $09e991522ca7e64e$var$score.textContent = \"0\";\n $09e991522ca7e64e$var$cells.forEach((cell)=>{\n cell.classList.remove(\"hidden\");\n });\n if ($09e991522ca7e64e$var$game.status === (0, $a5fd07fa01589658$export$eb2b832b8b9fda85) || $09e991522ca7e64e$var$game.status === (0, $a5fd07fa01589658$export$43a03cf66b318012)) $09e991522ca7e64e$var$hideMessage();\n $09e991522ca7e64e$var$game.start();\n $09e991522ca7e64e$var$hideMessage();\n $09e991522ca7e64e$var$displayRecord();\n});\ndocument.addEventListener(\"keydown\", (e)=>{\n switch(e.key){\n case \"ArrowLeft\":\n $09e991522ca7e64e$var$game.moveLeft();\n break;\n case \"ArrowRight\":\n $09e991522ca7e64e$var$game.moveRight();\n break;\n case \"ArrowUp\":\n $09e991522ca7e64e$var$game.moveUp();\n break;\n case \"ArrowDown\":\n $09e991522ca7e64e$var$game.moveDown();\n break;\n }\n});\n\n\n//# sourceMappingURL=index.edb5a6b7.js.map\n","'use strict';\n\nimport { WIN, LOSE, Game } from '../modules/Game.class';\n\nconst game = new Game(null, showWinMessage, showLoseMessage);\n\nconst startButton = document.querySelector('.start');\nconst cells = document.querySelectorAll('.field-cell');\nconst score = document.querySelector('.game-score');\nconst recordElement = document.querySelector('.best__score');\nconst messageContainer = document.querySelector('.message-container');\n\nfunction showWinMessage() {\n messageContainer.classList.remove('hidden');\n messageContainer.classList.add('message-win');\n messageContainer.textContent = 'You Win!';\n}\n\nfunction showLoseMessage() {\n messageContainer.classList.remove('hidden');\n messageContainer.classList.add('message-lose');\n messageContainer.textContent = 'You Lose!';\n}\n\nfunction hideMessage() {\n messageContainer.classList.add('hidden');\n}\n\nfunction updateScore(value) {\n score.textContent = value;\n}\n\nfunction saveScore(sscore) {\n const currentRecord = localStorage.getItem('highScore');\n\n if (!currentRecord || sscore > currentRecord) {\n localStorage.setItem('highScore', sscore);\n displayRecord();\n }\n}\n\nfunction displayRecord() {\n const highScore = localStorage.getItem('highScore') || 0;\n\n recordElement.textContent = highScore;\n}\n\ndisplayRecord();\n\ngame.getScore = function (moved, value) {\n if (moved && value > 0) {\n this.score += value;\n updateScore(this.score);\n saveScore(this.score);\n }\n};\n\nstartButton.addEventListener('click', () => {\n startButton.textContent = 'Restart';\n startButton.classList.remove('start');\n startButton.classList.add('restart');\n score.textContent = '0';\n\n cells.forEach((cell) => {\n cell.classList.remove('hidden');\n });\n\n if (game.status === WIN || game.status === LOSE) {\n hideMessage();\n }\n\n game.start();\n hideMessage();\n displayRecord();\n});\n\ndocument.addEventListener('keydown', (e) => {\n switch (e.key) {\n case 'ArrowLeft':\n game.moveLeft();\n break;\n case 'ArrowRight':\n game.moveRight();\n break;\n case 'ArrowUp':\n game.moveUp();\n break;\n case 'ArrowDown':\n game.moveDown();\n break;\n }\n});\n","'use strict';\n\nconst IDLE = 'idle';\nconst PLAYING = 'playing';\n\nexport const WIN = 'win';\nexport const LOSE = 'lose';\n\nexport class Game {\n constructor(initialState, winCallback, loseCallback) {\n this.board = initialState || [\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n ];\n\n this.score = 0;\n\n this.status = IDLE;\n this.isStarted = false;\n this.winCallback = winCallback;\n this.loseCallback = loseCallback;\n }\n\n moveTile(fromCell, toCell) {\n const fromCellRect = fromCell.getBoundingClientRect();\n const toCellRect = toCell.getBoundingClientRect();\n\n const xOffset = toCellRect.left - fromCellRect.left;\n const yOffset = toCellRect.top - fromCellRect.top;\n\n fromCell.style.setProperty('--x-offset', `${xOffset}px`);\n fromCell.style.setProperty('--y-offset', `${yOffset}px`);\n\n fromCell.classList.add('moving');\n }\n\n updateBoard() {\n const cells = document.querySelectorAll('.field-cell');\n\n let cellIndex = 0;\n\n for (let row = 0; row < this.board.length; row++) {\n for (let col = 0; col < this.board[row].length; col++) {\n const cell = cells[cellIndex++];\n const value = this.board[row][col];\n const previousValue = cell.textContent;\n\n cell.classList.remove(`field-cell--${previousValue}`);\n\n if (value === 0) {\n cell.textContent = '';\n } else {\n cell.classList.add(`field-cell--${value}`);\n cell.textContent = value;\n }\n }\n }\n }\n\n addRandomTile() {\n const emptyCells = [];\n\n for (let row = 0; row < 4; row++) {\n for (let col = 0; col < 4; col++) {\n if (this.board[row][col] === 0) {\n emptyCells.push({ row, col });\n }\n }\n }\n\n if (emptyCells.length > 0) {\n const { row, col } =\n emptyCells[Math.floor(Math.random() * emptyCells.length)];\n\n if (this.score === 0) {\n this.board[row][col] = 2;\n }\n this.updateBoard();\n }\n }\n\n addRandomCellAfterMoving() {\n const emptyCells = [];\n\n for (let row = 0; row < 4; row++) {\n for (let col = 0; col < 4; col++) {\n if (this.board[row][col] === 0) {\n emptyCells.push({ row, col });\n }\n }\n }\n\n if (emptyCells.length > 0) {\n const { row, col } =\n emptyCells[Math.floor(Math.random() * emptyCells.length)];\n\n this.board[row][col] = Math.random() < 0.9 ? 2 : 4;\n this.updateBoard();\n }\n }\n\n createColumn(col) {\n const newColumn = [];\n\n for (let row = 0; row < this.board.length; row++) {\n if (this.board[row][col] !== 0) {\n newColumn.push(this.board[row][col]);\n }\n }\n\n return newColumn;\n }\n\n updateColumn(col, newColumn) {\n let moved = false;\n\n for (let row = 0; row < this.board.length; row++) {\n if (this.board[row][col] !== newColumn[row]) {\n this.board[row][col] = newColumn[row];\n moved = true;\n }\n }\n\n return moved;\n }\n\n resetGameStart() {\n this.score = 0;\n this.status = PLAYING;\n\n this.board = [\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n ];\n\n this.addRandomTile();\n this.addRandomTile();\n }\n\n mergeTitles(newRow, canMerge) {\n const mergedThisMove = [];\n\n for (let i = 0; i < newRow.length - 1; i++) {\n if (newRow[i] === newRow[i + 1]) {\n newRow[i] *= 2;\n newRow.splice(i + 1, 1);\n canMerge[i] = false;\n mergedThisMove.push(i);\n }\n }\n\n return mergedThisMove;\n }\n\n moveLeft() {\n let moved = false;\n\n for (let row = 0; row < this.board.length; row++) {\n const currentRow = this.board[row].filter((val) => val !== 0);\n const mergedRow = [];\n\n let skip = false;\n\n for (let i = 0; i < currentRow.length; i++) {\n if (skip) {\n skip = false;\n continue;\n }\n\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else {\n mergedRow.push(currentRow[i]);\n }\n }\n\n while (mergedRow.length < this.board[row].length) {\n mergedRow.push(0);\n }\n\n if (!moved) {\n for (let i = 0; i < this.board[row].length; i++) {\n if (this.board[row][i] !== mergedRow[i]) {\n moved = true;\n break;\n }\n }\n }\n\n this.board[row] = mergedRow;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n moveRight() {\n let moved = false;\n\n for (let row = 0; row < this.board.length; row++) {\n const currentRow = this.board[row].filter((val) => val !== 0);\n\n const mergedRow = [];\n let skip = false;\n\n for (let i = 0; i < currentRow.length; i++) {\n if (skip) {\n skip = false;\n continue;\n }\n\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else {\n mergedRow.push(currentRow[i]);\n }\n }\n\n while (mergedRow.length < this.board[row].length) {\n mergedRow.unshift(0);\n }\n\n for (let i = 0; i < this.board[row].length; i++) {\n if (this.board[row][i] !== mergedRow[i]) {\n moved = true;\n break;\n }\n }\n\n this.board[row] = mergedRow;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n moveUp() {\n let moved = false;\n\n for (let col = 0; col < this.board.length; col++) {\n const newColumn = this.createColumn(col);\n const canMerge = new Array(newColumn.length).fill(true);\n\n for (let i = 0; i < newColumn.length - 1; i++) {\n if (\n newColumn[i] === newColumn[i + 1] &&\n canMerge[i] &&\n canMerge[i + 1]\n ) {\n newColumn[i] *= 2;\n newColumn.splice(i + 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n }\n\n while (newColumn.length < this.board.length) {\n newColumn.push(0);\n }\n\n moved = this.updateColumn(col, newColumn) || moved;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n moveDown() {\n let moved = false;\n\n for (let col = 0; col < this.board.length; col++) {\n const newColumn = this.createColumn(col);\n const canMerge = new Array(newColumn.length).fill(true);\n\n for (let i = newColumn.length - 1; i > 0; i--) {\n if (\n newColumn[i] === newColumn[i - 1] &&\n canMerge[i] &&\n canMerge[i - 1]\n ) {\n newColumn[i] *= 2;\n newColumn.splice(i - 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n }\n\n while (newColumn.length < this.board.length) {\n newColumn.unshift(0);\n }\n\n moved = this.updateColumn(col, newColumn) || moved;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n /**\n * @returns {number[][]}\n */\n getState() {\n return this.board;\n }\n\n getStatus() {\n if (this.score === 0) {\n this.status = IDLE;\n } else {\n let hasEmptyCell = false;\n let has2048Cell = false;\n let canMove = false;\n\n for (let row = 0; row < this.board.length; row++) {\n for (let col = 0; col < this.board[row].length; col++) {\n if (this.board[row][col] === 0) {\n hasEmptyCell = true;\n }\n\n if (this.board[row][col] === 2048) {\n has2048Cell = true;\n }\n\n if (\n row < this.board.length - 1 &&\n this.board[row][col] === this.board[row + 1][col]\n ) {\n canMove = true;\n }\n\n if (\n col < this.board[row].length - 1 &&\n this.board[row][col] === this.board[row][col + 1]\n ) {\n canMove = true;\n }\n }\n }\n\n if (has2048Cell) {\n this.status = WIN;\n this.winCallback();\n } else if (hasEmptyCell || canMove) {\n this.status = PLAYING;\n } else {\n this.status = LOSE;\n this.loseCallback();\n }\n }\n\n return this.status;\n }\n\n start() {\n this.resetGameStart();\n }\n\n restart() {\n this.resetGameStart();\n }\n}\n"],"names":["$a5fd07fa01589658$var$IDLE","$a5fd07fa01589658$var$PLAYING","$a5fd07fa01589658$export$43a03cf66b318012","$09e991522ca7e64e$var$game","constructor","initialState","winCallback","loseCallback","board","score","status","isStarted","moveTile","fromCell","toCell","fromCellRect","getBoundingClientRect","toCellRect","xOffset","left","yOffset","top","style","setProperty","classList","add","updateBoard","cells","document","querySelectorAll","cellIndex","row","length","col","cell","value","previousValue","textContent","remove","addRandomTile","emptyCells","push","Math","floor","random","addRandomCellAfterMoving","createColumn","newColumn","updateColumn","moved","resetGameStart","mergeTitles","newRow","canMerge","mergedThisMove","i","splice","moveLeft","currentRow","filter","val","mergedRow","skip","getScore","getStatus","moveRight","unshift","moveUp","Array","fill","moveDown","getState","hasEmptyCell","has2048Cell","canMove","start","restart","$09e991522ca7e64e$var$messageContainer","$09e991522ca7e64e$var$startButton","querySelector","$09e991522ca7e64e$var$cells","$09e991522ca7e64e$var$score","$09e991522ca7e64e$var$recordElement","$09e991522ca7e64e$var$hideMessage","$09e991522ca7e64e$var$displayRecord","highScore","localStorage","getItem","$09e991522ca7e64e$var$saveScore","sscore","currentRecord","setItem","addEventListener","forEach","e","key"],"version":3,"file":"index.edb5a6b7.js.map"} \ No newline at end of file diff --git a/dist/index.html b/dist/index.html new file mode 100644 index 000000000..7ced03203 --- /dev/null +++ b/dist/index.html @@ -0,0 +1 @@ +2048

2048

Best: 0

Score: 0

Press "Start" to begin game. Good luck!

\ No newline at end of file From ea736ce45862c940ccf95f3fac3fa5018ecf1dbe Mon Sep 17 00:00:00 2001 From: Iryna Mariiko Date: Tue, 12 Nov 2024 11:17:47 +0200 Subject: [PATCH 11/14] Solution --- src/scripts/main.js | 31 ++++++++++++++++++++----------- src/styles/main.scss | 8 -------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/scripts/main.js b/src/scripts/main.js index 429b4c0b2..6ba853b36 100644 --- a/src/scripts/main.js +++ b/src/scripts/main.js @@ -8,22 +8,28 @@ const startButton = document.querySelector('.start'); const cells = document.querySelectorAll('.field-cell'); const score = document.querySelector('.game-score'); const recordElement = document.querySelector('.best__score'); -const messageContainer = document.querySelector('.message-container'); +const messageStart = document.querySelector('.message-start'); +const messageWin = document.querySelector('.message-win'); +const messageLose = document.querySelector('.message-lose'); function showWinMessage() { - messageContainer.classList.remove('hidden'); - messageContainer.classList.add('message-win'); - messageContainer.textContent = 'You Win!'; + messageWin.classList.remove('hidden'); } function showLoseMessage() { - messageContainer.classList.remove('hidden'); - messageContainer.classList.add('message-lose'); - messageContainer.textContent = 'You Lose!'; + messageLose.classList.remove('hidden'); } -function hideMessage() { - messageContainer.classList.add('hidden'); +function hideMessageStart() { + messageStart.classList.add('hidden'); +} + +function hideMessageLose() { + messageLose.classList.add('hidden'); +} + +function hideMessageWin() { + messageWin.classList.add('hidden'); } function updateScore(value) { @@ -66,11 +72,14 @@ startButton.addEventListener('click', () => { }); if (game.status === WIN || game.status === LOSE) { - hideMessage(); + hideMessageWin(); + hideMessageLose(); } game.start(); - hideMessage(); + hideMessageStart(); + hideMessageLose(); + hideMessageWin(); displayRecord(); }); diff --git a/src/styles/main.scss b/src/styles/main.scss index ce1749bc6..14cc90dc3 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -188,16 +188,8 @@ h1 { } .message-lose { - width: 100%; - box-sizing: border-box; - height: 60px !important; - padding-top: 14px; background: #bf687c; color: #f9f6f2; - text-align: center; - border-radius: 5px; - font-size: 20px; - margin-top: 35px; } .message-container { From 0dc3f6b85e59d67c2abd5da5f1d8243b2f255f5f Mon Sep 17 00:00:00 2001 From: Iryna Mariiko Date: Tue, 12 Nov 2024 11:19:40 +0200 Subject: [PATCH 12/14] make build --- dist/index.0d5498be.js | 2 ++ dist/index.0d5498be.js.map | 1 + dist/index.1ca8bb72.js | 2 -- dist/index.1ca8bb72.js.map | 1 - dist/{index.eaaf36ec.css => index.b8123ea8.css} | 4 ++-- dist/index.b8123ea8.css.map | 1 + dist/index.eaaf36ec.css.map | 1 - dist/index.edb5a6b7.js.map | 1 - dist/{index.edb5a6b7.js => index.ef8de8d9.js} | 4 ++-- dist/index.ef8de8d9.js.map | 1 + dist/index.html | 2 +- 11 files changed, 10 insertions(+), 10 deletions(-) create mode 100644 dist/index.0d5498be.js create mode 100644 dist/index.0d5498be.js.map delete mode 100644 dist/index.1ca8bb72.js delete mode 100644 dist/index.1ca8bb72.js.map rename dist/{index.eaaf36ec.css => index.b8123ea8.css} (76%) create mode 100644 dist/index.b8123ea8.css.map delete mode 100644 dist/index.eaaf36ec.css.map delete mode 100644 dist/index.edb5a6b7.js.map rename dist/{index.edb5a6b7.js => index.ef8de8d9.js} (76%) create mode 100644 dist/index.ef8de8d9.js.map diff --git a/dist/index.0d5498be.js b/dist/index.0d5498be.js new file mode 100644 index 000000000..244b0fcfb --- /dev/null +++ b/dist/index.0d5498be.js @@ -0,0 +1,2 @@ +!function(){var t="idle",e="playing",r="lose",o=new(function(){var o;function a(e,r,o){!function(t,e){if(!(t instanceof e))throw TypeError("Cannot call a class as a function")}(this,a),this.board=e||[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],this.score=0,this.status=t,this.isStarted=!1,this.winCallback=r,this.loseCallback=o}return o=[{key:"moveTile",value:function(t,e){var r=t.getBoundingClientRect(),o=e.getBoundingClientRect(),a=o.left-r.left,n=o.top-r.top;t.style.setProperty("--x-offset","".concat(a,"px")),t.style.setProperty("--y-offset","".concat(n,"px")),t.classList.add("moving")}},{key:"updateBoard",value:function(){for(var t=document.querySelectorAll(".field-cell"),e=0,r=0;r0){var o=t[Math.floor(Math.random()*t.length)],a=o.row,n=o.col;0===this.score&&(this.board[a][n]=2),this.updateBoard()}}},{key:"addRandomCellAfterMoving",value:function(){for(var t=[],e=0;e<4;e++)for(var r=0;r<4;r++)0===this.board[e][r]&&t.push({row:e,col:r});if(t.length>0){var o=t[Math.floor(Math.random()*t.length)],a=o.row,n=o.col;this.board[a][n]=.9>Math.random()?2:4,this.updateBoard()}}},{key:"createColumn",value:function(t){for(var e=[],r=0;r0;a--)r[a]===r[a-1]&&o[a]&&o[a-1]&&(r[a]*=2,r.splice(a-1,1),t=!0,o[a]=!1,this.getScore(t,r[a]));for(;r.length0){var r,o,a;this.score+=e,r=this.score,s.textContent=r,o=this.score,(a=localStorage.getItem("highScore"))&&!(o>a)||(localStorage.setItem("highScore",o),f())}},a.addEventListener("click",function(){a.textContent="Restart",a.classList.remove("start"),a.classList.add("restart"),s.textContent="0",n.forEach(function(t){t.classList.remove("hidden")}),("win"===o.status||o.status===r)&&(c(),u()),o.start(),l.classList.add("hidden"),u(),c(),f()}),document.addEventListener("keydown",function(t){switch(t.key){case"ArrowLeft":o.moveLeft();break;case"ArrowRight":o.moveRight();break;case"ArrowUp":o.moveUp();break;case"ArrowDown":o.moveDown()}})}(); +//# sourceMappingURL=index.0d5498be.js.map diff --git a/dist/index.0d5498be.js.map b/dist/index.0d5498be.js.map new file mode 100644 index 000000000..7a6e02ea3 --- /dev/null +++ b/dist/index.0d5498be.js.map @@ -0,0 +1 @@ +{"mappings":"C,A,WEEA,IAAM,EAAO,OACP,EAAU,UAGH,EAAO,ODFd,EAAO,GCIN,CAAA,eEG6B,EFHvB,SAAA,EACC,CAAY,CAAE,CAAW,CAAE,CAAY,GADxC,ACRb,SAA2B,CAAQ,CAAE,CAAW,EAC5C,GAAI,CAAE,CAAA,aAAoB,CAAA,EAAc,MAAM,AAAI,UAAU,oCAChE,EDMa,IAAA,CAAA,GAET,IAAI,CAAC,KAAK,CAAG,GAAgB,CAC3B,CAAC,EAAG,EAAG,EAAG,EAAE,CACZ,CAAC,EAAG,EAAG,EAAG,EAAE,CACZ,CAAC,EAAG,EAAG,EAAG,EAAE,CACZ,CAAC,EAAG,EAAG,EAAG,EAAE,CACb,CAED,IAAI,CAAC,KAAK,CAAG,EAEb,IAAI,CAAC,MAAM,CAAG,EACd,IAAI,CAAC,SAAS,CAAG,CAAA,EACjB,IAAI,CAAC,WAAW,CAAG,EACnB,IAAI,CAAC,YAAY,CAAG,C,CAdX,OEGuB,EFHvB,C,CAiBX,IAAA,WAAA,MAAA,SAAS,CAAQ,CAAE,CAAM,EACvB,IAAM,EAAe,EAAS,qBAAqB,GAC7C,EAAa,EAAO,qBAAqB,GAEzC,EAAU,EAAW,IAAI,CAAG,EAAa,IAAI,CAC7C,EAAU,EAAW,GAAG,CAAG,EAAa,GAAG,CAEjD,EAAS,KAAK,CAAC,WAAW,CAAC,aAAe,GAAU,MAAA,CAAR,EAAQ,OACpD,EAAS,KAAK,CAAC,WAAW,CAAC,aAAe,GAAU,MAAA,CAAR,EAAQ,OAEpD,EAAS,SAAS,CAAC,GAAG,CAAC,SACzB,C,E,CAEA,IAAA,cAAA,MAAA,WAKE,IAAK,IAJC,EAAQ,SAAS,gBAAgB,CAAC,eAEpC,EAAY,EAEP,EAAM,EAAG,EAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAE,IACzC,IAAK,IAAI,EAAM,EAAG,EAAM,IAAI,CAAC,KAAK,CAAC,EAAI,CAAC,MAAM,CAAE,IAAO,CACrD,IAAM,EAAO,CAAK,CAAC,IAAY,CACzB,EAAQ,IAAI,CAAC,KAAK,CAAC,EAAI,CAAC,EAAI,CAC5B,EAAgB,EAAK,WAAW,CAEtC,EAAK,SAAS,CAAC,MAAM,CAAE,eAA4B,MAAA,CAAd,IAEjC,AAAU,IAAV,EACF,EAAK,WAAW,CAAG,IAEnB,EAAK,SAAS,CAAC,GAAG,CAAE,eAAoB,MAAA,CAAN,IAClC,EAAK,WAAW,CAAG,EAEvB,CAEJ,C,E,CAEA,IAAA,gBAAA,MAAA,WAGE,IAAK,IAFC,EAAa,EAAE,CAEZ,EAAM,EAAG,EAAM,EAAG,IACzB,IAAK,IAAI,EAAM,EAAG,EAAM,EAAG,IACI,IAAzB,IAAI,CAAC,KAAK,CAAC,EAAI,CAAC,EAAI,EACtB,EAAW,IAAI,CAAC,CAAE,IAAA,EAAK,IAAA,CAAI,GAKjC,GAAI,EAAW,MAAM,CAAG,EAAG,CACzB,IACE,EAAA,CAAU,CAAC,KAAK,KAAK,CAAC,KAAK,MAAM,GAAK,EAAW,MAAM,EAAE,CADnD,EACN,EADM,GAAA,CAAK,EACX,EADW,GAAb,AAGmB,CAAA,IAAf,IAAI,CAAC,KAAK,EACZ,CAAA,IAAI,CAAC,KAAK,CAAC,EAAI,CAAC,EAAI,CAAG,CAAA,EAEzB,IAAI,CAAC,WAAW,EAClB,CACF,C,E,CAEA,IAAA,2BAAA,MAAA,WAGE,IAAK,IAFC,EAAa,EAAE,CAEZ,EAAM,EAAG,EAAM,EAAG,IACzB,IAAK,IAAI,EAAM,EAAG,EAAM,EAAG,IACI,IAAzB,IAAI,CAAC,KAAK,CAAC,EAAI,CAAC,EAAI,EACtB,EAAW,IAAI,CAAC,CAAE,IAAA,EAAK,IAAA,CAAI,GAKjC,GAAI,EAAW,MAAM,CAAG,EAAG,CACzB,IACE,EAAA,CAAU,CAAC,KAAK,KAAK,CAAC,KAAK,MAAM,GAAK,EAAW,MAAM,EAAE,CADnD,EACN,EADM,GAAA,CAAK,EACX,EADW,GAAb,AAGA,CAAA,IAAI,CAAC,KAAK,CAAC,EAAI,CAAC,EAAI,CAAG,AAAgB,GAAhB,KAAK,MAAM,GAAW,EAAI,EACjD,IAAI,CAAC,WAAW,EAClB,CACF,C,E,CAEA,IAAA,eAAA,MAAA,SAAa,CAAG,EAGd,IAAK,IAFC,EAAY,EAAE,CAEX,EAAM,EAAG,EAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAE,IACZ,IAAzB,IAAI,CAAC,KAAK,CAAC,EAAI,CAAC,EAAI,EACtB,EAAU,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAI,CAAC,EAAI,EAIvC,OAAO,CACT,C,E,CAEA,IAAA,eAAA,MAAA,SAAa,CAAG,CAAE,CAAS,EAGzB,IAAK,IAFD,EAAQ,CAAA,EAEH,EAAM,EAAG,EAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAE,IACrC,IAAI,CAAC,KAAK,CAAC,EAAI,CAAC,EAAI,GAAK,CAAS,CAAC,EAAI,GACzC,IAAI,CAAC,KAAK,CAAC,EAAI,CAAC,EAAI,CAAG,CAAS,CAAC,EAAI,CACrC,EAAQ,CAAA,GAIZ,OAAO,CACT,C,E,CAEA,IAAA,iBAAA,MAAA,WACE,IAAI,CAAC,KAAK,CAAG,EACb,IAAI,CAAC,MAAM,CAAG,EAEd,IAAI,CAAC,KAAK,CAAG,CACX,CAAC,EAAG,EAAG,EAAG,EAAE,CACZ,CAAC,EAAG,EAAG,EAAG,EAAE,CACZ,CAAC,EAAG,EAAG,EAAG,EAAE,CACZ,CAAC,EAAG,EAAG,EAAG,EAAE,CACb,CAED,IAAI,CAAC,aAAa,GAClB,IAAI,CAAC,aAAa,EACpB,C,E,CAEA,IAAA,cAAA,MAAA,SAAY,CAAM,CAAE,CAAQ,EAG1B,IAAK,IAFC,EAAiB,EAAE,CAEhB,EAAI,EAAG,EAAI,EAAO,MAAM,CAAG,EAAG,IACjC,CAAM,CAAC,EAAE,GAAK,CAAM,CAAC,EAAI,EAAE,GAC7B,CAAM,CAAC,EAAE,EAAI,EACb,EAAO,MAAM,CAAC,EAAI,EAAG,GACrB,CAAQ,CAAC,EAAE,CAAG,CAAA,EACd,EAAe,IAAI,CAAC,IAIxB,OAAO,CACT,C,E,CAEA,IAAA,WAAA,MAAA,WAGE,IAAK,I,E,I,CAFD,EAAQ,CAAA,EAEH,EAAM,EAAG,EAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAE,KAA3C,A,S,C,EAME,IAAK,IALC,EAAa,EAAK,KAAK,CAAC,EAAI,CAAC,MAAM,CAAC,SAAC,CAA3C,EAAmD,OAAA,AAAQ,IAAR,C,GAC7C,EAAY,EAAE,CAEhB,EAAO,CAAA,EAEF,EAAI,EAAG,EAAI,EAAW,MAAM,CAAE,IAAK,CAC1C,GAAI,EAAM,CACR,EAAO,CAAA,EACP,QACF,CAEI,CAAU,CAAC,EAAE,GAAK,CAAU,CAAC,EAAI,EAAE,EACrC,EAAU,IAAI,CAAC,AAAgB,EAAhB,CAAU,CAAC,EAAE,EAC5B,EAAK,QAAQ,CAAC,CAAA,EAAM,AAAgB,EAAhB,CAAU,CAAC,EAAE,EACjC,EAAO,CAAA,EACP,EAAQ,CAAA,GAER,EAAU,IAAI,CAAC,CAAU,CAAC,EAAE,CAEhC,CAEA,KAAO,EAAU,MAAM,CAAG,EAAK,KAAK,CAAC,EAAI,CAAC,MAAM,EAC9C,EAAU,IAAI,CAAC,GAGjB,GAAI,CAAC,EACH,CAAA,IAAK,IAAI,EAAI,EAAG,EAAI,EAAK,KAAK,CAAC,EAAI,CAAC,MAAM,CAAE,IAC1C,GAAI,EAAK,KAAK,CAAC,EAAI,CAAC,EAAE,GAAK,CAAS,CAAC,EAAE,CAAE,CACvC,EAAQ,CAAA,EACR,KACF,CAAA,CAIJ,EAAK,KAAK,CAAC,EAAI,CAAG,CACpB,EApCA,GA4CA,OANI,IACF,IAAI,CAAC,wBAAwB,GAC7B,IAAI,CAAC,WAAW,GAChB,IAAI,CAAC,SAAS,IAGT,CACT,C,E,CAEA,IAAA,YAAA,MAAA,WAGE,IAAK,I,E,I,CAFD,EAAQ,CAAA,EAEH,EAAM,EAAG,EAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAE,KAA3C,A,S,C,EAME,IAAK,IALC,EAAa,EAAK,KAAK,CAAC,EAAI,CAAC,MAAM,CAAC,SAAC,CAA3C,EAAmD,OAAA,AAAQ,IAAR,C,GAE7C,EAAY,EAAE,CAChB,EAAO,CAAA,EAEF,EAAI,EAAG,EAAI,EAAW,MAAM,CAAE,IAAK,CAC1C,GAAI,EAAM,CACR,EAAO,CAAA,EACP,QACF,CAEI,CAAU,CAAC,EAAE,GAAK,CAAU,CAAC,EAAI,EAAE,EACrC,EAAU,IAAI,CAAC,AAAgB,EAAhB,CAAU,CAAC,EAAE,EAC5B,EAAK,QAAQ,CAAC,CAAA,EAAM,AAAgB,EAAhB,CAAU,CAAC,EAAE,EACjC,EAAO,CAAA,EACP,EAAQ,CAAA,GAER,EAAU,IAAI,CAAC,CAAU,CAAC,EAAE,CAEhC,CAEA,KAAO,EAAU,MAAM,CAAG,EAAK,KAAK,CAAC,EAAI,CAAC,MAAM,EAC9C,EAAU,OAAO,CAAC,GAGpB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAK,KAAK,CAAC,EAAI,CAAC,MAAM,CAAE,IAC1C,GAAI,EAAK,KAAK,CAAC,EAAI,CAAC,EAAE,GAAK,CAAS,CAAC,EAAE,CAAE,CACvC,EAAQ,CAAA,EACR,KACF,CAGF,EAAK,KAAK,CAAC,EAAI,CAAG,CACpB,EAlCA,GA0CA,OANI,IACF,IAAI,CAAC,wBAAwB,GAC7B,IAAI,CAAC,WAAW,GAChB,IAAI,CAAC,SAAS,IAGT,CACT,C,E,CAEA,IAAA,SAAA,MAAA,WAGE,IAAK,IAFD,EAAQ,CAAA,EAEH,EAAM,EAAG,EAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAE,IAAO,CAIhD,IAAK,IAHC,EAAY,IAAI,CAAC,YAAY,CAAC,GAC9B,EAAW,AAAI,MAAM,EAAU,MAAM,EAAE,IAAI,CAAC,CAAA,GAEzC,EAAI,EAAG,EAAI,EAAU,MAAM,CAAG,EAAG,IAEtC,CAAS,CAAC,EAAE,GAAK,CAAS,CAAC,EAAI,EAAE,EACjC,CAAQ,CAAC,EAAE,EACX,CAAQ,CAAC,EAAI,EAAE,GAEf,CAAS,CAAC,EAAE,EAAI,EAChB,EAAU,MAAM,CAAC,EAAI,EAAG,GACxB,EAAQ,CAAA,EACR,CAAQ,CAAC,EAAE,CAAG,CAAA,EACd,IAAI,CAAC,QAAQ,CAAC,EAAO,CAAS,CAAC,EAAE,GAIrC,KAAO,EAAU,MAAM,CAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EACzC,EAAU,IAAI,CAAC,GAGjB,EAAQ,IAAI,CAAC,YAAY,CAAC,EAAK,IAAc,CAC/C,CAQA,OANI,IACF,IAAI,CAAC,wBAAwB,GAC7B,IAAI,CAAC,WAAW,GAChB,IAAI,CAAC,SAAS,IAGT,CACT,C,E,CAEA,IAAA,WAAA,MAAA,WAGE,IAAK,IAFD,EAAQ,CAAA,EAEH,EAAM,EAAG,EAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAE,IAAO,CAIhD,IAAK,IAHC,EAAY,IAAI,CAAC,YAAY,CAAC,GAC9B,EAAW,AAAI,MAAM,EAAU,MAAM,EAAE,IAAI,CAAC,CAAA,GAEzC,EAAI,EAAU,MAAM,CAAG,EAAG,EAAI,EAAG,IAEtC,CAAS,CAAC,EAAE,GAAK,CAAS,CAAC,EAAI,EAAE,EACjC,CAAQ,CAAC,EAAE,EACX,CAAQ,CAAC,EAAI,EAAE,GAEf,CAAS,CAAC,EAAE,EAAI,EAChB,EAAU,MAAM,CAAC,EAAI,EAAG,GACxB,EAAQ,CAAA,EACR,CAAQ,CAAC,EAAE,CAAG,CAAA,EACd,IAAI,CAAC,QAAQ,CAAC,EAAO,CAAS,CAAC,EAAE,GAIrC,KAAO,EAAU,MAAM,CAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EACzC,EAAU,OAAO,CAAC,GAGpB,EAAQ,IAAI,CAAC,YAAY,CAAC,EAAK,IAAc,CAC/C,CAQA,OANI,IACF,IAAI,CAAC,wBAAwB,GAC7B,IAAI,CAAC,WAAW,GAChB,IAAI,CAAC,SAAS,IAGT,CACT,C,E,CAKA,IAAA,WAAA,MAAA,WACE,OAAO,IAAI,CAAC,KAAK,AACnB,C,E,CAEA,IAAA,YAAA,MAAA,WACE,GAAI,AAAe,IAAf,IAAI,CAAC,KAAK,CACZ,IAAI,CAAC,MAAM,CAAG,MACT,CAKL,IAAK,IAJD,EAAe,CAAA,EACf,EAAc,CAAA,EACd,EAAU,CAAA,EAEL,EAAM,EAAG,EAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAE,IACzC,IAAK,IAAI,EAAM,EAAG,EAAM,IAAI,CAAC,KAAK,CAAC,EAAI,CAAC,MAAM,CAAE,IACjB,IAAzB,IAAI,CAAC,KAAK,CAAC,EAAI,CAAC,EAAI,EACtB,CAAA,EAAe,CAAA,CADjB,EAI6B,OAAzB,IAAI,CAAC,KAAK,CAAC,EAAI,CAAC,EAAI,EACtB,CAAA,EAAc,CAAA,CADhB,EAKE,EAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAG,GAC1B,IAAI,CAAC,KAAK,CAAC,EAAI,CAAC,EAAI,GAAK,IAAI,CAAC,KAAK,CAAC,EAAM,EAAE,CAAC,EAAI,EAEjD,CAAA,EAAU,CAAA,CAJZ,EAQE,EAAM,IAAI,CAAC,KAAK,CAAC,EAAI,CAAC,MAAM,CAAG,GAC/B,IAAI,CAAC,KAAK,CAAC,EAAI,CAAC,EAAI,GAAK,IAAI,CAAC,KAAK,CAAC,EAAI,CAAC,EAAM,EAAE,EAEjD,CAAA,EAAU,CAAA,CAJZ,EASA,GACF,IAAI,CAAC,MAAM,CA/WA,MAgXX,IAAI,CAAC,WAAW,IACP,GAAgB,EACzB,IAAI,CAAC,MAAM,CAAG,GAEd,IAAI,CAAC,MAAM,CAAG,EACd,IAAI,CAAC,YAAY,GAErB,CAEA,OAAO,IAAI,CAAC,MAAM,AACpB,C,E,CAEA,IAAA,QAAA,MAAA,WACE,IAAI,CAAC,cAAc,EACrB,C,E,CAEA,IAAA,UAAA,MAAA,WACE,IAAI,CAAC,cAAc,EACrB,C,E,CE3XkB,AAZpB,SAA2B,CAAM,CAAE,CAAK,EACpC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAM,MAAM,CAAE,IAAK,CACnC,IAAI,EAAa,CAAK,CAAC,EAAE,AACzB,CAAA,EAAW,UAAU,CAAG,EAAW,UAAU,EAAI,CAAA,EACjD,EAAW,YAAY,CAAG,CAAA,EAEtB,UAAW,GAAY,CAAA,EAAW,QAAQ,CAAG,CAAA,CAAjD,EAEA,OAAO,cAAc,CAAC,EAAQ,EAAW,GAAG,CAAE,EAClD,CACJ,EAEsC,AFJzB,EEIqC,SAAS,CAAE,GFJhD,C,G,EDJS,KAUtB,WACE,EAAW,SAAS,CAAC,MAAM,CAAC,SAC9B,EAEA,WACE,EAAY,SAAS,CAAC,MAAM,CAAC,SAC/B,GAdM,EAAc,SAAS,aAAa,CAAC,UACrC,EAAQ,SAAS,gBAAgB,CAAC,eAClC,EAAQ,SAAS,aAAa,CAAC,eAC/B,EAAgB,SAAS,aAAa,CAAC,gBACvC,EAAe,SAAS,aAAa,CAAC,kBACtC,EAAa,SAAS,aAAa,CAAC,gBACpC,EAAc,SAAS,aAAa,CAAC,iBAc3C,SAAS,IACP,EAAY,SAAS,CAAC,GAAG,CAAC,SAC5B,CAEA,SAAS,IACP,EAAW,SAAS,CAAC,GAAG,CAAC,SAC3B,CAeA,SAAS,IACP,IAAM,EAAY,aAAa,OAAO,CAAC,cAAgB,CAEvD,CAAA,EAAc,WAAW,CAAG,CAC9B,CAEA,IAEA,EAAK,QAAQ,CAAG,SAAU,CAAK,CAAE,CAAK,EACpC,GAAI,GAAS,EAAQ,EAAG,KAtBL,EAIF,EACX,CAkBJ,CAAA,IAAI,CAAC,KAAK,EAAI,EAvBG,EAwBL,IAAI,CAAC,KAAK,CAvBxB,EAAM,WAAW,CAAG,EAGH,EAqBL,IAAI,CAAC,KAAK,EApBhB,EAAgB,aAAa,OAAO,CAAC,gBAErB,CAAA,EAAS,CAAA,IAC7B,aAAa,OAAO,CAAC,YAAa,GAClC,IAiBF,CACF,EAEA,EAAY,gBAAgB,CAAC,QAAS,WACpC,EAAY,WAAW,CAAG,UAC1B,EAAY,SAAS,CAAC,MAAM,CAAC,SAC7B,EAAY,SAAS,CAAC,GAAG,CAAC,WAC1B,EAAM,WAAW,CAAG,IAEpB,EAAM,OAAO,CAAC,SAAC,CAAf,EACE,EAAK,SAAS,CAAC,MAAM,CAAC,SACxB,GAEI,CAAA,ACpEa,QDoEb,EAAK,MAAM,EAAY,EAAK,MAAM,GAAK,CAAG,IAC5C,IACA,KAGF,EAAK,KAAK,GAvDV,EAAa,SAAS,CAAC,GAAG,CAAC,UAyD3B,IACA,IACA,GACF,GAEA,SAAS,gBAAgB,CAAC,UAAW,SAAC,CAAtC,EACE,OAAQ,EAAE,GAAG,EACX,IAAK,YACH,EAAK,QAAQ,GACb,KACF,KAAK,aACH,EAAK,SAAS,GACd,KACF,KAAK,UACH,EAAK,MAAM,GACX,KACF,KAAK,YACH,EAAK,QAAQ,EAEjB,CACF,E","sources":["","src/scripts/main.js","src/modules/Game.class.js","node_modules/@swc/helpers/esm/_class_call_check.js","node_modules/@swc/helpers/esm/_create_class.js"],"sourcesContent":["(function () {\nfunction $8713978b2328d32b$export$71511d61b312f219(instance, Constructor) {\n if (!(instance instanceof Constructor)) throw new TypeError(\"Cannot call a class as a function\");\n}\n\n\nfunction $4fc75ccb937ab1df$var$_defineProperties(target, props) {\n for(var i = 0; i < props.length; i++){\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n}\nfunction $4fc75ccb937ab1df$export$71511d61b312f219(Constructor, protoProps, staticProps) {\n if (protoProps) $4fc75ccb937ab1df$var$_defineProperties(Constructor.prototype, protoProps);\n if (staticProps) $4fc75ccb937ab1df$var$_defineProperties(Constructor, staticProps);\n return Constructor;\n}\n\n\n\"use strict\";\nvar $3d28d7f1aac198f5$var$IDLE = \"idle\";\nvar $3d28d7f1aac198f5$var$PLAYING = \"playing\";\nvar $3d28d7f1aac198f5$export$eb2b832b8b9fda85 = \"win\";\nvar $3d28d7f1aac198f5$export$43a03cf66b318012 = \"lose\";\nvar $3d28d7f1aac198f5$export$985739bfa5723e08 = /*#__PURE__*/ function() {\n function Game(initialState, winCallback, loseCallback) {\n (0, $8713978b2328d32b$export$71511d61b312f219)(this, Game);\n this.board = initialState || [\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ]\n ];\n this.score = 0;\n this.status = $3d28d7f1aac198f5$var$IDLE;\n this.isStarted = false;\n this.winCallback = winCallback;\n this.loseCallback = loseCallback;\n }\n (0, $4fc75ccb937ab1df$export$71511d61b312f219)(Game, [\n {\n key: \"moveTile\",\n value: function moveTile(fromCell, toCell) {\n var fromCellRect = fromCell.getBoundingClientRect();\n var toCellRect = toCell.getBoundingClientRect();\n var xOffset = toCellRect.left - fromCellRect.left;\n var yOffset = toCellRect.top - fromCellRect.top;\n fromCell.style.setProperty(\"--x-offset\", \"\".concat(xOffset, \"px\"));\n fromCell.style.setProperty(\"--y-offset\", \"\".concat(yOffset, \"px\"));\n fromCell.classList.add(\"moving\");\n }\n },\n {\n key: \"updateBoard\",\n value: function updateBoard() {\n var cells = document.querySelectorAll(\".field-cell\");\n var cellIndex = 0;\n for(var row = 0; row < this.board.length; row++)for(var col = 0; col < this.board[row].length; col++){\n var cell = cells[cellIndex++];\n var value = this.board[row][col];\n var previousValue = cell.textContent;\n cell.classList.remove(\"field-cell--\".concat(previousValue));\n if (value === 0) cell.textContent = \"\";\n else {\n cell.classList.add(\"field-cell--\".concat(value));\n cell.textContent = value;\n }\n }\n }\n },\n {\n key: \"addRandomTile\",\n value: function addRandomTile() {\n var emptyCells = [];\n for(var row = 0; row < 4; row++){\n for(var col = 0; col < 4; col++)if (this.board[row][col] === 0) emptyCells.push({\n row: row,\n col: col\n });\n }\n if (emptyCells.length > 0) {\n var _emptyCells_Math_floor = emptyCells[Math.floor(Math.random() * emptyCells.length)], row1 = _emptyCells_Math_floor.row, col1 = _emptyCells_Math_floor.col;\n if (this.score === 0) this.board[row1][col1] = 2;\n this.updateBoard();\n }\n }\n },\n {\n key: \"addRandomCellAfterMoving\",\n value: function addRandomCellAfterMoving() {\n var emptyCells = [];\n for(var row = 0; row < 4; row++){\n for(var col = 0; col < 4; col++)if (this.board[row][col] === 0) emptyCells.push({\n row: row,\n col: col\n });\n }\n if (emptyCells.length > 0) {\n var _emptyCells_Math_floor = emptyCells[Math.floor(Math.random() * emptyCells.length)], row1 = _emptyCells_Math_floor.row, col1 = _emptyCells_Math_floor.col;\n this.board[row1][col1] = Math.random() < 0.9 ? 2 : 4;\n this.updateBoard();\n }\n }\n },\n {\n key: \"createColumn\",\n value: function createColumn(col) {\n var newColumn = [];\n for(var row = 0; row < this.board.length; row++)if (this.board[row][col] !== 0) newColumn.push(this.board[row][col]);\n return newColumn;\n }\n },\n {\n key: \"updateColumn\",\n value: function updateColumn(col, newColumn) {\n var moved = false;\n for(var row = 0; row < this.board.length; row++)if (this.board[row][col] !== newColumn[row]) {\n this.board[row][col] = newColumn[row];\n moved = true;\n }\n return moved;\n }\n },\n {\n key: \"resetGameStart\",\n value: function resetGameStart() {\n this.score = 0;\n this.status = $3d28d7f1aac198f5$var$PLAYING;\n this.board = [\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ]\n ];\n this.addRandomTile();\n this.addRandomTile();\n }\n },\n {\n key: \"mergeTitles\",\n value: function mergeTitles(newRow, canMerge) {\n var mergedThisMove = [];\n for(var i = 0; i < newRow.length - 1; i++)if (newRow[i] === newRow[i + 1]) {\n newRow[i] *= 2;\n newRow.splice(i + 1, 1);\n canMerge[i] = false;\n mergedThisMove.push(i);\n }\n return mergedThisMove;\n }\n },\n {\n key: \"moveLeft\",\n value: function moveLeft() {\n var _this = this, _loop = function(row) {\n var currentRow = _this.board[row].filter(function(val) {\n return val !== 0;\n });\n var mergedRow = [];\n var skip = false;\n for(var i = 0; i < currentRow.length; i++){\n if (skip) {\n skip = false;\n continue;\n }\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n _this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else mergedRow.push(currentRow[i]);\n }\n while(mergedRow.length < _this.board[row].length)mergedRow.push(0);\n if (!moved) {\n for(var i1 = 0; i1 < _this.board[row].length; i1++)if (_this.board[row][i1] !== mergedRow[i1]) {\n moved = true;\n break;\n }\n }\n _this.board[row] = mergedRow;\n };\n var moved = false;\n for(var row = 0; row < this.board.length; row++)_loop(row);\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n },\n {\n key: \"moveRight\",\n value: function moveRight() {\n var _this = this, _loop = function(row) {\n var currentRow = _this.board[row].filter(function(val) {\n return val !== 0;\n });\n var mergedRow = [];\n var skip = false;\n for(var i = 0; i < currentRow.length; i++){\n if (skip) {\n skip = false;\n continue;\n }\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n _this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else mergedRow.push(currentRow[i]);\n }\n while(mergedRow.length < _this.board[row].length)mergedRow.unshift(0);\n for(var i1 = 0; i1 < _this.board[row].length; i1++)if (_this.board[row][i1] !== mergedRow[i1]) {\n moved = true;\n break;\n }\n _this.board[row] = mergedRow;\n };\n var moved = false;\n for(var row = 0; row < this.board.length; row++)_loop(row);\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n },\n {\n key: \"moveUp\",\n value: function moveUp() {\n var moved = false;\n for(var col = 0; col < this.board.length; col++){\n var newColumn = this.createColumn(col);\n var canMerge = new Array(newColumn.length).fill(true);\n for(var i = 0; i < newColumn.length - 1; i++)if (newColumn[i] === newColumn[i + 1] && canMerge[i] && canMerge[i + 1]) {\n newColumn[i] *= 2;\n newColumn.splice(i + 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n while(newColumn.length < this.board.length)newColumn.push(0);\n moved = this.updateColumn(col, newColumn) || moved;\n }\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n },\n {\n key: \"moveDown\",\n value: function moveDown() {\n var moved = false;\n for(var col = 0; col < this.board.length; col++){\n var newColumn = this.createColumn(col);\n var canMerge = new Array(newColumn.length).fill(true);\n for(var i = newColumn.length - 1; i > 0; i--)if (newColumn[i] === newColumn[i - 1] && canMerge[i] && canMerge[i - 1]) {\n newColumn[i] *= 2;\n newColumn.splice(i - 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n while(newColumn.length < this.board.length)newColumn.unshift(0);\n moved = this.updateColumn(col, newColumn) || moved;\n }\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n },\n {\n /**\n * @returns {number[][]}\n */ key: \"getState\",\n value: function getState() {\n return this.board;\n }\n },\n {\n key: \"getStatus\",\n value: function getStatus() {\n if (this.score === 0) this.status = $3d28d7f1aac198f5$var$IDLE;\n else {\n var hasEmptyCell = false;\n var has2048Cell = false;\n var canMove = false;\n for(var row = 0; row < this.board.length; row++)for(var col = 0; col < this.board[row].length; col++){\n if (this.board[row][col] === 0) hasEmptyCell = true;\n if (this.board[row][col] === 2048) has2048Cell = true;\n if (row < this.board.length - 1 && this.board[row][col] === this.board[row + 1][col]) canMove = true;\n if (col < this.board[row].length - 1 && this.board[row][col] === this.board[row][col + 1]) canMove = true;\n }\n if (has2048Cell) {\n this.status = $3d28d7f1aac198f5$export$eb2b832b8b9fda85;\n this.winCallback();\n } else if (hasEmptyCell || canMove) this.status = $3d28d7f1aac198f5$var$PLAYING;\n else {\n this.status = $3d28d7f1aac198f5$export$43a03cf66b318012;\n this.loseCallback();\n }\n }\n return this.status;\n }\n },\n {\n key: \"start\",\n value: function start() {\n this.resetGameStart();\n }\n },\n {\n key: \"restart\",\n value: function restart() {\n this.resetGameStart();\n }\n }\n ]);\n return Game;\n}();\n\n\n\"use strict\";\nvar $197cd56b15c33885$var$game = new (0, $3d28d7f1aac198f5$export$985739bfa5723e08)(null, $197cd56b15c33885$var$showWinMessage, $197cd56b15c33885$var$showLoseMessage);\nvar $197cd56b15c33885$var$startButton = document.querySelector(\".start\");\nvar $197cd56b15c33885$var$cells = document.querySelectorAll(\".field-cell\");\nvar $197cd56b15c33885$var$score = document.querySelector(\".game-score\");\nvar $197cd56b15c33885$var$recordElement = document.querySelector(\".best__score\");\nvar $197cd56b15c33885$var$messageStart = document.querySelector(\".message-start\");\nvar $197cd56b15c33885$var$messageWin = document.querySelector(\".message-win\");\nvar $197cd56b15c33885$var$messageLose = document.querySelector(\".message-lose\");\nfunction $197cd56b15c33885$var$showWinMessage() {\n $197cd56b15c33885$var$messageWin.classList.remove(\"hidden\");\n}\nfunction $197cd56b15c33885$var$showLoseMessage() {\n $197cd56b15c33885$var$messageLose.classList.remove(\"hidden\");\n}\nfunction $197cd56b15c33885$var$hideMessageStart() {\n $197cd56b15c33885$var$messageStart.classList.add(\"hidden\");\n}\nfunction $197cd56b15c33885$var$hideMessageLose() {\n $197cd56b15c33885$var$messageLose.classList.add(\"hidden\");\n}\nfunction $197cd56b15c33885$var$hideMessageWin() {\n $197cd56b15c33885$var$messageWin.classList.add(\"hidden\");\n}\nfunction $197cd56b15c33885$var$updateScore(value) {\n $197cd56b15c33885$var$score.textContent = value;\n}\nfunction $197cd56b15c33885$var$saveScore(sscore) {\n var currentRecord = localStorage.getItem(\"highScore\");\n if (!currentRecord || sscore > currentRecord) {\n localStorage.setItem(\"highScore\", sscore);\n $197cd56b15c33885$var$displayRecord();\n }\n}\nfunction $197cd56b15c33885$var$displayRecord() {\n var highScore = localStorage.getItem(\"highScore\") || 0;\n $197cd56b15c33885$var$recordElement.textContent = highScore;\n}\n$197cd56b15c33885$var$displayRecord();\n$197cd56b15c33885$var$game.getScore = function(moved, value) {\n if (moved && value > 0) {\n this.score += value;\n $197cd56b15c33885$var$updateScore(this.score);\n $197cd56b15c33885$var$saveScore(this.score);\n }\n};\n$197cd56b15c33885$var$startButton.addEventListener(\"click\", function() {\n $197cd56b15c33885$var$startButton.textContent = \"Restart\";\n $197cd56b15c33885$var$startButton.classList.remove(\"start\");\n $197cd56b15c33885$var$startButton.classList.add(\"restart\");\n $197cd56b15c33885$var$score.textContent = \"0\";\n $197cd56b15c33885$var$cells.forEach(function(cell) {\n cell.classList.remove(\"hidden\");\n });\n if ($197cd56b15c33885$var$game.status === (0, $3d28d7f1aac198f5$export$eb2b832b8b9fda85) || $197cd56b15c33885$var$game.status === (0, $3d28d7f1aac198f5$export$43a03cf66b318012)) {\n $197cd56b15c33885$var$hideMessageWin();\n $197cd56b15c33885$var$hideMessageLose();\n }\n $197cd56b15c33885$var$game.start();\n $197cd56b15c33885$var$hideMessageStart();\n $197cd56b15c33885$var$hideMessageLose();\n $197cd56b15c33885$var$hideMessageWin();\n $197cd56b15c33885$var$displayRecord();\n});\ndocument.addEventListener(\"keydown\", function(e) {\n switch(e.key){\n case \"ArrowLeft\":\n $197cd56b15c33885$var$game.moveLeft();\n break;\n case \"ArrowRight\":\n $197cd56b15c33885$var$game.moveRight();\n break;\n case \"ArrowUp\":\n $197cd56b15c33885$var$game.moveUp();\n break;\n case \"ArrowDown\":\n $197cd56b15c33885$var$game.moveDown();\n break;\n }\n});\n\n})();\n//# sourceMappingURL=index.0d5498be.js.map\n","'use strict';\n\nimport { WIN, LOSE, Game } from '../modules/Game.class';\n\nconst game = new Game(null, showWinMessage, showLoseMessage);\n\nconst startButton = document.querySelector('.start');\nconst cells = document.querySelectorAll('.field-cell');\nconst score = document.querySelector('.game-score');\nconst recordElement = document.querySelector('.best__score');\nconst messageStart = document.querySelector('.message-start');\nconst messageWin = document.querySelector('.message-win');\nconst messageLose = document.querySelector('.message-lose');\n\nfunction showWinMessage() {\n messageWin.classList.remove('hidden');\n}\n\nfunction showLoseMessage() {\n messageLose.classList.remove('hidden');\n}\n\nfunction hideMessageStart() {\n messageStart.classList.add('hidden');\n}\n\nfunction hideMessageLose() {\n messageLose.classList.add('hidden');\n}\n\nfunction hideMessageWin() {\n messageWin.classList.add('hidden');\n}\n\nfunction updateScore(value) {\n score.textContent = value;\n}\n\nfunction saveScore(sscore) {\n const currentRecord = localStorage.getItem('highScore');\n\n if (!currentRecord || sscore > currentRecord) {\n localStorage.setItem('highScore', sscore);\n displayRecord();\n }\n}\n\nfunction displayRecord() {\n const highScore = localStorage.getItem('highScore') || 0;\n\n recordElement.textContent = highScore;\n}\n\ndisplayRecord();\n\ngame.getScore = function (moved, value) {\n if (moved && value > 0) {\n this.score += value;\n updateScore(this.score);\n saveScore(this.score);\n }\n};\n\nstartButton.addEventListener('click', () => {\n startButton.textContent = 'Restart';\n startButton.classList.remove('start');\n startButton.classList.add('restart');\n score.textContent = '0';\n\n cells.forEach((cell) => {\n cell.classList.remove('hidden');\n });\n\n if (game.status === WIN || game.status === LOSE) {\n hideMessageWin();\n hideMessageLose();\n }\n\n game.start();\n hideMessageStart();\n hideMessageLose();\n hideMessageWin();\n displayRecord();\n});\n\ndocument.addEventListener('keydown', (e) => {\n switch (e.key) {\n case 'ArrowLeft':\n game.moveLeft();\n break;\n case 'ArrowRight':\n game.moveRight();\n break;\n case 'ArrowUp':\n game.moveUp();\n break;\n case 'ArrowDown':\n game.moveDown();\n break;\n }\n});\n","'use strict';\n\nconst IDLE = 'idle';\nconst PLAYING = 'playing';\n\nexport const WIN = 'win';\nexport const LOSE = 'lose';\n\nexport class Game {\n constructor(initialState, winCallback, loseCallback) {\n this.board = initialState || [\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n ];\n\n this.score = 0;\n\n this.status = IDLE;\n this.isStarted = false;\n this.winCallback = winCallback;\n this.loseCallback = loseCallback;\n }\n\n moveTile(fromCell, toCell) {\n const fromCellRect = fromCell.getBoundingClientRect();\n const toCellRect = toCell.getBoundingClientRect();\n\n const xOffset = toCellRect.left - fromCellRect.left;\n const yOffset = toCellRect.top - fromCellRect.top;\n\n fromCell.style.setProperty('--x-offset', `${xOffset}px`);\n fromCell.style.setProperty('--y-offset', `${yOffset}px`);\n\n fromCell.classList.add('moving');\n }\n\n updateBoard() {\n const cells = document.querySelectorAll('.field-cell');\n\n let cellIndex = 0;\n\n for (let row = 0; row < this.board.length; row++) {\n for (let col = 0; col < this.board[row].length; col++) {\n const cell = cells[cellIndex++];\n const value = this.board[row][col];\n const previousValue = cell.textContent;\n\n cell.classList.remove(`field-cell--${previousValue}`);\n\n if (value === 0) {\n cell.textContent = '';\n } else {\n cell.classList.add(`field-cell--${value}`);\n cell.textContent = value;\n }\n }\n }\n }\n\n addRandomTile() {\n const emptyCells = [];\n\n for (let row = 0; row < 4; row++) {\n for (let col = 0; col < 4; col++) {\n if (this.board[row][col] === 0) {\n emptyCells.push({ row, col });\n }\n }\n }\n\n if (emptyCells.length > 0) {\n const { row, col } =\n emptyCells[Math.floor(Math.random() * emptyCells.length)];\n\n if (this.score === 0) {\n this.board[row][col] = 2;\n }\n this.updateBoard();\n }\n }\n\n addRandomCellAfterMoving() {\n const emptyCells = [];\n\n for (let row = 0; row < 4; row++) {\n for (let col = 0; col < 4; col++) {\n if (this.board[row][col] === 0) {\n emptyCells.push({ row, col });\n }\n }\n }\n\n if (emptyCells.length > 0) {\n const { row, col } =\n emptyCells[Math.floor(Math.random() * emptyCells.length)];\n\n this.board[row][col] = Math.random() < 0.9 ? 2 : 4;\n this.updateBoard();\n }\n }\n\n createColumn(col) {\n const newColumn = [];\n\n for (let row = 0; row < this.board.length; row++) {\n if (this.board[row][col] !== 0) {\n newColumn.push(this.board[row][col]);\n }\n }\n\n return newColumn;\n }\n\n updateColumn(col, newColumn) {\n let moved = false;\n\n for (let row = 0; row < this.board.length; row++) {\n if (this.board[row][col] !== newColumn[row]) {\n this.board[row][col] = newColumn[row];\n moved = true;\n }\n }\n\n return moved;\n }\n\n resetGameStart() {\n this.score = 0;\n this.status = PLAYING;\n\n this.board = [\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n ];\n\n this.addRandomTile();\n this.addRandomTile();\n }\n\n mergeTitles(newRow, canMerge) {\n const mergedThisMove = [];\n\n for (let i = 0; i < newRow.length - 1; i++) {\n if (newRow[i] === newRow[i + 1]) {\n newRow[i] *= 2;\n newRow.splice(i + 1, 1);\n canMerge[i] = false;\n mergedThisMove.push(i);\n }\n }\n\n return mergedThisMove;\n }\n\n moveLeft() {\n let moved = false;\n\n for (let row = 0; row < this.board.length; row++) {\n const currentRow = this.board[row].filter((val) => val !== 0);\n const mergedRow = [];\n\n let skip = false;\n\n for (let i = 0; i < currentRow.length; i++) {\n if (skip) {\n skip = false;\n continue;\n }\n\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else {\n mergedRow.push(currentRow[i]);\n }\n }\n\n while (mergedRow.length < this.board[row].length) {\n mergedRow.push(0);\n }\n\n if (!moved) {\n for (let i = 0; i < this.board[row].length; i++) {\n if (this.board[row][i] !== mergedRow[i]) {\n moved = true;\n break;\n }\n }\n }\n\n this.board[row] = mergedRow;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n moveRight() {\n let moved = false;\n\n for (let row = 0; row < this.board.length; row++) {\n const currentRow = this.board[row].filter((val) => val !== 0);\n\n const mergedRow = [];\n let skip = false;\n\n for (let i = 0; i < currentRow.length; i++) {\n if (skip) {\n skip = false;\n continue;\n }\n\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else {\n mergedRow.push(currentRow[i]);\n }\n }\n\n while (mergedRow.length < this.board[row].length) {\n mergedRow.unshift(0);\n }\n\n for (let i = 0; i < this.board[row].length; i++) {\n if (this.board[row][i] !== mergedRow[i]) {\n moved = true;\n break;\n }\n }\n\n this.board[row] = mergedRow;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n moveUp() {\n let moved = false;\n\n for (let col = 0; col < this.board.length; col++) {\n const newColumn = this.createColumn(col);\n const canMerge = new Array(newColumn.length).fill(true);\n\n for (let i = 0; i < newColumn.length - 1; i++) {\n if (\n newColumn[i] === newColumn[i + 1] &&\n canMerge[i] &&\n canMerge[i + 1]\n ) {\n newColumn[i] *= 2;\n newColumn.splice(i + 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n }\n\n while (newColumn.length < this.board.length) {\n newColumn.push(0);\n }\n\n moved = this.updateColumn(col, newColumn) || moved;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n moveDown() {\n let moved = false;\n\n for (let col = 0; col < this.board.length; col++) {\n const newColumn = this.createColumn(col);\n const canMerge = new Array(newColumn.length).fill(true);\n\n for (let i = newColumn.length - 1; i > 0; i--) {\n if (\n newColumn[i] === newColumn[i - 1] &&\n canMerge[i] &&\n canMerge[i - 1]\n ) {\n newColumn[i] *= 2;\n newColumn.splice(i - 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n }\n\n while (newColumn.length < this.board.length) {\n newColumn.unshift(0);\n }\n\n moved = this.updateColumn(col, newColumn) || moved;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n /**\n * @returns {number[][]}\n */\n getState() {\n return this.board;\n }\n\n getStatus() {\n if (this.score === 0) {\n this.status = IDLE;\n } else {\n let hasEmptyCell = false;\n let has2048Cell = false;\n let canMove = false;\n\n for (let row = 0; row < this.board.length; row++) {\n for (let col = 0; col < this.board[row].length; col++) {\n if (this.board[row][col] === 0) {\n hasEmptyCell = true;\n }\n\n if (this.board[row][col] === 2048) {\n has2048Cell = true;\n }\n\n if (\n row < this.board.length - 1 &&\n this.board[row][col] === this.board[row + 1][col]\n ) {\n canMove = true;\n }\n\n if (\n col < this.board[row].length - 1 &&\n this.board[row][col] === this.board[row][col + 1]\n ) {\n canMove = true;\n }\n }\n }\n\n if (has2048Cell) {\n this.status = WIN;\n this.winCallback();\n } else if (hasEmptyCell || canMove) {\n this.status = PLAYING;\n } else {\n this.status = LOSE;\n this.loseCallback();\n }\n }\n\n return this.status;\n }\n\n start() {\n this.resetGameStart();\n }\n\n restart() {\n this.resetGameStart();\n }\n}\n","function _class_call_check(instance, Constructor) {\n if (!(instance instanceof Constructor)) throw new TypeError(\"Cannot call a class as a function\");\n}\nexport { _class_call_check as _ };\n","function _defineProperties(target, props) {\n for (var i = 0; i < props.length; i++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n\n if (\"value\" in descriptor) descriptor.writable = true;\n\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n}\nfunction _create_class(Constructor, protoProps, staticProps) {\n if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n if (staticProps) _defineProperties(Constructor, staticProps);\n\n return Constructor;\n}\nexport { _create_class as _ };\n"],"names":["$3d28d7f1aac198f5$var$IDLE","$3d28d7f1aac198f5$var$PLAYING","$3d28d7f1aac198f5$export$43a03cf66b318012","$197cd56b15c33885$var$game","protoProps","Game","initialState","winCallback","loseCallback","instance","Constructor","TypeError","board","score","status","isStarted","key","value","fromCell","toCell","fromCellRect","getBoundingClientRect","toCellRect","xOffset","left","yOffset","top","style","setProperty","concat","classList","add","cells","document","querySelectorAll","cellIndex","row","length","col","cell","previousValue","textContent","remove","emptyCells","push","_emptyCells_Math_floor","Math","floor","random","row1","col1","updateBoard","newColumn","moved","addRandomTile","newRow","canMerge","mergedThisMove","i","splice","_this","_loop","currentRow","filter","val","mergedRow","skip","getScore","i1","addRandomCellAfterMoving","getStatus","unshift","createColumn","Array","fill","updateColumn","hasEmptyCell","has2048Cell","canMove","resetGameStart","$4fc75ccb937ab1df$var$_defineProperties","target","props","descriptor","enumerable","configurable","writable","Object","defineProperty","prototype","$197cd56b15c33885$var$messageWin","$197cd56b15c33885$var$messageLose","$197cd56b15c33885$var$startButton","querySelector","$197cd56b15c33885$var$cells","$197cd56b15c33885$var$score","$197cd56b15c33885$var$recordElement","$197cd56b15c33885$var$messageStart","$197cd56b15c33885$var$hideMessageLose","$197cd56b15c33885$var$hideMessageWin","$197cd56b15c33885$var$displayRecord","highScore","localStorage","getItem","sscore","currentRecord","setItem","addEventListener","forEach","start","e","moveLeft","moveRight","moveUp","moveDown"],"version":3,"file":"index.0d5498be.js.map"} \ No newline at end of file diff --git a/dist/index.1ca8bb72.js b/dist/index.1ca8bb72.js deleted file mode 100644 index 15f89ab8b..000000000 --- a/dist/index.1ca8bb72.js +++ /dev/null @@ -1,2 +0,0 @@ -!function(){var t="idle",e="playing",o="lose",r=new(function(){var r;function a(e,o,r){!function(t,e){if(!(t instanceof e))throw TypeError("Cannot call a class as a function")}(this,a),this.board=e||[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],this.score=0,this.status=t,this.isStarted=!1,this.winCallback=o,this.loseCallback=r}return r=[{key:"moveTile",value:function(t,e){var o=t.getBoundingClientRect(),r=e.getBoundingClientRect(),a=r.left-o.left,n=r.top-o.top;t.style.setProperty("--x-offset","".concat(a,"px")),t.style.setProperty("--y-offset","".concat(n,"px")),t.classList.add("moving")}},{key:"updateBoard",value:function(){for(var t=document.querySelectorAll(".field-cell"),e=0,o=0;o0){var r=t[Math.floor(Math.random()*t.length)],a=r.row,n=r.col;0===this.score&&(this.board[a][n]=2),this.updateBoard()}}},{key:"addRandomCellAfterMoving",value:function(){for(var t=[],e=0;e<4;e++)for(var o=0;o<4;o++)0===this.board[e][o]&&t.push({row:e,col:o});if(t.length>0){var r=t[Math.floor(Math.random()*t.length)],a=r.row,n=r.col;this.board[a][n]=.9>Math.random()?2:4,this.updateBoard()}}},{key:"createColumn",value:function(t){for(var e=[],o=0;o0;a--)o[a]===o[a-1]&&r[a]&&r[a-1]&&(o[a]*=2,o.splice(a-1,1),t=!0,r[a]=!1,this.getScore(t,o[a]));for(;o.length0){var o,r,a;this.score+=e,o=this.score,s.textContent=o,r=this.score,(a=localStorage.getItem("highScore"))&&!(r>a)||(localStorage.setItem("highScore",r),u())}},a.addEventListener("click",function(){a.textContent="Restart",a.classList.remove("start"),a.classList.add("restart"),s.textContent="0",n.forEach(function(t){t.classList.remove("hidden")}),("win"===r.status||r.status===o)&&h(),r.start(),h(),u()}),document.addEventListener("keydown",function(t){switch(t.key){case"ArrowLeft":r.moveLeft();break;case"ArrowRight":r.moveRight();break;case"ArrowUp":r.moveUp();break;case"ArrowDown":r.moveDown()}})}(); -//# sourceMappingURL=index.1ca8bb72.js.map diff --git a/dist/index.1ca8bb72.js.map b/dist/index.1ca8bb72.js.map deleted file mode 100644 index e0d3366b6..000000000 --- a/dist/index.1ca8bb72.js.map +++ /dev/null @@ -1 +0,0 @@ -{"mappings":"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","sources":["","src/scripts/main.js","src/modules/Game.class.js","node_modules/@swc/helpers/esm/_class_call_check.js","node_modules/@swc/helpers/esm/_create_class.js"],"sourcesContent":["(function () {\nfunction $8713978b2328d32b$export$71511d61b312f219(instance, Constructor) {\n if (!(instance instanceof Constructor)) throw new TypeError(\"Cannot call a class as a function\");\n}\n\n\nfunction $4fc75ccb937ab1df$var$_defineProperties(target, props) {\n for(var i = 0; i < props.length; i++){\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n}\nfunction $4fc75ccb937ab1df$export$71511d61b312f219(Constructor, protoProps, staticProps) {\n if (protoProps) $4fc75ccb937ab1df$var$_defineProperties(Constructor.prototype, protoProps);\n if (staticProps) $4fc75ccb937ab1df$var$_defineProperties(Constructor, staticProps);\n return Constructor;\n}\n\n\n\"use strict\";\nvar $3d28d7f1aac198f5$var$IDLE = \"idle\";\nvar $3d28d7f1aac198f5$var$PLAYING = \"playing\";\nvar $3d28d7f1aac198f5$export$eb2b832b8b9fda85 = \"win\";\nvar $3d28d7f1aac198f5$export$43a03cf66b318012 = \"lose\";\nvar $3d28d7f1aac198f5$export$985739bfa5723e08 = /*#__PURE__*/ function() {\n function Game(initialState, winCallback, loseCallback) {\n (0, $8713978b2328d32b$export$71511d61b312f219)(this, Game);\n this.board = initialState || [\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ]\n ];\n this.score = 0;\n this.status = $3d28d7f1aac198f5$var$IDLE;\n this.isStarted = false;\n this.winCallback = winCallback;\n this.loseCallback = loseCallback;\n }\n (0, $4fc75ccb937ab1df$export$71511d61b312f219)(Game, [\n {\n key: \"moveTile\",\n value: function moveTile(fromCell, toCell) {\n var fromCellRect = fromCell.getBoundingClientRect();\n var toCellRect = toCell.getBoundingClientRect();\n var xOffset = toCellRect.left - fromCellRect.left;\n var yOffset = toCellRect.top - fromCellRect.top;\n fromCell.style.setProperty(\"--x-offset\", \"\".concat(xOffset, \"px\"));\n fromCell.style.setProperty(\"--y-offset\", \"\".concat(yOffset, \"px\"));\n fromCell.classList.add(\"moving\");\n }\n },\n {\n key: \"updateBoard\",\n value: function updateBoard() {\n var cells = document.querySelectorAll(\".field-cell\");\n var cellIndex = 0;\n for(var row = 0; row < this.board.length; row++)for(var col = 0; col < this.board[row].length; col++){\n var cell = cells[cellIndex++];\n var value = this.board[row][col];\n var previousValue = cell.textContent;\n cell.classList.remove(\"field-cell--\".concat(previousValue));\n if (value === 0) cell.textContent = \"\";\n else {\n cell.classList.add(\"field-cell--\".concat(value));\n cell.textContent = value;\n }\n }\n }\n },\n {\n key: \"addRandomTile\",\n value: function addRandomTile() {\n var emptyCells = [];\n for(var row = 0; row < 4; row++){\n for(var col = 0; col < 4; col++)if (this.board[row][col] === 0) emptyCells.push({\n row: row,\n col: col\n });\n }\n if (emptyCells.length > 0) {\n var _emptyCells_Math_floor = emptyCells[Math.floor(Math.random() * emptyCells.length)], row1 = _emptyCells_Math_floor.row, col1 = _emptyCells_Math_floor.col;\n if (this.score === 0) this.board[row1][col1] = 2;\n this.updateBoard();\n }\n }\n },\n {\n key: \"addRandomCellAfterMoving\",\n value: function addRandomCellAfterMoving() {\n var emptyCells = [];\n for(var row = 0; row < 4; row++){\n for(var col = 0; col < 4; col++)if (this.board[row][col] === 0) emptyCells.push({\n row: row,\n col: col\n });\n }\n if (emptyCells.length > 0) {\n var _emptyCells_Math_floor = emptyCells[Math.floor(Math.random() * emptyCells.length)], row1 = _emptyCells_Math_floor.row, col1 = _emptyCells_Math_floor.col;\n this.board[row1][col1] = Math.random() < 0.9 ? 2 : 4;\n this.updateBoard();\n }\n }\n },\n {\n key: \"createColumn\",\n value: function createColumn(col) {\n var newColumn = [];\n for(var row = 0; row < this.board.length; row++)if (this.board[row][col] !== 0) newColumn.push(this.board[row][col]);\n return newColumn;\n }\n },\n {\n key: \"updateColumn\",\n value: function updateColumn(col, newColumn) {\n var moved = false;\n for(var row = 0; row < this.board.length; row++)if (this.board[row][col] !== newColumn[row]) {\n this.board[row][col] = newColumn[row];\n moved = true;\n }\n return moved;\n }\n },\n {\n key: \"resetGameStart\",\n value: function resetGameStart() {\n this.score = 0;\n this.status = $3d28d7f1aac198f5$var$PLAYING;\n this.board = [\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ]\n ];\n this.addRandomTile();\n this.addRandomTile();\n }\n },\n {\n key: \"mergeTitles\",\n value: function mergeTitles(newRow, canMerge) {\n var mergedThisMove = [];\n for(var i = 0; i < newRow.length - 1; i++)if (newRow[i] === newRow[i + 1]) {\n newRow[i] *= 2;\n newRow.splice(i + 1, 1);\n canMerge[i] = false;\n mergedThisMove.push(i);\n }\n return mergedThisMove;\n }\n },\n {\n key: \"moveLeft\",\n value: function moveLeft() {\n var _this = this, _loop = function(row) {\n var currentRow = _this.board[row].filter(function(val) {\n return val !== 0;\n });\n var mergedRow = [];\n var skip = false;\n for(var i = 0; i < currentRow.length; i++){\n if (skip) {\n skip = false;\n continue;\n }\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n _this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else mergedRow.push(currentRow[i]);\n }\n while(mergedRow.length < _this.board[row].length)mergedRow.push(0);\n if (!moved) {\n for(var i1 = 0; i1 < _this.board[row].length; i1++)if (_this.board[row][i1] !== mergedRow[i1]) {\n moved = true;\n break;\n }\n }\n _this.board[row] = mergedRow;\n };\n var moved = false;\n for(var row = 0; row < this.board.length; row++)_loop(row);\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n },\n {\n key: \"moveRight\",\n value: function moveRight() {\n var _this = this, _loop = function(row) {\n var currentRow = _this.board[row].filter(function(val) {\n return val !== 0;\n });\n var mergedRow = [];\n var skip = false;\n for(var i = 0; i < currentRow.length; i++){\n if (skip) {\n skip = false;\n continue;\n }\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n _this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else mergedRow.push(currentRow[i]);\n }\n while(mergedRow.length < _this.board[row].length)mergedRow.unshift(0);\n for(var i1 = 0; i1 < _this.board[row].length; i1++)if (_this.board[row][i1] !== mergedRow[i1]) {\n moved = true;\n break;\n }\n _this.board[row] = mergedRow;\n };\n var moved = false;\n for(var row = 0; row < this.board.length; row++)_loop(row);\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n },\n {\n key: \"moveUp\",\n value: function moveUp() {\n var moved = false;\n for(var col = 0; col < this.board.length; col++){\n var newColumn = this.createColumn(col);\n var canMerge = new Array(newColumn.length).fill(true);\n for(var i = 0; i < newColumn.length - 1; i++)if (newColumn[i] === newColumn[i + 1] && canMerge[i] && canMerge[i + 1]) {\n newColumn[i] *= 2;\n newColumn.splice(i + 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n while(newColumn.length < this.board.length)newColumn.push(0);\n moved = this.updateColumn(col, newColumn) || moved;\n }\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n },\n {\n key: \"moveDown\",\n value: function moveDown() {\n var moved = false;\n for(var col = 0; col < this.board.length; col++){\n var newColumn = this.createColumn(col);\n var canMerge = new Array(newColumn.length).fill(true);\n for(var i = newColumn.length - 1; i > 0; i--)if (newColumn[i] === newColumn[i - 1] && canMerge[i] && canMerge[i - 1]) {\n newColumn[i] *= 2;\n newColumn.splice(i - 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n while(newColumn.length < this.board.length)newColumn.unshift(0);\n moved = this.updateColumn(col, newColumn) || moved;\n }\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n },\n {\n /**\n * @returns {number[][]}\n */ key: \"getState\",\n value: function getState() {\n return this.board;\n }\n },\n {\n key: \"getStatus\",\n value: function getStatus() {\n if (this.score === 0) this.status = $3d28d7f1aac198f5$var$IDLE;\n else {\n var hasEmptyCell = false;\n var has2048Cell = false;\n var canMove = false;\n for(var row = 0; row < this.board.length; row++)for(var col = 0; col < this.board[row].length; col++){\n if (this.board[row][col] === 0) hasEmptyCell = true;\n if (this.board[row][col] === 2048) has2048Cell = true;\n if (row < this.board.length - 1 && this.board[row][col] === this.board[row + 1][col]) canMove = true;\n if (col < this.board[row].length - 1 && this.board[row][col] === this.board[row][col + 1]) canMove = true;\n }\n if (has2048Cell) {\n this.status = $3d28d7f1aac198f5$export$eb2b832b8b9fda85;\n this.winCallback();\n } else if (hasEmptyCell || canMove) this.status = $3d28d7f1aac198f5$var$PLAYING;\n else {\n this.status = $3d28d7f1aac198f5$export$43a03cf66b318012;\n this.loseCallback();\n }\n }\n return this.status;\n }\n },\n {\n key: \"start\",\n value: function start() {\n this.resetGameStart();\n }\n },\n {\n key: \"restart\",\n value: function restart() {\n this.resetGameStart();\n }\n }\n ]);\n return Game;\n}();\n\n\n\"use strict\";\nvar $197cd56b15c33885$var$game = new (0, $3d28d7f1aac198f5$export$985739bfa5723e08)(null, $197cd56b15c33885$var$showWinMessage, $197cd56b15c33885$var$showLoseMessage);\nvar $197cd56b15c33885$var$startButton = document.querySelector(\".start\");\nvar $197cd56b15c33885$var$cells = document.querySelectorAll(\".field-cell\");\nvar $197cd56b15c33885$var$score = document.querySelector(\".game-score\");\nvar $197cd56b15c33885$var$recordElement = document.querySelector(\".best__score\");\nvar $197cd56b15c33885$var$messageContainer = document.querySelector(\".message-container\");\nfunction $197cd56b15c33885$var$showWinMessage() {\n $197cd56b15c33885$var$messageContainer.classList.remove(\"hidden\");\n $197cd56b15c33885$var$messageContainer.classList.add(\"message-win\");\n $197cd56b15c33885$var$messageContainer.textContent = \"You Win!\";\n}\nfunction $197cd56b15c33885$var$showLoseMessage() {\n $197cd56b15c33885$var$messageContainer.classList.remove(\"hidden\");\n $197cd56b15c33885$var$messageContainer.classList.add(\"message-lose\");\n $197cd56b15c33885$var$messageContainer.textContent = \"You Lose!\";\n}\nfunction $197cd56b15c33885$var$hideMessage() {\n $197cd56b15c33885$var$messageContainer.classList.add(\"hidden\");\n}\nfunction $197cd56b15c33885$var$updateScore(value) {\n $197cd56b15c33885$var$score.textContent = value;\n}\nfunction $197cd56b15c33885$var$saveScore(sscore) {\n var currentRecord = localStorage.getItem(\"highScore\");\n if (!currentRecord || sscore > currentRecord) {\n localStorage.setItem(\"highScore\", sscore);\n $197cd56b15c33885$var$displayRecord();\n }\n}\nfunction $197cd56b15c33885$var$displayRecord() {\n var highScore = localStorage.getItem(\"highScore\") || 0;\n $197cd56b15c33885$var$recordElement.textContent = highScore;\n}\n$197cd56b15c33885$var$displayRecord();\n$197cd56b15c33885$var$game.getScore = function(moved, value) {\n if (moved && value > 0) {\n this.score += value;\n $197cd56b15c33885$var$updateScore(this.score);\n $197cd56b15c33885$var$saveScore(this.score);\n }\n};\n$197cd56b15c33885$var$startButton.addEventListener(\"click\", function() {\n $197cd56b15c33885$var$startButton.textContent = \"Restart\";\n $197cd56b15c33885$var$startButton.classList.remove(\"start\");\n $197cd56b15c33885$var$startButton.classList.add(\"restart\");\n $197cd56b15c33885$var$score.textContent = \"0\";\n $197cd56b15c33885$var$cells.forEach(function(cell) {\n cell.classList.remove(\"hidden\");\n });\n if ($197cd56b15c33885$var$game.status === (0, $3d28d7f1aac198f5$export$eb2b832b8b9fda85) || $197cd56b15c33885$var$game.status === (0, $3d28d7f1aac198f5$export$43a03cf66b318012)) $197cd56b15c33885$var$hideMessage();\n $197cd56b15c33885$var$game.start();\n $197cd56b15c33885$var$hideMessage();\n $197cd56b15c33885$var$displayRecord();\n});\ndocument.addEventListener(\"keydown\", function(e) {\n switch(e.key){\n case \"ArrowLeft\":\n $197cd56b15c33885$var$game.moveLeft();\n break;\n case \"ArrowRight\":\n $197cd56b15c33885$var$game.moveRight();\n break;\n case \"ArrowUp\":\n $197cd56b15c33885$var$game.moveUp();\n break;\n case \"ArrowDown\":\n $197cd56b15c33885$var$game.moveDown();\n break;\n }\n});\n\n})();\n//# sourceMappingURL=index.1ca8bb72.js.map\n","'use strict';\n\nimport { WIN, LOSE, Game } from '../modules/Game.class';\n\nconst game = new Game(null, showWinMessage, showLoseMessage);\n\nconst startButton = document.querySelector('.start');\nconst cells = document.querySelectorAll('.field-cell');\nconst score = document.querySelector('.game-score');\nconst recordElement = document.querySelector('.best__score');\nconst messageContainer = document.querySelector('.message-container');\n\nfunction showWinMessage() {\n messageContainer.classList.remove('hidden');\n messageContainer.classList.add('message-win');\n messageContainer.textContent = 'You Win!';\n}\n\nfunction showLoseMessage() {\n messageContainer.classList.remove('hidden');\n messageContainer.classList.add('message-lose');\n messageContainer.textContent = 'You Lose!';\n}\n\nfunction hideMessage() {\n messageContainer.classList.add('hidden');\n}\n\nfunction updateScore(value) {\n score.textContent = value;\n}\n\nfunction saveScore(sscore) {\n const currentRecord = localStorage.getItem('highScore');\n\n if (!currentRecord || sscore > currentRecord) {\n localStorage.setItem('highScore', sscore);\n displayRecord();\n }\n}\n\nfunction displayRecord() {\n const highScore = localStorage.getItem('highScore') || 0;\n\n recordElement.textContent = highScore;\n}\n\ndisplayRecord();\n\ngame.getScore = function (moved, value) {\n if (moved && value > 0) {\n this.score += value;\n updateScore(this.score);\n saveScore(this.score);\n }\n};\n\nstartButton.addEventListener('click', () => {\n startButton.textContent = 'Restart';\n startButton.classList.remove('start');\n startButton.classList.add('restart');\n score.textContent = '0';\n\n cells.forEach((cell) => {\n cell.classList.remove('hidden');\n });\n\n if (game.status === WIN || game.status === LOSE) {\n hideMessage();\n }\n\n game.start();\n hideMessage();\n displayRecord();\n});\n\ndocument.addEventListener('keydown', (e) => {\n switch (e.key) {\n case 'ArrowLeft':\n game.moveLeft();\n break;\n case 'ArrowRight':\n game.moveRight();\n break;\n case 'ArrowUp':\n game.moveUp();\n break;\n case 'ArrowDown':\n game.moveDown();\n break;\n }\n});\n","'use strict';\n\nconst IDLE = 'idle';\nconst PLAYING = 'playing';\n\nexport const WIN = 'win';\nexport const LOSE = 'lose';\n\nexport class Game {\n constructor(initialState, winCallback, loseCallback) {\n this.board = initialState || [\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n ];\n\n this.score = 0;\n\n this.status = IDLE;\n this.isStarted = false;\n this.winCallback = winCallback;\n this.loseCallback = loseCallback;\n }\n\n moveTile(fromCell, toCell) {\n const fromCellRect = fromCell.getBoundingClientRect();\n const toCellRect = toCell.getBoundingClientRect();\n\n const xOffset = toCellRect.left - fromCellRect.left;\n const yOffset = toCellRect.top - fromCellRect.top;\n\n fromCell.style.setProperty('--x-offset', `${xOffset}px`);\n fromCell.style.setProperty('--y-offset', `${yOffset}px`);\n\n fromCell.classList.add('moving');\n }\n\n updateBoard() {\n const cells = document.querySelectorAll('.field-cell');\n\n let cellIndex = 0;\n\n for (let row = 0; row < this.board.length; row++) {\n for (let col = 0; col < this.board[row].length; col++) {\n const cell = cells[cellIndex++];\n const value = this.board[row][col];\n const previousValue = cell.textContent;\n\n cell.classList.remove(`field-cell--${previousValue}`);\n\n if (value === 0) {\n cell.textContent = '';\n } else {\n cell.classList.add(`field-cell--${value}`);\n cell.textContent = value;\n }\n }\n }\n }\n\n addRandomTile() {\n const emptyCells = [];\n\n for (let row = 0; row < 4; row++) {\n for (let col = 0; col < 4; col++) {\n if (this.board[row][col] === 0) {\n emptyCells.push({ row, col });\n }\n }\n }\n\n if (emptyCells.length > 0) {\n const { row, col } =\n emptyCells[Math.floor(Math.random() * emptyCells.length)];\n\n if (this.score === 0) {\n this.board[row][col] = 2;\n }\n this.updateBoard();\n }\n }\n\n addRandomCellAfterMoving() {\n const emptyCells = [];\n\n for (let row = 0; row < 4; row++) {\n for (let col = 0; col < 4; col++) {\n if (this.board[row][col] === 0) {\n emptyCells.push({ row, col });\n }\n }\n }\n\n if (emptyCells.length > 0) {\n const { row, col } =\n emptyCells[Math.floor(Math.random() * emptyCells.length)];\n\n this.board[row][col] = Math.random() < 0.9 ? 2 : 4;\n this.updateBoard();\n }\n }\n\n createColumn(col) {\n const newColumn = [];\n\n for (let row = 0; row < this.board.length; row++) {\n if (this.board[row][col] !== 0) {\n newColumn.push(this.board[row][col]);\n }\n }\n\n return newColumn;\n }\n\n updateColumn(col, newColumn) {\n let moved = false;\n\n for (let row = 0; row < this.board.length; row++) {\n if (this.board[row][col] !== newColumn[row]) {\n this.board[row][col] = newColumn[row];\n moved = true;\n }\n }\n\n return moved;\n }\n\n resetGameStart() {\n this.score = 0;\n this.status = PLAYING;\n\n this.board = [\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n ];\n\n this.addRandomTile();\n this.addRandomTile();\n }\n\n mergeTitles(newRow, canMerge) {\n const mergedThisMove = [];\n\n for (let i = 0; i < newRow.length - 1; i++) {\n if (newRow[i] === newRow[i + 1]) {\n newRow[i] *= 2;\n newRow.splice(i + 1, 1);\n canMerge[i] = false;\n mergedThisMove.push(i);\n }\n }\n\n return mergedThisMove;\n }\n\n moveLeft() {\n let moved = false;\n\n for (let row = 0; row < this.board.length; row++) {\n const currentRow = this.board[row].filter((val) => val !== 0);\n const mergedRow = [];\n\n let skip = false;\n\n for (let i = 0; i < currentRow.length; i++) {\n if (skip) {\n skip = false;\n continue;\n }\n\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else {\n mergedRow.push(currentRow[i]);\n }\n }\n\n while (mergedRow.length < this.board[row].length) {\n mergedRow.push(0);\n }\n\n if (!moved) {\n for (let i = 0; i < this.board[row].length; i++) {\n if (this.board[row][i] !== mergedRow[i]) {\n moved = true;\n break;\n }\n }\n }\n\n this.board[row] = mergedRow;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n moveRight() {\n let moved = false;\n\n for (let row = 0; row < this.board.length; row++) {\n const currentRow = this.board[row].filter((val) => val !== 0);\n\n const mergedRow = [];\n let skip = false;\n\n for (let i = 0; i < currentRow.length; i++) {\n if (skip) {\n skip = false;\n continue;\n }\n\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else {\n mergedRow.push(currentRow[i]);\n }\n }\n\n while (mergedRow.length < this.board[row].length) {\n mergedRow.unshift(0);\n }\n\n for (let i = 0; i < this.board[row].length; i++) {\n if (this.board[row][i] !== mergedRow[i]) {\n moved = true;\n break;\n }\n }\n\n this.board[row] = mergedRow;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n moveUp() {\n let moved = false;\n\n for (let col = 0; col < this.board.length; col++) {\n const newColumn = this.createColumn(col);\n const canMerge = new Array(newColumn.length).fill(true);\n\n for (let i = 0; i < newColumn.length - 1; i++) {\n if (\n newColumn[i] === newColumn[i + 1] &&\n canMerge[i] &&\n canMerge[i + 1]\n ) {\n newColumn[i] *= 2;\n newColumn.splice(i + 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n }\n\n while (newColumn.length < this.board.length) {\n newColumn.push(0);\n }\n\n moved = this.updateColumn(col, newColumn) || moved;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n moveDown() {\n let moved = false;\n\n for (let col = 0; col < this.board.length; col++) {\n const newColumn = this.createColumn(col);\n const canMerge = new Array(newColumn.length).fill(true);\n\n for (let i = newColumn.length - 1; i > 0; i--) {\n if (\n newColumn[i] === newColumn[i - 1] &&\n canMerge[i] &&\n canMerge[i - 1]\n ) {\n newColumn[i] *= 2;\n newColumn.splice(i - 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n }\n\n while (newColumn.length < this.board.length) {\n newColumn.unshift(0);\n }\n\n moved = this.updateColumn(col, newColumn) || moved;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n /**\n * @returns {number[][]}\n */\n getState() {\n return this.board;\n }\n\n getStatus() {\n if (this.score === 0) {\n this.status = IDLE;\n } else {\n let hasEmptyCell = false;\n let has2048Cell = false;\n let canMove = false;\n\n for (let row = 0; row < this.board.length; row++) {\n for (let col = 0; col < this.board[row].length; col++) {\n if (this.board[row][col] === 0) {\n hasEmptyCell = true;\n }\n\n if (this.board[row][col] === 2048) {\n has2048Cell = true;\n }\n\n if (\n row < this.board.length - 1 &&\n this.board[row][col] === this.board[row + 1][col]\n ) {\n canMove = true;\n }\n\n if (\n col < this.board[row].length - 1 &&\n this.board[row][col] === this.board[row][col + 1]\n ) {\n canMove = true;\n }\n }\n }\n\n if (has2048Cell) {\n this.status = WIN;\n this.winCallback();\n } else if (hasEmptyCell || canMove) {\n this.status = PLAYING;\n } else {\n this.status = LOSE;\n this.loseCallback();\n }\n }\n\n return this.status;\n }\n\n start() {\n this.resetGameStart();\n }\n\n restart() {\n this.resetGameStart();\n }\n}\n","function _class_call_check(instance, Constructor) {\n if (!(instance instanceof Constructor)) throw new TypeError(\"Cannot call a class as a function\");\n}\nexport { _class_call_check as _ };\n","function _defineProperties(target, props) {\n for (var i = 0; i < props.length; i++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n\n if (\"value\" in descriptor) descriptor.writable = true;\n\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n}\nfunction _create_class(Constructor, protoProps, staticProps) {\n if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n if (staticProps) _defineProperties(Constructor, staticProps);\n\n return Constructor;\n}\nexport { _create_class as _ };\n"],"names":["$3d28d7f1aac198f5$var$IDLE","$3d28d7f1aac198f5$var$PLAYING","$3d28d7f1aac198f5$export$43a03cf66b318012","$197cd56b15c33885$var$game","protoProps","Game","initialState","winCallback","loseCallback","instance","Constructor","TypeError","board","score","status","isStarted","key","value","fromCell","toCell","fromCellRect","getBoundingClientRect","toCellRect","xOffset","left","yOffset","top","style","setProperty","concat","classList","add","cells","document","querySelectorAll","cellIndex","row","length","col","cell","previousValue","textContent","remove","emptyCells","push","_emptyCells_Math_floor","Math","floor","random","row1","col1","updateBoard","newColumn","moved","addRandomTile","newRow","canMerge","mergedThisMove","i","splice","_this","_loop","currentRow","filter","val","mergedRow","skip","getScore","i1","addRandomCellAfterMoving","getStatus","unshift","createColumn","Array","fill","updateColumn","hasEmptyCell","has2048Cell","canMove","resetGameStart","$4fc75ccb937ab1df$var$_defineProperties","target","props","descriptor","enumerable","configurable","writable","Object","defineProperty","prototype","$197cd56b15c33885$var$messageContainer","$197cd56b15c33885$var$startButton","querySelector","$197cd56b15c33885$var$cells","$197cd56b15c33885$var$score","$197cd56b15c33885$var$recordElement","$197cd56b15c33885$var$hideMessage","$197cd56b15c33885$var$displayRecord","highScore","localStorage","getItem","sscore","currentRecord","setItem","addEventListener","forEach","start","e","moveLeft","moveRight","moveUp","moveDown"],"version":3,"file":"index.1ca8bb72.js.map"} \ No newline at end of file diff --git a/dist/index.eaaf36ec.css b/dist/index.b8123ea8.css similarity index 76% rename from dist/index.eaaf36ec.css rename to dist/index.b8123ea8.css index 7ce3022c5..30dcca84d 100644 --- a/dist/index.eaaf36ec.css +++ b/dist/index.b8123ea8.css @@ -1,2 +1,2 @@ -body{background:#fbf8ef;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center;min-height:100vh;margin:0;font-family:sans-serif;font-size:24px;font-weight:900;display:-ms-flexbox;display:flex}.field-cell{color:#776e65;box-sizing:border-box;text-align:center;vertical-align:middle;-webkit-user-select:none;-ms-user-select:none;user-select:none;background:#d6cdc4;border-radius:5px;width:75px;height:75px;transition:transform .2s,background-color .2s;position:relative}.field-cell:empty{background:#d6cdc4}.field-cell--2{background:#eee4da}.field-cell--4{background:#e1d5c7}.field-cell--8{color:#f9f6f2;background:#5cb3bb}.field-cell--16{color:#f9f6f2;background:#469299}.field-cell--32{color:#f9f6f2;background:#349569}.field-cell--64{color:#f9f6f2;background:#30ac64}.field-cell--128{color:#f9f6f2;background:#26b84d}.field-cell--256{color:#fbfbfb;background:#0b7476}.field-cell--512{color:#f9f6f2;background:#5b8fd9}.field-cell--1024{color:#f9f6f2;background:#3b75c6}.field-cell--2048{color:#f9f6f2;background:#3b49c6}.game-field{border-spacing:10px;background:#bbada0;border-radius:5px}.game-header{box-sizing:border-box;-ms-flex-pack:justify;justify-content:space-between;width:100%;margin-bottom:24px;padding:10px;display:-ms-flexbox;display:flex}h1{color:#f9f6f2;box-sizing:border-box;background:#3a6ed6;border-radius:5px;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center;width:75px;height:75px;margin:0;font-size:24px;display:-ms-flexbox;display:flex}.best,.info{color:#776e65;box-sizing:border-box;background:#d6cdc4;border-radius:5px;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center;width:75px;height:75px;margin:0 8px 0 0;font-size:16px;display:-ms-flexbox;display:flex}.controls{display:-ms-flexbox;display:flex}.button{cursor:pointer;color:#f9f6f2;border:none;border-radius:5px;width:75px;height:75px;font-family:sans-serif;font-size:16px;font-weight:700;transition:background .25s}.start{background:#0aca6d;font-size:20px}.start:hover{background:#10b96a}.restart{background:#eb5b7d}.restart:hover{background:#d45271}.message{box-sizing:border-box;color:#776e65;text-align:center;background:#d6cdc4;border-radius:5px;width:100%;padding:10px;font-size:20px}.hidden{display:none}.container{-ms-flex-direction:column;flex-direction:column;-ms-flex-align:center;align-items:center;width:350px;display:-ms-flexbox;display:flex}.message-win{color:#f9f6f2;background:#2669b5}.message-lose{box-sizing:border-box;color:#f9f6f2;text-align:center;background:#bf687c;border-radius:5px;width:100%;margin-top:35px;padding-top:14px;font-size:20px;height:60px!important}.message-container{width:100%;height:150px}.moving{animation:.5s forwards move-tile}@keyframes move-tile{0%{transform:translate(var(--x-offset),var(--y-offset))}to{transform:translate(0)}}@keyframes merge-tile{0%{opacity:1;transform:scale(1);box-shadow:0 0 transparent}50%{opacity:.7;transform:scale(1.2);box-shadow:0 0 10px rgba(0,0,0,.3)}to{opacity:1;transform:scale(1);box-shadow:0 0 transparent}}.field-cell--merged{transition:transform .2s,opacity .4s;animation:.2s merge-tile} -/*# sourceMappingURL=index.eaaf36ec.css.map */ +body{background:#fbf8ef;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center;min-height:100vh;margin:0;font-family:sans-serif;font-size:24px;font-weight:900;display:-ms-flexbox;display:flex}.field-cell{color:#776e65;box-sizing:border-box;text-align:center;vertical-align:middle;-webkit-user-select:none;-ms-user-select:none;user-select:none;background:#d6cdc4;border-radius:5px;width:75px;height:75px;transition:transform .2s,background-color .2s;position:relative}.field-cell:empty{background:#d6cdc4}.field-cell--2{background:#eee4da}.field-cell--4{background:#e1d5c7}.field-cell--8{color:#f9f6f2;background:#5cb3bb}.field-cell--16{color:#f9f6f2;background:#469299}.field-cell--32{color:#f9f6f2;background:#349569}.field-cell--64{color:#f9f6f2;background:#30ac64}.field-cell--128{color:#f9f6f2;background:#26b84d}.field-cell--256{color:#fbfbfb;background:#0b7476}.field-cell--512{color:#f9f6f2;background:#5b8fd9}.field-cell--1024{color:#f9f6f2;background:#3b75c6}.field-cell--2048{color:#f9f6f2;background:#3b49c6}.game-field{border-spacing:10px;background:#bbada0;border-radius:5px}.game-header{box-sizing:border-box;-ms-flex-pack:justify;justify-content:space-between;width:100%;margin-bottom:24px;padding:10px;display:-ms-flexbox;display:flex}h1{color:#f9f6f2;box-sizing:border-box;background:#3a6ed6;border-radius:5px;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center;width:75px;height:75px;margin:0;font-size:24px;display:-ms-flexbox;display:flex}.best,.info{color:#776e65;box-sizing:border-box;background:#d6cdc4;border-radius:5px;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center;width:75px;height:75px;margin:0 8px 0 0;font-size:16px;display:-ms-flexbox;display:flex}.controls{display:-ms-flexbox;display:flex}.button{cursor:pointer;color:#f9f6f2;border:none;border-radius:5px;width:75px;height:75px;font-family:sans-serif;font-size:16px;font-weight:700;transition:background .25s}.start{background:#0aca6d;font-size:20px}.start:hover{background:#10b96a}.restart{background:#eb5b7d}.restart:hover{background:#d45271}.message{box-sizing:border-box;color:#776e65;text-align:center;background:#d6cdc4;border-radius:5px;width:100%;padding:10px;font-size:20px}.hidden{display:none}.container{-ms-flex-direction:column;flex-direction:column;-ms-flex-align:center;align-items:center;width:350px;display:-ms-flexbox;display:flex}.message-win{color:#f9f6f2;background:#2669b5}.message-lose{color:#f9f6f2;background:#bf687c}.message-container{width:100%;height:150px}.moving{animation:.5s forwards move-tile}@keyframes move-tile{0%{transform:translate(var(--x-offset),var(--y-offset))}to{transform:translate(0)}}@keyframes merge-tile{0%{opacity:1;transform:scale(1);box-shadow:0 0 transparent}50%{opacity:.7;transform:scale(1.2);box-shadow:0 0 10px rgba(0,0,0,.3)}to{opacity:1;transform:scale(1);box-shadow:0 0 transparent}}.field-cell--merged{transition:transform .2s,opacity .4s;animation:.2s merge-tile} +/*# sourceMappingURL=index.b8123ea8.css.map */ diff --git a/dist/index.b8123ea8.css.map b/dist/index.b8123ea8.css.map new file mode 100644 index 000000000..1d32f4f70 --- /dev/null +++ b/dist/index.b8123ea8.css.map @@ -0,0 +1 @@ +{"mappings":"ACAA,8NAYA,mRAcA,qCAIA,kCAIA,kCAIA,gDAKA,iDAKA,iDAKA,iDAKA,kDAKA,kDAKA,kDAKA,mDAKA,mDAKA,qEAMA,mKASA,iPAcA,kTAgBA,2CAIA,2KAaA,yCAIE,gCAKF,4BAGE,kCAKF,2IAWA,qBAIA,iJAOA,8CAKA,+CAKA,2CAKA,yCAIA,wGAKA,oNAkBA","sources":["index.b8123ea8.css","src/styles/main.scss"],"sourcesContent":["body {\n background: #fbf8ef;\n justify-content: center;\n align-items: center;\n min-height: 100vh;\n margin: 0;\n font-family: sans-serif;\n font-size: 24px;\n font-weight: 900;\n display: -ms-flexbox;\n display: flex;\n}\n\n.field-cell {\n color: #776e65;\n box-sizing: border-box;\n text-align: center;\n vertical-align: middle;\n -webkit-user-select: none;\n -ms-user-select: none;\n user-select: none;\n background: #d6cdc4;\n border-radius: 5px;\n width: 75px;\n height: 75px;\n transition: transform .2s, background-color .2s;\n position: relative;\n}\n\n.field-cell:empty {\n background: #d6cdc4;\n}\n\n.field-cell--2 {\n background: #eee4da;\n}\n\n.field-cell--4 {\n background: #e1d5c7;\n}\n\n.field-cell--8 {\n color: #f9f6f2;\n background: #5cb3bb;\n}\n\n.field-cell--16 {\n color: #f9f6f2;\n background: #469299;\n}\n\n.field-cell--32 {\n color: #f9f6f2;\n background: #349569;\n}\n\n.field-cell--64 {\n color: #f9f6f2;\n background: #30ac64;\n}\n\n.field-cell--128 {\n color: #f9f6f2;\n background: #26b84d;\n}\n\n.field-cell--256 {\n color: #fbfbfb;\n background: #0b7476;\n}\n\n.field-cell--512 {\n color: #f9f6f2;\n background: #5b8fd9;\n}\n\n.field-cell--1024 {\n color: #f9f6f2;\n background: #3b75c6;\n}\n\n.field-cell--2048 {\n color: #f9f6f2;\n background: #3b49c6;\n}\n\n.game-field {\n border-spacing: 10px;\n background: #bbada0;\n border-radius: 5px;\n}\n\n.game-header {\n box-sizing: border-box;\n justify-content: space-between;\n width: 100%;\n margin-bottom: 24px;\n padding: 10px;\n display: -ms-flexbox;\n display: flex;\n}\n\nh1 {\n color: #f9f6f2;\n box-sizing: border-box;\n background: #3a6ed6;\n border-radius: 5px;\n justify-content: center;\n align-items: center;\n width: 75px;\n height: 75px;\n margin: 0;\n font-size: 24px;\n display: -ms-flexbox;\n display: flex;\n}\n\n.best, .info {\n color: #776e65;\n box-sizing: border-box;\n background: #d6cdc4;\n border-radius: 5px;\n -ms-flex-direction: column;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n width: 75px;\n height: 75px;\n margin: 0 8px 0 0;\n font-size: 16px;\n display: -ms-flexbox;\n display: flex;\n}\n\n.controls {\n display: -ms-flexbox;\n display: flex;\n}\n\n.button {\n cursor: pointer;\n color: #f9f6f2;\n border: none;\n border-radius: 5px;\n width: 75px;\n height: 75px;\n font-family: sans-serif;\n font-size: 16px;\n font-weight: 700;\n transition: background .25s;\n}\n\n.start {\n background: #0aca6d;\n font-size: 20px;\n}\n\n.start:hover {\n background: #10b96a;\n}\n\n.restart {\n background: #eb5b7d;\n}\n\n.restart:hover {\n background: #d45271;\n}\n\n.message {\n box-sizing: border-box;\n color: #776e65;\n text-align: center;\n background: #d6cdc4;\n border-radius: 5px;\n width: 100%;\n padding: 10px;\n font-size: 20px;\n}\n\n.hidden {\n display: none;\n}\n\n.container {\n -ms-flex-direction: column;\n flex-direction: column;\n align-items: center;\n width: 350px;\n display: -ms-flexbox;\n display: flex;\n}\n\n.message-win {\n color: #f9f6f2;\n background: #2669b5;\n}\n\n.message-lose {\n color: #f9f6f2;\n background: #bf687c;\n}\n\n.message-container {\n width: 100%;\n height: 150px;\n}\n\n.moving {\n animation: .5s forwards move-tile;\n}\n\n@keyframes move-tile {\n from {\n transform: translate(var(--x-offset), var(--y-offset));\n }\n\n to {\n transform: translate(0);\n }\n}\n\n@keyframes merge-tile {\n 0% {\n opacity: 1;\n transform: scale(1);\n box-shadow: 0 0 #0000;\n }\n\n 50% {\n opacity: .7;\n transform: scale(1.2);\n box-shadow: 0 0 10px #0000004d;\n }\n\n 100% {\n opacity: 1;\n transform: scale(1);\n box-shadow: 0 0 #0000;\n }\n}\n\n.field-cell--merged {\n transition: transform .2s, opacity .4s;\n animation: .2s merge-tile;\n}\n/*# sourceMappingURL=index.b8123ea8.css.map */\n","body {\n margin: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n background: #fbf8ef;\n font-family: sans-serif;\n font-size: 24px;\n font-weight: 900;\n}\n\n.field-cell {\n background: #d6cdc4;\n width: 75px;\n height: 75px;\n border-radius: 5px;\n color: #776e65;\n box-sizing: border-box;\n text-align: center;\n vertical-align: middle;\n user-select: none;\n position: relative;\n transition: transform 0.2s ease, background-color 0.2s ease;\n}\n\n.field-cell:empty {\n background: #d6cdc4;\n}\n\n.field-cell--2 {\n background: #eee4da;\n}\n\n.field-cell--4 {\n background: #e1d5c7;\n}\n\n.field-cell--8 {\n background: #5cb3bb;\n color: #f9f6f2;\n}\n\n.field-cell--16 {\n background: #469299;\n color: #f9f6f2;\n}\n\n.field-cell--32 {\n background: #349569;\n color: #f9f6f2;\n}\n\n.field-cell--64 {\n background: #30ac64;\n color: #f9f6f2;\n}\n\n.field-cell--128 {\n background: #26b84d;\n color: #f9f6f2;\n}\n\n.field-cell--256 {\n background: #0b7476;\n color: #fbfbfb;\n}\n\n.field-cell--512 {\n background: #5b8fd9;\n color: #f9f6f2;\n}\n\n.field-cell--1024 {\n background: #3b75c6;\n color: #f9f6f2;\n}\n\n.field-cell--2048 {\n background: #3b49c6;\n color: #f9f6f2;\n}\n\n.game-field {\n background: #bbada0;\n border-spacing: 10px;\n border-radius: 5px;\n}\n\n.game-header {\n display: flex;\n width: 100%;\n justify-content: space-between;\n margin-bottom: 24px;\n padding: 10px;\n box-sizing: border-box;\n}\n\nh1 {\n background: #3a6ed6;\n color: #f9f6f2;\n width: 75px;\n height: 75px;\n font-size: 24px;\n border-radius: 5px;\n display: flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n margin: 0;\n}\n\n.best,\n.info {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background: #d6cdc4;\n width: 75px;\n height: 75px;\n border-radius: 5px;\n color: #776e65;\n box-sizing: border-box;\n font-size: 16px;\n margin: 0 8px 0 0;\n}\n\n.controls {\n display: flex;\n}\n\n.button {\n border: none;\n border-radius: 5px;\n cursor: pointer;\n color: #f9f6f2;\n font-family: sans-serif;\n font-weight: 700;\n font-size: 16px;\n width: 75px;\n height: 75px;\n transition: 0.25s ease background;\n}\n\n.start {\n background: #0aca6d;\n font-size: 20px;\n\n &:hover {\n background: #10b96a;\n }\n}\n\n.restart {\n background: #eb5b7d;\n\n &:hover {\n background: #d45271;\n }\n}\n\n.message {\n box-sizing: border-box;\n width: 100%;\n background: #d6cdc4;\n color: #776e65;\n padding: 10px;\n text-align: center;\n border-radius: 5px;\n font-size: 20px;\n}\n\n.hidden {\n display: none;\n}\n\n.container {\n display: flex;\n flex-direction: column;\n align-items: center;\n width: 350px;\n}\n\n.message-win {\n background: #2669b5;\n color: #f9f6f2;\n}\n\n.message-lose {\n background: #bf687c;\n color: #f9f6f2;\n}\n\n.message-container {\n width: 100%;\n height: 150px;\n}\n\n.moving {\n animation: move-tile 0.5s forwards;\n}\n\n@keyframes move-tile {\n from { transform: translate(var(--x-offset), var(--y-offset)); }\n to { transform: translate(0, 0); }\n}\n\n@keyframes merge-tile {\n 0% {\n transform: scale(1);\n opacity: 1;\n box-shadow: 0 0 0 rgba(0, 0, 0, 0);\n }\n 50% {\n transform: scale(1.2);\n opacity: 0.7;\n box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);\n }\n 100% {\n transform: scale(1);\n opacity: 1;\n box-shadow: 0 0 0 rgba(0, 0, 0, 0);\n }\n}\n\n.field-cell--merged {\n animation: merge-tile 0.2s ease;\n transition: transform 0.2s ease, opacity 0.4s ease;\n}\n"],"names":[],"version":3,"file":"index.b8123ea8.css.map"} \ No newline at end of file diff --git a/dist/index.eaaf36ec.css.map b/dist/index.eaaf36ec.css.map deleted file mode 100644 index e5dc23ddd..000000000 --- a/dist/index.eaaf36ec.css.map +++ /dev/null @@ -1 +0,0 @@ -{"mappings":"ACAA,8NAYA,mRAcA,qCAIA,kCAIA,kCAIA,gDAKA,iDAKA,iDAKA,iDAKA,kDAKA,kDAKA,kDAKA,mDAKA,mDAKA,qEAMA,mKASA,iPAcA,kTAgBA,2CAIA,2KAaA,yCAIE,gCAKF,4BAGE,kCAKF,2IAWA,qBAIA,iJAOA,8CAKA,0LAaA,2CAKA,yCAIA,wGAKA,oNAkBA","sources":["index.eaaf36ec.css","src/styles/main.scss"],"sourcesContent":["body {\n background: #fbf8ef;\n justify-content: center;\n align-items: center;\n min-height: 100vh;\n margin: 0;\n font-family: sans-serif;\n font-size: 24px;\n font-weight: 900;\n display: -ms-flexbox;\n display: flex;\n}\n\n.field-cell {\n color: #776e65;\n box-sizing: border-box;\n text-align: center;\n vertical-align: middle;\n -webkit-user-select: none;\n -ms-user-select: none;\n user-select: none;\n background: #d6cdc4;\n border-radius: 5px;\n width: 75px;\n height: 75px;\n transition: transform .2s, background-color .2s;\n position: relative;\n}\n\n.field-cell:empty {\n background: #d6cdc4;\n}\n\n.field-cell--2 {\n background: #eee4da;\n}\n\n.field-cell--4 {\n background: #e1d5c7;\n}\n\n.field-cell--8 {\n color: #f9f6f2;\n background: #5cb3bb;\n}\n\n.field-cell--16 {\n color: #f9f6f2;\n background: #469299;\n}\n\n.field-cell--32 {\n color: #f9f6f2;\n background: #349569;\n}\n\n.field-cell--64 {\n color: #f9f6f2;\n background: #30ac64;\n}\n\n.field-cell--128 {\n color: #f9f6f2;\n background: #26b84d;\n}\n\n.field-cell--256 {\n color: #fbfbfb;\n background: #0b7476;\n}\n\n.field-cell--512 {\n color: #f9f6f2;\n background: #5b8fd9;\n}\n\n.field-cell--1024 {\n color: #f9f6f2;\n background: #3b75c6;\n}\n\n.field-cell--2048 {\n color: #f9f6f2;\n background: #3b49c6;\n}\n\n.game-field {\n border-spacing: 10px;\n background: #bbada0;\n border-radius: 5px;\n}\n\n.game-header {\n box-sizing: border-box;\n justify-content: space-between;\n width: 100%;\n margin-bottom: 24px;\n padding: 10px;\n display: -ms-flexbox;\n display: flex;\n}\n\nh1 {\n color: #f9f6f2;\n box-sizing: border-box;\n background: #3a6ed6;\n border-radius: 5px;\n justify-content: center;\n align-items: center;\n width: 75px;\n height: 75px;\n margin: 0;\n font-size: 24px;\n display: -ms-flexbox;\n display: flex;\n}\n\n.best, .info {\n color: #776e65;\n box-sizing: border-box;\n background: #d6cdc4;\n border-radius: 5px;\n -ms-flex-direction: column;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n width: 75px;\n height: 75px;\n margin: 0 8px 0 0;\n font-size: 16px;\n display: -ms-flexbox;\n display: flex;\n}\n\n.controls {\n display: -ms-flexbox;\n display: flex;\n}\n\n.button {\n cursor: pointer;\n color: #f9f6f2;\n border: none;\n border-radius: 5px;\n width: 75px;\n height: 75px;\n font-family: sans-serif;\n font-size: 16px;\n font-weight: 700;\n transition: background .25s;\n}\n\n.start {\n background: #0aca6d;\n font-size: 20px;\n}\n\n.start:hover {\n background: #10b96a;\n}\n\n.restart {\n background: #eb5b7d;\n}\n\n.restart:hover {\n background: #d45271;\n}\n\n.message {\n box-sizing: border-box;\n color: #776e65;\n text-align: center;\n background: #d6cdc4;\n border-radius: 5px;\n width: 100%;\n padding: 10px;\n font-size: 20px;\n}\n\n.hidden {\n display: none;\n}\n\n.container {\n -ms-flex-direction: column;\n flex-direction: column;\n align-items: center;\n width: 350px;\n display: -ms-flexbox;\n display: flex;\n}\n\n.message-win {\n color: #f9f6f2;\n background: #2669b5;\n}\n\n.message-lose {\n box-sizing: border-box;\n color: #f9f6f2;\n text-align: center;\n background: #bf687c;\n border-radius: 5px;\n width: 100%;\n margin-top: 35px;\n padding-top: 14px;\n font-size: 20px;\n height: 60px !important;\n}\n\n.message-container {\n width: 100%;\n height: 150px;\n}\n\n.moving {\n animation: .5s forwards move-tile;\n}\n\n@keyframes move-tile {\n from {\n transform: translate(var(--x-offset), var(--y-offset));\n }\n\n to {\n transform: translate(0);\n }\n}\n\n@keyframes merge-tile {\n 0% {\n opacity: 1;\n transform: scale(1);\n box-shadow: 0 0 #0000;\n }\n\n 50% {\n opacity: .7;\n transform: scale(1.2);\n box-shadow: 0 0 10px #0000004d;\n }\n\n 100% {\n opacity: 1;\n transform: scale(1);\n box-shadow: 0 0 #0000;\n }\n}\n\n.field-cell--merged {\n transition: transform .2s, opacity .4s;\n animation: .2s merge-tile;\n}\n/*# sourceMappingURL=index.eaaf36ec.css.map */\n","body {\n margin: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n background: #fbf8ef;\n font-family: sans-serif;\n font-size: 24px;\n font-weight: 900;\n}\n\n.field-cell {\n background: #d6cdc4;\n width: 75px;\n height: 75px;\n border-radius: 5px;\n color: #776e65;\n box-sizing: border-box;\n text-align: center;\n vertical-align: middle;\n user-select: none;\n position: relative;\n transition: transform 0.2s ease, background-color 0.2s ease;\n}\n\n.field-cell:empty {\n background: #d6cdc4;\n}\n\n.field-cell--2 {\n background: #eee4da;\n}\n\n.field-cell--4 {\n background: #e1d5c7;\n}\n\n.field-cell--8 {\n background: #5cb3bb;\n color: #f9f6f2;\n}\n\n.field-cell--16 {\n background: #469299;\n color: #f9f6f2;\n}\n\n.field-cell--32 {\n background: #349569;\n color: #f9f6f2;\n}\n\n.field-cell--64 {\n background: #30ac64;\n color: #f9f6f2;\n}\n\n.field-cell--128 {\n background: #26b84d;\n color: #f9f6f2;\n}\n\n.field-cell--256 {\n background: #0b7476;\n color: #fbfbfb;\n}\n\n.field-cell--512 {\n background: #5b8fd9;\n color: #f9f6f2;\n}\n\n.field-cell--1024 {\n background: #3b75c6;\n color: #f9f6f2;\n}\n\n.field-cell--2048 {\n background: #3b49c6;\n color: #f9f6f2;\n}\n\n.game-field {\n background: #bbada0;\n border-spacing: 10px;\n border-radius: 5px;\n}\n\n.game-header {\n display: flex;\n width: 100%;\n justify-content: space-between;\n margin-bottom: 24px;\n padding: 10px;\n box-sizing: border-box;\n}\n\nh1 {\n background: #3a6ed6;\n color: #f9f6f2;\n width: 75px;\n height: 75px;\n font-size: 24px;\n border-radius: 5px;\n display: flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n margin: 0;\n}\n\n.best,\n.info {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background: #d6cdc4;\n width: 75px;\n height: 75px;\n border-radius: 5px;\n color: #776e65;\n box-sizing: border-box;\n font-size: 16px;\n margin: 0 8px 0 0;\n}\n\n.controls {\n display: flex;\n}\n\n.button {\n border: none;\n border-radius: 5px;\n cursor: pointer;\n color: #f9f6f2;\n font-family: sans-serif;\n font-weight: 700;\n font-size: 16px;\n width: 75px;\n height: 75px;\n transition: 0.25s ease background;\n}\n\n.start {\n background: #0aca6d;\n font-size: 20px;\n\n &:hover {\n background: #10b96a;\n }\n}\n\n.restart {\n background: #eb5b7d;\n\n &:hover {\n background: #d45271;\n }\n}\n\n.message {\n box-sizing: border-box;\n width: 100%;\n background: #d6cdc4;\n color: #776e65;\n padding: 10px;\n text-align: center;\n border-radius: 5px;\n font-size: 20px;\n}\n\n.hidden {\n display: none;\n}\n\n.container {\n display: flex;\n flex-direction: column;\n align-items: center;\n width: 350px;\n}\n\n.message-win {\n background: #2669b5;\n color: #f9f6f2;\n}\n\n.message-lose {\n width: 100%;\n box-sizing: border-box;\n height: 60px !important;\n padding-top: 14px;\n background: #bf687c;\n color: #f9f6f2;\n text-align: center;\n border-radius: 5px;\n font-size: 20px;\n margin-top: 35px;\n}\n\n.message-container {\n width: 100%;\n height: 150px;\n}\n\n.moving {\n animation: move-tile 0.5s forwards;\n}\n\n@keyframes move-tile {\n from { transform: translate(var(--x-offset), var(--y-offset)); }\n to { transform: translate(0, 0); }\n}\n\n@keyframes merge-tile {\n 0% {\n transform: scale(1);\n opacity: 1;\n box-shadow: 0 0 0 rgba(0, 0, 0, 0);\n }\n 50% {\n transform: scale(1.2);\n opacity: 0.7;\n box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);\n }\n 100% {\n transform: scale(1);\n opacity: 1;\n box-shadow: 0 0 0 rgba(0, 0, 0, 0);\n }\n}\n\n.field-cell--merged {\n animation: merge-tile 0.2s ease;\n transition: transform 0.2s ease, opacity 0.4s ease;\n}\n"],"names":[],"version":3,"file":"index.eaaf36ec.css.map"} \ No newline at end of file diff --git a/dist/index.edb5a6b7.js.map b/dist/index.edb5a6b7.js.map deleted file mode 100644 index 12e5a341d..000000000 --- a/dist/index.edb5a6b7.js.map +++ /dev/null @@ -1 +0,0 @@ -{"mappings":"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","sources":["","src/scripts/main.js","src/modules/Game.class.js"],"sourcesContent":["\"use strict\";\nconst $a5fd07fa01589658$var$IDLE = \"idle\";\nconst $a5fd07fa01589658$var$PLAYING = \"playing\";\nconst $a5fd07fa01589658$export$eb2b832b8b9fda85 = \"win\";\nconst $a5fd07fa01589658$export$43a03cf66b318012 = \"lose\";\nclass $a5fd07fa01589658$export$985739bfa5723e08 {\n constructor(initialState, winCallback, loseCallback){\n this.board = initialState || [\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ]\n ];\n this.score = 0;\n this.status = $a5fd07fa01589658$var$IDLE;\n this.isStarted = false;\n this.winCallback = winCallback;\n this.loseCallback = loseCallback;\n }\n moveTile(fromCell, toCell) {\n const fromCellRect = fromCell.getBoundingClientRect();\n const toCellRect = toCell.getBoundingClientRect();\n const xOffset = toCellRect.left - fromCellRect.left;\n const yOffset = toCellRect.top - fromCellRect.top;\n fromCell.style.setProperty(\"--x-offset\", `${xOffset}px`);\n fromCell.style.setProperty(\"--y-offset\", `${yOffset}px`);\n fromCell.classList.add(\"moving\");\n }\n updateBoard() {\n const cells = document.querySelectorAll(\".field-cell\");\n let cellIndex = 0;\n for(let row = 0; row < this.board.length; row++)for(let col = 0; col < this.board[row].length; col++){\n const cell = cells[cellIndex++];\n const value = this.board[row][col];\n const previousValue = cell.textContent;\n cell.classList.remove(`field-cell--${previousValue}`);\n if (value === 0) cell.textContent = \"\";\n else {\n cell.classList.add(`field-cell--${value}`);\n cell.textContent = value;\n }\n }\n }\n addRandomTile() {\n const emptyCells = [];\n for(let row = 0; row < 4; row++){\n for(let col = 0; col < 4; col++)if (this.board[row][col] === 0) emptyCells.push({\n row: row,\n col: col\n });\n }\n if (emptyCells.length > 0) {\n const { row: row, col: col } = emptyCells[Math.floor(Math.random() * emptyCells.length)];\n if (this.score === 0) this.board[row][col] = 2;\n this.updateBoard();\n }\n }\n addRandomCellAfterMoving() {\n const emptyCells = [];\n for(let row = 0; row < 4; row++){\n for(let col = 0; col < 4; col++)if (this.board[row][col] === 0) emptyCells.push({\n row: row,\n col: col\n });\n }\n if (emptyCells.length > 0) {\n const { row: row, col: col } = emptyCells[Math.floor(Math.random() * emptyCells.length)];\n this.board[row][col] = Math.random() < 0.9 ? 2 : 4;\n this.updateBoard();\n }\n }\n createColumn(col) {\n const newColumn = [];\n for(let row = 0; row < this.board.length; row++)if (this.board[row][col] !== 0) newColumn.push(this.board[row][col]);\n return newColumn;\n }\n updateColumn(col, newColumn) {\n let moved = false;\n for(let row = 0; row < this.board.length; row++)if (this.board[row][col] !== newColumn[row]) {\n this.board[row][col] = newColumn[row];\n moved = true;\n }\n return moved;\n }\n resetGameStart() {\n this.score = 0;\n this.status = $a5fd07fa01589658$var$PLAYING;\n this.board = [\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ]\n ];\n this.addRandomTile();\n this.addRandomTile();\n }\n mergeTitles(newRow, canMerge) {\n const mergedThisMove = [];\n for(let i = 0; i < newRow.length - 1; i++)if (newRow[i] === newRow[i + 1]) {\n newRow[i] *= 2;\n newRow.splice(i + 1, 1);\n canMerge[i] = false;\n mergedThisMove.push(i);\n }\n return mergedThisMove;\n }\n moveLeft() {\n let moved = false;\n for(let row = 0; row < this.board.length; row++){\n const currentRow = this.board[row].filter((val)=>val !== 0);\n const mergedRow = [];\n let skip = false;\n for(let i = 0; i < currentRow.length; i++){\n if (skip) {\n skip = false;\n continue;\n }\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else mergedRow.push(currentRow[i]);\n }\n while(mergedRow.length < this.board[row].length)mergedRow.push(0);\n if (!moved) {\n for(let i = 0; i < this.board[row].length; i++)if (this.board[row][i] !== mergedRow[i]) {\n moved = true;\n break;\n }\n }\n this.board[row] = mergedRow;\n }\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n moveRight() {\n let moved = false;\n for(let row = 0; row < this.board.length; row++){\n const currentRow = this.board[row].filter((val)=>val !== 0);\n const mergedRow = [];\n let skip = false;\n for(let i = 0; i < currentRow.length; i++){\n if (skip) {\n skip = false;\n continue;\n }\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else mergedRow.push(currentRow[i]);\n }\n while(mergedRow.length < this.board[row].length)mergedRow.unshift(0);\n for(let i = 0; i < this.board[row].length; i++)if (this.board[row][i] !== mergedRow[i]) {\n moved = true;\n break;\n }\n this.board[row] = mergedRow;\n }\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n moveUp() {\n let moved = false;\n for(let col = 0; col < this.board.length; col++){\n const newColumn = this.createColumn(col);\n const canMerge = new Array(newColumn.length).fill(true);\n for(let i = 0; i < newColumn.length - 1; i++)if (newColumn[i] === newColumn[i + 1] && canMerge[i] && canMerge[i + 1]) {\n newColumn[i] *= 2;\n newColumn.splice(i + 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n while(newColumn.length < this.board.length)newColumn.push(0);\n moved = this.updateColumn(col, newColumn) || moved;\n }\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n moveDown() {\n let moved = false;\n for(let col = 0; col < this.board.length; col++){\n const newColumn = this.createColumn(col);\n const canMerge = new Array(newColumn.length).fill(true);\n for(let i = newColumn.length - 1; i > 0; i--)if (newColumn[i] === newColumn[i - 1] && canMerge[i] && canMerge[i - 1]) {\n newColumn[i] *= 2;\n newColumn.splice(i - 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n while(newColumn.length < this.board.length)newColumn.unshift(0);\n moved = this.updateColumn(col, newColumn) || moved;\n }\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n /**\n * @returns {number[][]}\n */ getState() {\n return this.board;\n }\n getStatus() {\n if (this.score === 0) this.status = $a5fd07fa01589658$var$IDLE;\n else {\n let hasEmptyCell = false;\n let has2048Cell = false;\n let canMove = false;\n for(let row = 0; row < this.board.length; row++)for(let col = 0; col < this.board[row].length; col++){\n if (this.board[row][col] === 0) hasEmptyCell = true;\n if (this.board[row][col] === 2048) has2048Cell = true;\n if (row < this.board.length - 1 && this.board[row][col] === this.board[row + 1][col]) canMove = true;\n if (col < this.board[row].length - 1 && this.board[row][col] === this.board[row][col + 1]) canMove = true;\n }\n if (has2048Cell) {\n this.status = $a5fd07fa01589658$export$eb2b832b8b9fda85;\n this.winCallback();\n } else if (hasEmptyCell || canMove) this.status = $a5fd07fa01589658$var$PLAYING;\n else {\n this.status = $a5fd07fa01589658$export$43a03cf66b318012;\n this.loseCallback();\n }\n }\n return this.status;\n }\n start() {\n this.resetGameStart();\n }\n restart() {\n this.resetGameStart();\n }\n}\n\n\n\"use strict\";\nconst $09e991522ca7e64e$var$game = new (0, $a5fd07fa01589658$export$985739bfa5723e08)(null, $09e991522ca7e64e$var$showWinMessage, $09e991522ca7e64e$var$showLoseMessage);\nconst $09e991522ca7e64e$var$startButton = document.querySelector(\".start\");\nconst $09e991522ca7e64e$var$cells = document.querySelectorAll(\".field-cell\");\nconst $09e991522ca7e64e$var$score = document.querySelector(\".game-score\");\nconst $09e991522ca7e64e$var$recordElement = document.querySelector(\".best__score\");\nconst $09e991522ca7e64e$var$messageContainer = document.querySelector(\".message-container\");\nfunction $09e991522ca7e64e$var$showWinMessage() {\n $09e991522ca7e64e$var$messageContainer.classList.remove(\"hidden\");\n $09e991522ca7e64e$var$messageContainer.classList.add(\"message-win\");\n $09e991522ca7e64e$var$messageContainer.textContent = \"You Win!\";\n}\nfunction $09e991522ca7e64e$var$showLoseMessage() {\n $09e991522ca7e64e$var$messageContainer.classList.remove(\"hidden\");\n $09e991522ca7e64e$var$messageContainer.classList.add(\"message-lose\");\n $09e991522ca7e64e$var$messageContainer.textContent = \"You Lose!\";\n}\nfunction $09e991522ca7e64e$var$hideMessage() {\n $09e991522ca7e64e$var$messageContainer.classList.add(\"hidden\");\n}\nfunction $09e991522ca7e64e$var$updateScore(value) {\n $09e991522ca7e64e$var$score.textContent = value;\n}\nfunction $09e991522ca7e64e$var$saveScore(sscore) {\n const currentRecord = localStorage.getItem(\"highScore\");\n if (!currentRecord || sscore > currentRecord) {\n localStorage.setItem(\"highScore\", sscore);\n $09e991522ca7e64e$var$displayRecord();\n }\n}\nfunction $09e991522ca7e64e$var$displayRecord() {\n const highScore = localStorage.getItem(\"highScore\") || 0;\n $09e991522ca7e64e$var$recordElement.textContent = highScore;\n}\n$09e991522ca7e64e$var$displayRecord();\n$09e991522ca7e64e$var$game.getScore = function(moved, value) {\n if (moved && value > 0) {\n this.score += value;\n $09e991522ca7e64e$var$updateScore(this.score);\n $09e991522ca7e64e$var$saveScore(this.score);\n }\n};\n$09e991522ca7e64e$var$startButton.addEventListener(\"click\", ()=>{\n $09e991522ca7e64e$var$startButton.textContent = \"Restart\";\n $09e991522ca7e64e$var$startButton.classList.remove(\"start\");\n $09e991522ca7e64e$var$startButton.classList.add(\"restart\");\n $09e991522ca7e64e$var$score.textContent = \"0\";\n $09e991522ca7e64e$var$cells.forEach((cell)=>{\n cell.classList.remove(\"hidden\");\n });\n if ($09e991522ca7e64e$var$game.status === (0, $a5fd07fa01589658$export$eb2b832b8b9fda85) || $09e991522ca7e64e$var$game.status === (0, $a5fd07fa01589658$export$43a03cf66b318012)) $09e991522ca7e64e$var$hideMessage();\n $09e991522ca7e64e$var$game.start();\n $09e991522ca7e64e$var$hideMessage();\n $09e991522ca7e64e$var$displayRecord();\n});\ndocument.addEventListener(\"keydown\", (e)=>{\n switch(e.key){\n case \"ArrowLeft\":\n $09e991522ca7e64e$var$game.moveLeft();\n break;\n case \"ArrowRight\":\n $09e991522ca7e64e$var$game.moveRight();\n break;\n case \"ArrowUp\":\n $09e991522ca7e64e$var$game.moveUp();\n break;\n case \"ArrowDown\":\n $09e991522ca7e64e$var$game.moveDown();\n break;\n }\n});\n\n\n//# sourceMappingURL=index.edb5a6b7.js.map\n","'use strict';\n\nimport { WIN, LOSE, Game } from '../modules/Game.class';\n\nconst game = new Game(null, showWinMessage, showLoseMessage);\n\nconst startButton = document.querySelector('.start');\nconst cells = document.querySelectorAll('.field-cell');\nconst score = document.querySelector('.game-score');\nconst recordElement = document.querySelector('.best__score');\nconst messageContainer = document.querySelector('.message-container');\n\nfunction showWinMessage() {\n messageContainer.classList.remove('hidden');\n messageContainer.classList.add('message-win');\n messageContainer.textContent = 'You Win!';\n}\n\nfunction showLoseMessage() {\n messageContainer.classList.remove('hidden');\n messageContainer.classList.add('message-lose');\n messageContainer.textContent = 'You Lose!';\n}\n\nfunction hideMessage() {\n messageContainer.classList.add('hidden');\n}\n\nfunction updateScore(value) {\n score.textContent = value;\n}\n\nfunction saveScore(sscore) {\n const currentRecord = localStorage.getItem('highScore');\n\n if (!currentRecord || sscore > currentRecord) {\n localStorage.setItem('highScore', sscore);\n displayRecord();\n }\n}\n\nfunction displayRecord() {\n const highScore = localStorage.getItem('highScore') || 0;\n\n recordElement.textContent = highScore;\n}\n\ndisplayRecord();\n\ngame.getScore = function (moved, value) {\n if (moved && value > 0) {\n this.score += value;\n updateScore(this.score);\n saveScore(this.score);\n }\n};\n\nstartButton.addEventListener('click', () => {\n startButton.textContent = 'Restart';\n startButton.classList.remove('start');\n startButton.classList.add('restart');\n score.textContent = '0';\n\n cells.forEach((cell) => {\n cell.classList.remove('hidden');\n });\n\n if (game.status === WIN || game.status === LOSE) {\n hideMessage();\n }\n\n game.start();\n hideMessage();\n displayRecord();\n});\n\ndocument.addEventListener('keydown', (e) => {\n switch (e.key) {\n case 'ArrowLeft':\n game.moveLeft();\n break;\n case 'ArrowRight':\n game.moveRight();\n break;\n case 'ArrowUp':\n game.moveUp();\n break;\n case 'ArrowDown':\n game.moveDown();\n break;\n }\n});\n","'use strict';\n\nconst IDLE = 'idle';\nconst PLAYING = 'playing';\n\nexport const WIN = 'win';\nexport const LOSE = 'lose';\n\nexport class Game {\n constructor(initialState, winCallback, loseCallback) {\n this.board = initialState || [\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n ];\n\n this.score = 0;\n\n this.status = IDLE;\n this.isStarted = false;\n this.winCallback = winCallback;\n this.loseCallback = loseCallback;\n }\n\n moveTile(fromCell, toCell) {\n const fromCellRect = fromCell.getBoundingClientRect();\n const toCellRect = toCell.getBoundingClientRect();\n\n const xOffset = toCellRect.left - fromCellRect.left;\n const yOffset = toCellRect.top - fromCellRect.top;\n\n fromCell.style.setProperty('--x-offset', `${xOffset}px`);\n fromCell.style.setProperty('--y-offset', `${yOffset}px`);\n\n fromCell.classList.add('moving');\n }\n\n updateBoard() {\n const cells = document.querySelectorAll('.field-cell');\n\n let cellIndex = 0;\n\n for (let row = 0; row < this.board.length; row++) {\n for (let col = 0; col < this.board[row].length; col++) {\n const cell = cells[cellIndex++];\n const value = this.board[row][col];\n const previousValue = cell.textContent;\n\n cell.classList.remove(`field-cell--${previousValue}`);\n\n if (value === 0) {\n cell.textContent = '';\n } else {\n cell.classList.add(`field-cell--${value}`);\n cell.textContent = value;\n }\n }\n }\n }\n\n addRandomTile() {\n const emptyCells = [];\n\n for (let row = 0; row < 4; row++) {\n for (let col = 0; col < 4; col++) {\n if (this.board[row][col] === 0) {\n emptyCells.push({ row, col });\n }\n }\n }\n\n if (emptyCells.length > 0) {\n const { row, col } =\n emptyCells[Math.floor(Math.random() * emptyCells.length)];\n\n if (this.score === 0) {\n this.board[row][col] = 2;\n }\n this.updateBoard();\n }\n }\n\n addRandomCellAfterMoving() {\n const emptyCells = [];\n\n for (let row = 0; row < 4; row++) {\n for (let col = 0; col < 4; col++) {\n if (this.board[row][col] === 0) {\n emptyCells.push({ row, col });\n }\n }\n }\n\n if (emptyCells.length > 0) {\n const { row, col } =\n emptyCells[Math.floor(Math.random() * emptyCells.length)];\n\n this.board[row][col] = Math.random() < 0.9 ? 2 : 4;\n this.updateBoard();\n }\n }\n\n createColumn(col) {\n const newColumn = [];\n\n for (let row = 0; row < this.board.length; row++) {\n if (this.board[row][col] !== 0) {\n newColumn.push(this.board[row][col]);\n }\n }\n\n return newColumn;\n }\n\n updateColumn(col, newColumn) {\n let moved = false;\n\n for (let row = 0; row < this.board.length; row++) {\n if (this.board[row][col] !== newColumn[row]) {\n this.board[row][col] = newColumn[row];\n moved = true;\n }\n }\n\n return moved;\n }\n\n resetGameStart() {\n this.score = 0;\n this.status = PLAYING;\n\n this.board = [\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n ];\n\n this.addRandomTile();\n this.addRandomTile();\n }\n\n mergeTitles(newRow, canMerge) {\n const mergedThisMove = [];\n\n for (let i = 0; i < newRow.length - 1; i++) {\n if (newRow[i] === newRow[i + 1]) {\n newRow[i] *= 2;\n newRow.splice(i + 1, 1);\n canMerge[i] = false;\n mergedThisMove.push(i);\n }\n }\n\n return mergedThisMove;\n }\n\n moveLeft() {\n let moved = false;\n\n for (let row = 0; row < this.board.length; row++) {\n const currentRow = this.board[row].filter((val) => val !== 0);\n const mergedRow = [];\n\n let skip = false;\n\n for (let i = 0; i < currentRow.length; i++) {\n if (skip) {\n skip = false;\n continue;\n }\n\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else {\n mergedRow.push(currentRow[i]);\n }\n }\n\n while (mergedRow.length < this.board[row].length) {\n mergedRow.push(0);\n }\n\n if (!moved) {\n for (let i = 0; i < this.board[row].length; i++) {\n if (this.board[row][i] !== mergedRow[i]) {\n moved = true;\n break;\n }\n }\n }\n\n this.board[row] = mergedRow;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n moveRight() {\n let moved = false;\n\n for (let row = 0; row < this.board.length; row++) {\n const currentRow = this.board[row].filter((val) => val !== 0);\n\n const mergedRow = [];\n let skip = false;\n\n for (let i = 0; i < currentRow.length; i++) {\n if (skip) {\n skip = false;\n continue;\n }\n\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else {\n mergedRow.push(currentRow[i]);\n }\n }\n\n while (mergedRow.length < this.board[row].length) {\n mergedRow.unshift(0);\n }\n\n for (let i = 0; i < this.board[row].length; i++) {\n if (this.board[row][i] !== mergedRow[i]) {\n moved = true;\n break;\n }\n }\n\n this.board[row] = mergedRow;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n moveUp() {\n let moved = false;\n\n for (let col = 0; col < this.board.length; col++) {\n const newColumn = this.createColumn(col);\n const canMerge = new Array(newColumn.length).fill(true);\n\n for (let i = 0; i < newColumn.length - 1; i++) {\n if (\n newColumn[i] === newColumn[i + 1] &&\n canMerge[i] &&\n canMerge[i + 1]\n ) {\n newColumn[i] *= 2;\n newColumn.splice(i + 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n }\n\n while (newColumn.length < this.board.length) {\n newColumn.push(0);\n }\n\n moved = this.updateColumn(col, newColumn) || moved;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n moveDown() {\n let moved = false;\n\n for (let col = 0; col < this.board.length; col++) {\n const newColumn = this.createColumn(col);\n const canMerge = new Array(newColumn.length).fill(true);\n\n for (let i = newColumn.length - 1; i > 0; i--) {\n if (\n newColumn[i] === newColumn[i - 1] &&\n canMerge[i] &&\n canMerge[i - 1]\n ) {\n newColumn[i] *= 2;\n newColumn.splice(i - 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n }\n\n while (newColumn.length < this.board.length) {\n newColumn.unshift(0);\n }\n\n moved = this.updateColumn(col, newColumn) || moved;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n /**\n * @returns {number[][]}\n */\n getState() {\n return this.board;\n }\n\n getStatus() {\n if (this.score === 0) {\n this.status = IDLE;\n } else {\n let hasEmptyCell = false;\n let has2048Cell = false;\n let canMove = false;\n\n for (let row = 0; row < this.board.length; row++) {\n for (let col = 0; col < this.board[row].length; col++) {\n if (this.board[row][col] === 0) {\n hasEmptyCell = true;\n }\n\n if (this.board[row][col] === 2048) {\n has2048Cell = true;\n }\n\n if (\n row < this.board.length - 1 &&\n this.board[row][col] === this.board[row + 1][col]\n ) {\n canMove = true;\n }\n\n if (\n col < this.board[row].length - 1 &&\n this.board[row][col] === this.board[row][col + 1]\n ) {\n canMove = true;\n }\n }\n }\n\n if (has2048Cell) {\n this.status = WIN;\n this.winCallback();\n } else if (hasEmptyCell || canMove) {\n this.status = PLAYING;\n } else {\n this.status = LOSE;\n this.loseCallback();\n }\n }\n\n return this.status;\n }\n\n start() {\n this.resetGameStart();\n }\n\n restart() {\n this.resetGameStart();\n }\n}\n"],"names":["$a5fd07fa01589658$var$IDLE","$a5fd07fa01589658$var$PLAYING","$a5fd07fa01589658$export$43a03cf66b318012","$09e991522ca7e64e$var$game","constructor","initialState","winCallback","loseCallback","board","score","status","isStarted","moveTile","fromCell","toCell","fromCellRect","getBoundingClientRect","toCellRect","xOffset","left","yOffset","top","style","setProperty","classList","add","updateBoard","cells","document","querySelectorAll","cellIndex","row","length","col","cell","value","previousValue","textContent","remove","addRandomTile","emptyCells","push","Math","floor","random","addRandomCellAfterMoving","createColumn","newColumn","updateColumn","moved","resetGameStart","mergeTitles","newRow","canMerge","mergedThisMove","i","splice","moveLeft","currentRow","filter","val","mergedRow","skip","getScore","getStatus","moveRight","unshift","moveUp","Array","fill","moveDown","getState","hasEmptyCell","has2048Cell","canMove","start","restart","$09e991522ca7e64e$var$messageContainer","$09e991522ca7e64e$var$startButton","querySelector","$09e991522ca7e64e$var$cells","$09e991522ca7e64e$var$score","$09e991522ca7e64e$var$recordElement","$09e991522ca7e64e$var$hideMessage","$09e991522ca7e64e$var$displayRecord","highScore","localStorage","getItem","$09e991522ca7e64e$var$saveScore","sscore","currentRecord","setItem","addEventListener","forEach","e","key"],"version":3,"file":"index.edb5a6b7.js.map"} \ No newline at end of file diff --git a/dist/index.edb5a6b7.js b/dist/index.ef8de8d9.js similarity index 76% rename from dist/index.edb5a6b7.js rename to dist/index.ef8de8d9.js index e658eafdf..62b7d33d9 100644 --- a/dist/index.edb5a6b7.js +++ b/dist/index.ef8de8d9.js @@ -1,2 +1,2 @@ -const t="idle",e="playing",s="lose",o=new class{constructor(e,s,o){this.board=e||[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],this.score=0,this.status=t,this.isStarted=!1,this.winCallback=s,this.loseCallback=o}moveTile(t,e){let s=t.getBoundingClientRect(),o=e.getBoundingClientRect(),r=o.left-s.left,l=o.top-s.top;t.style.setProperty("--x-offset",`${r}px`),t.style.setProperty("--y-offset",`${l}px`),t.classList.add("moving")}updateBoard(){let t=document.querySelectorAll(".field-cell"),e=0;for(let s=0;s0){let{row:e,col:s}=t[Math.floor(Math.random()*t.length)];0===this.score&&(this.board[e][s]=2),this.updateBoard()}}addRandomCellAfterMoving(){let t=[];for(let e=0;e<4;e++)for(let s=0;s<4;s++)0===this.board[e][s]&&t.push({row:e,col:s});if(t.length>0){let{row:e,col:s}=t[Math.floor(Math.random()*t.length)];this.board[e][s]=.9>Math.random()?2:4,this.updateBoard()}}createColumn(t){let e=[];for(let s=0;s0!==t),o=[],r=!1;for(let e=0;e0!==t),o=[],r=!1;for(let e=0;e0;e--)s[e]===s[e-1]&&o[e]&&o[e-1]&&(s[e]*=2,s.splice(e-1,1),t=!0,o[e]=!1,this.getScore(t,s[e]));for(;s.length0){var s;this.score+=e,s=this.score,a.textContent=s,function(t){let e=localStorage.getItem("highScore");(!e||t>e)&&(localStorage.setItem("highScore",t),d())}(this.score)}},r.addEventListener("click",()=>{r.textContent="Restart",r.classList.remove("start"),r.classList.add("restart"),a.textContent="0",l.forEach(t=>{t.classList.remove("hidden")}),("win"===o.status||o.status===s)&&n(),o.start(),n(),d()}),document.addEventListener("keydown",t=>{switch(t.key){case"ArrowLeft":o.moveLeft();break;case"ArrowRight":o.moveRight();break;case"ArrowUp":o.moveUp();break;case"ArrowDown":o.moveDown()}}); -//# sourceMappingURL=index.edb5a6b7.js.map +const t="idle",e="playing",s="lose",o=new class{constructor(e,s,o){this.board=e||[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],this.score=0,this.status=t,this.isStarted=!1,this.winCallback=s,this.loseCallback=o}moveTile(t,e){let s=t.getBoundingClientRect(),o=e.getBoundingClientRect(),r=o.left-s.left,l=o.top-s.top;t.style.setProperty("--x-offset",`${r}px`),t.style.setProperty("--y-offset",`${l}px`),t.classList.add("moving")}updateBoard(){let t=document.querySelectorAll(".field-cell"),e=0;for(let s=0;s0){let{row:e,col:s}=t[Math.floor(Math.random()*t.length)];0===this.score&&(this.board[e][s]=2),this.updateBoard()}}addRandomCellAfterMoving(){let t=[];for(let e=0;e<4;e++)for(let s=0;s<4;s++)0===this.board[e][s]&&t.push({row:e,col:s});if(t.length>0){let{row:e,col:s}=t[Math.floor(Math.random()*t.length)];this.board[e][s]=.9>Math.random()?2:4,this.updateBoard()}}createColumn(t){let e=[];for(let s=0;s0!==t),o=[],r=!1;for(let e=0;e0!==t),o=[],r=!1;for(let e=0;e0;e--)s[e]===s[e-1]&&o[e]&&o[e-1]&&(s[e]*=2,s.splice(e-1,1),t=!0,o[e]=!1,this.getScore(t,s[e]));for(;s.length0){var s;this.score+=e,s=this.score,a.textContent=s,function(t){let e=localStorage.getItem("highScore");(!e||t>e)&&(localStorage.setItem("highScore",t),g())}(this.score)}},r.addEventListener("click",()=>{r.textContent="Restart",r.classList.remove("start"),r.classList.add("restart"),a.textContent="0",l.forEach(t=>{t.classList.remove("hidden")}),("win"===o.status||o.status===s)&&(u(),c()),o.start(),h.classList.add("hidden"),c(),u(),g()}),document.addEventListener("keydown",t=>{switch(t.key){case"ArrowLeft":o.moveLeft();break;case"ArrowRight":o.moveRight();break;case"ArrowUp":o.moveUp();break;case"ArrowDown":o.moveDown()}}); +//# sourceMappingURL=index.ef8de8d9.js.map diff --git a/dist/index.ef8de8d9.js.map b/dist/index.ef8de8d9.js.map new file mode 100644 index 000000000..4a006bc17 --- /dev/null +++ b/dist/index.ef8de8d9.js.map @@ -0,0 +1 @@ +{"mappings":"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","sources":["","src/scripts/main.js","src/modules/Game.class.js"],"sourcesContent":["\"use strict\";\nconst $a5fd07fa01589658$var$IDLE = \"idle\";\nconst $a5fd07fa01589658$var$PLAYING = \"playing\";\nconst $a5fd07fa01589658$export$eb2b832b8b9fda85 = \"win\";\nconst $a5fd07fa01589658$export$43a03cf66b318012 = \"lose\";\nclass $a5fd07fa01589658$export$985739bfa5723e08 {\n constructor(initialState, winCallback, loseCallback){\n this.board = initialState || [\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ]\n ];\n this.score = 0;\n this.status = $a5fd07fa01589658$var$IDLE;\n this.isStarted = false;\n this.winCallback = winCallback;\n this.loseCallback = loseCallback;\n }\n moveTile(fromCell, toCell) {\n const fromCellRect = fromCell.getBoundingClientRect();\n const toCellRect = toCell.getBoundingClientRect();\n const xOffset = toCellRect.left - fromCellRect.left;\n const yOffset = toCellRect.top - fromCellRect.top;\n fromCell.style.setProperty(\"--x-offset\", `${xOffset}px`);\n fromCell.style.setProperty(\"--y-offset\", `${yOffset}px`);\n fromCell.classList.add(\"moving\");\n }\n updateBoard() {\n const cells = document.querySelectorAll(\".field-cell\");\n let cellIndex = 0;\n for(let row = 0; row < this.board.length; row++)for(let col = 0; col < this.board[row].length; col++){\n const cell = cells[cellIndex++];\n const value = this.board[row][col];\n const previousValue = cell.textContent;\n cell.classList.remove(`field-cell--${previousValue}`);\n if (value === 0) cell.textContent = \"\";\n else {\n cell.classList.add(`field-cell--${value}`);\n cell.textContent = value;\n }\n }\n }\n addRandomTile() {\n const emptyCells = [];\n for(let row = 0; row < 4; row++){\n for(let col = 0; col < 4; col++)if (this.board[row][col] === 0) emptyCells.push({\n row: row,\n col: col\n });\n }\n if (emptyCells.length > 0) {\n const { row: row, col: col } = emptyCells[Math.floor(Math.random() * emptyCells.length)];\n if (this.score === 0) this.board[row][col] = 2;\n this.updateBoard();\n }\n }\n addRandomCellAfterMoving() {\n const emptyCells = [];\n for(let row = 0; row < 4; row++){\n for(let col = 0; col < 4; col++)if (this.board[row][col] === 0) emptyCells.push({\n row: row,\n col: col\n });\n }\n if (emptyCells.length > 0) {\n const { row: row, col: col } = emptyCells[Math.floor(Math.random() * emptyCells.length)];\n this.board[row][col] = Math.random() < 0.9 ? 2 : 4;\n this.updateBoard();\n }\n }\n createColumn(col) {\n const newColumn = [];\n for(let row = 0; row < this.board.length; row++)if (this.board[row][col] !== 0) newColumn.push(this.board[row][col]);\n return newColumn;\n }\n updateColumn(col, newColumn) {\n let moved = false;\n for(let row = 0; row < this.board.length; row++)if (this.board[row][col] !== newColumn[row]) {\n this.board[row][col] = newColumn[row];\n moved = true;\n }\n return moved;\n }\n resetGameStart() {\n this.score = 0;\n this.status = $a5fd07fa01589658$var$PLAYING;\n this.board = [\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0\n ]\n ];\n this.addRandomTile();\n this.addRandomTile();\n }\n mergeTitles(newRow, canMerge) {\n const mergedThisMove = [];\n for(let i = 0; i < newRow.length - 1; i++)if (newRow[i] === newRow[i + 1]) {\n newRow[i] *= 2;\n newRow.splice(i + 1, 1);\n canMerge[i] = false;\n mergedThisMove.push(i);\n }\n return mergedThisMove;\n }\n moveLeft() {\n let moved = false;\n for(let row = 0; row < this.board.length; row++){\n const currentRow = this.board[row].filter((val)=>val !== 0);\n const mergedRow = [];\n let skip = false;\n for(let i = 0; i < currentRow.length; i++){\n if (skip) {\n skip = false;\n continue;\n }\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else mergedRow.push(currentRow[i]);\n }\n while(mergedRow.length < this.board[row].length)mergedRow.push(0);\n if (!moved) {\n for(let i = 0; i < this.board[row].length; i++)if (this.board[row][i] !== mergedRow[i]) {\n moved = true;\n break;\n }\n }\n this.board[row] = mergedRow;\n }\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n moveRight() {\n let moved = false;\n for(let row = 0; row < this.board.length; row++){\n const currentRow = this.board[row].filter((val)=>val !== 0);\n const mergedRow = [];\n let skip = false;\n for(let i = 0; i < currentRow.length; i++){\n if (skip) {\n skip = false;\n continue;\n }\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else mergedRow.push(currentRow[i]);\n }\n while(mergedRow.length < this.board[row].length)mergedRow.unshift(0);\n for(let i = 0; i < this.board[row].length; i++)if (this.board[row][i] !== mergedRow[i]) {\n moved = true;\n break;\n }\n this.board[row] = mergedRow;\n }\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n moveUp() {\n let moved = false;\n for(let col = 0; col < this.board.length; col++){\n const newColumn = this.createColumn(col);\n const canMerge = new Array(newColumn.length).fill(true);\n for(let i = 0; i < newColumn.length - 1; i++)if (newColumn[i] === newColumn[i + 1] && canMerge[i] && canMerge[i + 1]) {\n newColumn[i] *= 2;\n newColumn.splice(i + 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n while(newColumn.length < this.board.length)newColumn.push(0);\n moved = this.updateColumn(col, newColumn) || moved;\n }\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n moveDown() {\n let moved = false;\n for(let col = 0; col < this.board.length; col++){\n const newColumn = this.createColumn(col);\n const canMerge = new Array(newColumn.length).fill(true);\n for(let i = newColumn.length - 1; i > 0; i--)if (newColumn[i] === newColumn[i - 1] && canMerge[i] && canMerge[i - 1]) {\n newColumn[i] *= 2;\n newColumn.splice(i - 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n while(newColumn.length < this.board.length)newColumn.unshift(0);\n moved = this.updateColumn(col, newColumn) || moved;\n }\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n return moved;\n }\n /**\n * @returns {number[][]}\n */ getState() {\n return this.board;\n }\n getStatus() {\n if (this.score === 0) this.status = $a5fd07fa01589658$var$IDLE;\n else {\n let hasEmptyCell = false;\n let has2048Cell = false;\n let canMove = false;\n for(let row = 0; row < this.board.length; row++)for(let col = 0; col < this.board[row].length; col++){\n if (this.board[row][col] === 0) hasEmptyCell = true;\n if (this.board[row][col] === 2048) has2048Cell = true;\n if (row < this.board.length - 1 && this.board[row][col] === this.board[row + 1][col]) canMove = true;\n if (col < this.board[row].length - 1 && this.board[row][col] === this.board[row][col + 1]) canMove = true;\n }\n if (has2048Cell) {\n this.status = $a5fd07fa01589658$export$eb2b832b8b9fda85;\n this.winCallback();\n } else if (hasEmptyCell || canMove) this.status = $a5fd07fa01589658$var$PLAYING;\n else {\n this.status = $a5fd07fa01589658$export$43a03cf66b318012;\n this.loseCallback();\n }\n }\n return this.status;\n }\n start() {\n this.resetGameStart();\n }\n restart() {\n this.resetGameStart();\n }\n}\n\n\n\"use strict\";\nconst $09e991522ca7e64e$var$game = new (0, $a5fd07fa01589658$export$985739bfa5723e08)(null, $09e991522ca7e64e$var$showWinMessage, $09e991522ca7e64e$var$showLoseMessage);\nconst $09e991522ca7e64e$var$startButton = document.querySelector(\".start\");\nconst $09e991522ca7e64e$var$cells = document.querySelectorAll(\".field-cell\");\nconst $09e991522ca7e64e$var$score = document.querySelector(\".game-score\");\nconst $09e991522ca7e64e$var$recordElement = document.querySelector(\".best__score\");\nconst $09e991522ca7e64e$var$messageStart = document.querySelector(\".message-start\");\nconst $09e991522ca7e64e$var$messageWin = document.querySelector(\".message-win\");\nconst $09e991522ca7e64e$var$messageLose = document.querySelector(\".message-lose\");\nfunction $09e991522ca7e64e$var$showWinMessage() {\n $09e991522ca7e64e$var$messageWin.classList.remove(\"hidden\");\n}\nfunction $09e991522ca7e64e$var$showLoseMessage() {\n $09e991522ca7e64e$var$messageLose.classList.remove(\"hidden\");\n}\nfunction $09e991522ca7e64e$var$hideMessageStart() {\n $09e991522ca7e64e$var$messageStart.classList.add(\"hidden\");\n}\nfunction $09e991522ca7e64e$var$hideMessageLose() {\n $09e991522ca7e64e$var$messageLose.classList.add(\"hidden\");\n}\nfunction $09e991522ca7e64e$var$hideMessageWin() {\n $09e991522ca7e64e$var$messageWin.classList.add(\"hidden\");\n}\nfunction $09e991522ca7e64e$var$updateScore(value) {\n $09e991522ca7e64e$var$score.textContent = value;\n}\nfunction $09e991522ca7e64e$var$saveScore(sscore) {\n const currentRecord = localStorage.getItem(\"highScore\");\n if (!currentRecord || sscore > currentRecord) {\n localStorage.setItem(\"highScore\", sscore);\n $09e991522ca7e64e$var$displayRecord();\n }\n}\nfunction $09e991522ca7e64e$var$displayRecord() {\n const highScore = localStorage.getItem(\"highScore\") || 0;\n $09e991522ca7e64e$var$recordElement.textContent = highScore;\n}\n$09e991522ca7e64e$var$displayRecord();\n$09e991522ca7e64e$var$game.getScore = function(moved, value) {\n if (moved && value > 0) {\n this.score += value;\n $09e991522ca7e64e$var$updateScore(this.score);\n $09e991522ca7e64e$var$saveScore(this.score);\n }\n};\n$09e991522ca7e64e$var$startButton.addEventListener(\"click\", ()=>{\n $09e991522ca7e64e$var$startButton.textContent = \"Restart\";\n $09e991522ca7e64e$var$startButton.classList.remove(\"start\");\n $09e991522ca7e64e$var$startButton.classList.add(\"restart\");\n $09e991522ca7e64e$var$score.textContent = \"0\";\n $09e991522ca7e64e$var$cells.forEach((cell)=>{\n cell.classList.remove(\"hidden\");\n });\n if ($09e991522ca7e64e$var$game.status === (0, $a5fd07fa01589658$export$eb2b832b8b9fda85) || $09e991522ca7e64e$var$game.status === (0, $a5fd07fa01589658$export$43a03cf66b318012)) {\n $09e991522ca7e64e$var$hideMessageWin();\n $09e991522ca7e64e$var$hideMessageLose();\n }\n $09e991522ca7e64e$var$game.start();\n $09e991522ca7e64e$var$hideMessageStart();\n $09e991522ca7e64e$var$hideMessageLose();\n $09e991522ca7e64e$var$hideMessageWin();\n $09e991522ca7e64e$var$displayRecord();\n});\ndocument.addEventListener(\"keydown\", (e)=>{\n switch(e.key){\n case \"ArrowLeft\":\n $09e991522ca7e64e$var$game.moveLeft();\n break;\n case \"ArrowRight\":\n $09e991522ca7e64e$var$game.moveRight();\n break;\n case \"ArrowUp\":\n $09e991522ca7e64e$var$game.moveUp();\n break;\n case \"ArrowDown\":\n $09e991522ca7e64e$var$game.moveDown();\n break;\n }\n});\n\n\n//# sourceMappingURL=index.ef8de8d9.js.map\n","'use strict';\n\nimport { WIN, LOSE, Game } from '../modules/Game.class';\n\nconst game = new Game(null, showWinMessage, showLoseMessage);\n\nconst startButton = document.querySelector('.start');\nconst cells = document.querySelectorAll('.field-cell');\nconst score = document.querySelector('.game-score');\nconst recordElement = document.querySelector('.best__score');\nconst messageStart = document.querySelector('.message-start');\nconst messageWin = document.querySelector('.message-win');\nconst messageLose = document.querySelector('.message-lose');\n\nfunction showWinMessage() {\n messageWin.classList.remove('hidden');\n}\n\nfunction showLoseMessage() {\n messageLose.classList.remove('hidden');\n}\n\nfunction hideMessageStart() {\n messageStart.classList.add('hidden');\n}\n\nfunction hideMessageLose() {\n messageLose.classList.add('hidden');\n}\n\nfunction hideMessageWin() {\n messageWin.classList.add('hidden');\n}\n\nfunction updateScore(value) {\n score.textContent = value;\n}\n\nfunction saveScore(sscore) {\n const currentRecord = localStorage.getItem('highScore');\n\n if (!currentRecord || sscore > currentRecord) {\n localStorage.setItem('highScore', sscore);\n displayRecord();\n }\n}\n\nfunction displayRecord() {\n const highScore = localStorage.getItem('highScore') || 0;\n\n recordElement.textContent = highScore;\n}\n\ndisplayRecord();\n\ngame.getScore = function (moved, value) {\n if (moved && value > 0) {\n this.score += value;\n updateScore(this.score);\n saveScore(this.score);\n }\n};\n\nstartButton.addEventListener('click', () => {\n startButton.textContent = 'Restart';\n startButton.classList.remove('start');\n startButton.classList.add('restart');\n score.textContent = '0';\n\n cells.forEach((cell) => {\n cell.classList.remove('hidden');\n });\n\n if (game.status === WIN || game.status === LOSE) {\n hideMessageWin();\n hideMessageLose();\n }\n\n game.start();\n hideMessageStart();\n hideMessageLose();\n hideMessageWin();\n displayRecord();\n});\n\ndocument.addEventListener('keydown', (e) => {\n switch (e.key) {\n case 'ArrowLeft':\n game.moveLeft();\n break;\n case 'ArrowRight':\n game.moveRight();\n break;\n case 'ArrowUp':\n game.moveUp();\n break;\n case 'ArrowDown':\n game.moveDown();\n break;\n }\n});\n","'use strict';\n\nconst IDLE = 'idle';\nconst PLAYING = 'playing';\n\nexport const WIN = 'win';\nexport const LOSE = 'lose';\n\nexport class Game {\n constructor(initialState, winCallback, loseCallback) {\n this.board = initialState || [\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n ];\n\n this.score = 0;\n\n this.status = IDLE;\n this.isStarted = false;\n this.winCallback = winCallback;\n this.loseCallback = loseCallback;\n }\n\n moveTile(fromCell, toCell) {\n const fromCellRect = fromCell.getBoundingClientRect();\n const toCellRect = toCell.getBoundingClientRect();\n\n const xOffset = toCellRect.left - fromCellRect.left;\n const yOffset = toCellRect.top - fromCellRect.top;\n\n fromCell.style.setProperty('--x-offset', `${xOffset}px`);\n fromCell.style.setProperty('--y-offset', `${yOffset}px`);\n\n fromCell.classList.add('moving');\n }\n\n updateBoard() {\n const cells = document.querySelectorAll('.field-cell');\n\n let cellIndex = 0;\n\n for (let row = 0; row < this.board.length; row++) {\n for (let col = 0; col < this.board[row].length; col++) {\n const cell = cells[cellIndex++];\n const value = this.board[row][col];\n const previousValue = cell.textContent;\n\n cell.classList.remove(`field-cell--${previousValue}`);\n\n if (value === 0) {\n cell.textContent = '';\n } else {\n cell.classList.add(`field-cell--${value}`);\n cell.textContent = value;\n }\n }\n }\n }\n\n addRandomTile() {\n const emptyCells = [];\n\n for (let row = 0; row < 4; row++) {\n for (let col = 0; col < 4; col++) {\n if (this.board[row][col] === 0) {\n emptyCells.push({ row, col });\n }\n }\n }\n\n if (emptyCells.length > 0) {\n const { row, col } =\n emptyCells[Math.floor(Math.random() * emptyCells.length)];\n\n if (this.score === 0) {\n this.board[row][col] = 2;\n }\n this.updateBoard();\n }\n }\n\n addRandomCellAfterMoving() {\n const emptyCells = [];\n\n for (let row = 0; row < 4; row++) {\n for (let col = 0; col < 4; col++) {\n if (this.board[row][col] === 0) {\n emptyCells.push({ row, col });\n }\n }\n }\n\n if (emptyCells.length > 0) {\n const { row, col } =\n emptyCells[Math.floor(Math.random() * emptyCells.length)];\n\n this.board[row][col] = Math.random() < 0.9 ? 2 : 4;\n this.updateBoard();\n }\n }\n\n createColumn(col) {\n const newColumn = [];\n\n for (let row = 0; row < this.board.length; row++) {\n if (this.board[row][col] !== 0) {\n newColumn.push(this.board[row][col]);\n }\n }\n\n return newColumn;\n }\n\n updateColumn(col, newColumn) {\n let moved = false;\n\n for (let row = 0; row < this.board.length; row++) {\n if (this.board[row][col] !== newColumn[row]) {\n this.board[row][col] = newColumn[row];\n moved = true;\n }\n }\n\n return moved;\n }\n\n resetGameStart() {\n this.score = 0;\n this.status = PLAYING;\n\n this.board = [\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n [0, 0, 0, 0],\n ];\n\n this.addRandomTile();\n this.addRandomTile();\n }\n\n mergeTitles(newRow, canMerge) {\n const mergedThisMove = [];\n\n for (let i = 0; i < newRow.length - 1; i++) {\n if (newRow[i] === newRow[i + 1]) {\n newRow[i] *= 2;\n newRow.splice(i + 1, 1);\n canMerge[i] = false;\n mergedThisMove.push(i);\n }\n }\n\n return mergedThisMove;\n }\n\n moveLeft() {\n let moved = false;\n\n for (let row = 0; row < this.board.length; row++) {\n const currentRow = this.board[row].filter((val) => val !== 0);\n const mergedRow = [];\n\n let skip = false;\n\n for (let i = 0; i < currentRow.length; i++) {\n if (skip) {\n skip = false;\n continue;\n }\n\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else {\n mergedRow.push(currentRow[i]);\n }\n }\n\n while (mergedRow.length < this.board[row].length) {\n mergedRow.push(0);\n }\n\n if (!moved) {\n for (let i = 0; i < this.board[row].length; i++) {\n if (this.board[row][i] !== mergedRow[i]) {\n moved = true;\n break;\n }\n }\n }\n\n this.board[row] = mergedRow;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n moveRight() {\n let moved = false;\n\n for (let row = 0; row < this.board.length; row++) {\n const currentRow = this.board[row].filter((val) => val !== 0);\n\n const mergedRow = [];\n let skip = false;\n\n for (let i = 0; i < currentRow.length; i++) {\n if (skip) {\n skip = false;\n continue;\n }\n\n if (currentRow[i] === currentRow[i + 1]) {\n mergedRow.push(currentRow[i] * 2);\n this.getScore(true, currentRow[i] * 2);\n skip = true;\n moved = true;\n } else {\n mergedRow.push(currentRow[i]);\n }\n }\n\n while (mergedRow.length < this.board[row].length) {\n mergedRow.unshift(0);\n }\n\n for (let i = 0; i < this.board[row].length; i++) {\n if (this.board[row][i] !== mergedRow[i]) {\n moved = true;\n break;\n }\n }\n\n this.board[row] = mergedRow;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n moveUp() {\n let moved = false;\n\n for (let col = 0; col < this.board.length; col++) {\n const newColumn = this.createColumn(col);\n const canMerge = new Array(newColumn.length).fill(true);\n\n for (let i = 0; i < newColumn.length - 1; i++) {\n if (\n newColumn[i] === newColumn[i + 1] &&\n canMerge[i] &&\n canMerge[i + 1]\n ) {\n newColumn[i] *= 2;\n newColumn.splice(i + 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n }\n\n while (newColumn.length < this.board.length) {\n newColumn.push(0);\n }\n\n moved = this.updateColumn(col, newColumn) || moved;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n moveDown() {\n let moved = false;\n\n for (let col = 0; col < this.board.length; col++) {\n const newColumn = this.createColumn(col);\n const canMerge = new Array(newColumn.length).fill(true);\n\n for (let i = newColumn.length - 1; i > 0; i--) {\n if (\n newColumn[i] === newColumn[i - 1] &&\n canMerge[i] &&\n canMerge[i - 1]\n ) {\n newColumn[i] *= 2;\n newColumn.splice(i - 1, 1);\n moved = true;\n canMerge[i] = false;\n this.getScore(moved, newColumn[i]);\n }\n }\n\n while (newColumn.length < this.board.length) {\n newColumn.unshift(0);\n }\n\n moved = this.updateColumn(col, newColumn) || moved;\n }\n\n if (moved) {\n this.addRandomCellAfterMoving();\n this.updateBoard();\n this.getStatus();\n }\n\n return moved;\n }\n\n /**\n * @returns {number[][]}\n */\n getState() {\n return this.board;\n }\n\n getStatus() {\n if (this.score === 0) {\n this.status = IDLE;\n } else {\n let hasEmptyCell = false;\n let has2048Cell = false;\n let canMove = false;\n\n for (let row = 0; row < this.board.length; row++) {\n for (let col = 0; col < this.board[row].length; col++) {\n if (this.board[row][col] === 0) {\n hasEmptyCell = true;\n }\n\n if (this.board[row][col] === 2048) {\n has2048Cell = true;\n }\n\n if (\n row < this.board.length - 1 &&\n this.board[row][col] === this.board[row + 1][col]\n ) {\n canMove = true;\n }\n\n if (\n col < this.board[row].length - 1 &&\n this.board[row][col] === this.board[row][col + 1]\n ) {\n canMove = true;\n }\n }\n }\n\n if (has2048Cell) {\n this.status = WIN;\n this.winCallback();\n } else if (hasEmptyCell || canMove) {\n this.status = PLAYING;\n } else {\n this.status = LOSE;\n this.loseCallback();\n }\n }\n\n return this.status;\n }\n\n start() {\n this.resetGameStart();\n }\n\n restart() {\n this.resetGameStart();\n }\n}\n"],"names":["$a5fd07fa01589658$var$IDLE","$a5fd07fa01589658$var$PLAYING","$a5fd07fa01589658$export$43a03cf66b318012","$09e991522ca7e64e$var$game","constructor","initialState","winCallback","loseCallback","board","score","status","isStarted","moveTile","fromCell","toCell","fromCellRect","getBoundingClientRect","toCellRect","xOffset","left","yOffset","top","style","setProperty","classList","add","updateBoard","cells","document","querySelectorAll","cellIndex","row","length","col","cell","value","previousValue","textContent","remove","addRandomTile","emptyCells","push","Math","floor","random","addRandomCellAfterMoving","createColumn","newColumn","updateColumn","moved","resetGameStart","mergeTitles","newRow","canMerge","mergedThisMove","i","splice","moveLeft","currentRow","filter","val","mergedRow","skip","getScore","getStatus","moveRight","unshift","moveUp","Array","fill","moveDown","getState","hasEmptyCell","has2048Cell","canMove","start","restart","$09e991522ca7e64e$var$messageWin","$09e991522ca7e64e$var$messageLose","$09e991522ca7e64e$var$startButton","querySelector","$09e991522ca7e64e$var$cells","$09e991522ca7e64e$var$score","$09e991522ca7e64e$var$recordElement","$09e991522ca7e64e$var$messageStart","$09e991522ca7e64e$var$hideMessageLose","$09e991522ca7e64e$var$hideMessageWin","$09e991522ca7e64e$var$displayRecord","highScore","localStorage","getItem","$09e991522ca7e64e$var$saveScore","sscore","currentRecord","setItem","addEventListener","forEach","e","key"],"version":3,"file":"index.ef8de8d9.js.map"} \ No newline at end of file diff --git a/dist/index.html b/dist/index.html index 7ced03203..f538a138d 100644 --- a/dist/index.html +++ b/dist/index.html @@ -1 +1 @@ -2048

2048

Best: 0

Score: 0

Press "Start" to begin game. Good luck!

\ No newline at end of file +2048

2048

Best: 0

Score: 0

Press "Start" to begin game. Good luck!

\ No newline at end of file From 3760bba9d62f90a39e477d464a60ef44d6e2c47f Mon Sep 17 00:00:00 2001 From: Iryna Mariiko Date: Wed, 27 Nov 2024 21:23:40 +0200 Subject: [PATCH 13/14] impoved code --- src/modules/Game.class.js | 273 +++++++++++++------------------------- 1 file changed, 89 insertions(+), 184 deletions(-) diff --git a/src/modules/Game.class.js b/src/modules/Game.class.js index 1dbcf9e14..3622f8135 100644 --- a/src/modules/Game.class.js +++ b/src/modules/Game.class.js @@ -18,24 +18,10 @@ export class Game { this.score = 0; this.status = IDLE; - this.isStarted = false; this.winCallback = winCallback; this.loseCallback = loseCallback; } - moveTile(fromCell, toCell) { - const fromCellRect = fromCell.getBoundingClientRect(); - const toCellRect = toCell.getBoundingClientRect(); - - const xOffset = toCellRect.left - fromCellRect.left; - const yOffset = toCellRect.top - fromCellRect.top; - - fromCell.style.setProperty('--x-offset', `${xOffset}px`); - fromCell.style.setProperty('--y-offset', `${yOffset}px`); - - fromCell.classList.add('moving'); - } - updateBoard() { const cells = document.querySelectorAll('.field-cell'); @@ -59,46 +45,42 @@ export class Game { } } - addRandomTile() { + findEmptyCell() { const emptyCells = []; - for (let row = 0; row < 4; row++) { - for (let col = 0; col < 4; col++) { + for (let row = 0; row < this.board.length; row++) { + for (let col = 0; col < this.board.length; col++) { if (this.board[row][col] === 0) { emptyCells.push({ row, col }); } } } - if (emptyCells.length > 0) { - const { row, col } = - emptyCells[Math.floor(Math.random() * emptyCells.length)]; + return emptyCells[Math.floor(Math.random() * emptyCells.length)]; + } - if (this.score === 0) { - this.board[row][col] = 2; - } - this.updateBoard(); + addRandomTile() { + const emptyCell = this.findEmptyCell(); + + if (!emptyCell) { + return; } + + if (this.score === 0) { + this.board[emptyCell.row][emptyCell.col] = 2; + } + this.updateBoard(); } addRandomCellAfterMoving() { - const emptyCells = []; + const emptyCell = this.findEmptyCell(); - for (let row = 0; row < 4; row++) { - for (let col = 0; col < 4; col++) { - if (this.board[row][col] === 0) { - emptyCells.push({ row, col }); - } - } + if (!emptyCell) { + return; } - if (emptyCells.length > 0) { - const { row, col } = - emptyCells[Math.floor(Math.random() * emptyCells.length)]; - - this.board[row][col] = Math.random() < 0.9 ? 2 : 4; - this.updateBoard(); - } + this.board[emptyCell.row][emptyCell.col] = Math.random() < 0.9 ? 2 : 4; + this.updateBoard(); } createColumn(col) { @@ -141,122 +123,51 @@ export class Game { this.addRandomTile(); } - mergeTitles(newRow, canMerge) { - const mergedThisMove = []; - - for (let i = 0; i < newRow.length - 1; i++) { - if (newRow[i] === newRow[i + 1]) { - newRow[i] *= 2; - newRow.splice(i + 1, 1); - canMerge[i] = false; - mergedThisMove.push(i); - } - } - - return mergedThisMove; + updateBoardAfterMoving() { + this.addRandomCellAfterMoving(); + this.updateBoard(); + this.getStatus(); } - moveLeft() { - let moved = false; - + moveHorizontal(fillWithZeros) { for (let row = 0; row < this.board.length; row++) { const currentRow = this.board[row].filter((val) => val !== 0); - const mergedRow = []; - let skip = false; + const mergedRow = []; for (let i = 0; i < currentRow.length; i++) { - if (skip) { - skip = false; - continue; - } + const currentValue = currentRow[i]; + + if (currentValue === currentRow[i + 1]) { + const doubled = currentValue * 2; - if (currentRow[i] === currentRow[i + 1]) { - mergedRow.push(currentRow[i] * 2); - this.getScore(true, currentRow[i] * 2); - skip = true; - moved = true; + mergedRow.push(doubled); + this.getScore(true, doubled); + i++; } else { - mergedRow.push(currentRow[i]); + mergedRow.push(currentValue); } } while (mergedRow.length < this.board[row].length) { - mergedRow.push(0); - } - - if (!moved) { - for (let i = 0; i < this.board[row].length; i++) { - if (this.board[row][i] !== mergedRow[i]) { - moved = true; - break; - } - } + fillWithZeros(mergedRow); } this.board[row] = mergedRow; } + } - if (moved) { - this.addRandomCellAfterMoving(); - this.updateBoard(); - this.getStatus(); - } - - return moved; + moveLeft() { + this.moveHorizontal((array) => array.push(0)); + this.updateBoardAfterMoving(); } moveRight() { - let moved = false; - - for (let row = 0; row < this.board.length; row++) { - const currentRow = this.board[row].filter((val) => val !== 0); - - const mergedRow = []; - let skip = false; - - for (let i = 0; i < currentRow.length; i++) { - if (skip) { - skip = false; - continue; - } - - if (currentRow[i] === currentRow[i + 1]) { - mergedRow.push(currentRow[i] * 2); - this.getScore(true, currentRow[i] * 2); - skip = true; - moved = true; - } else { - mergedRow.push(currentRow[i]); - } - } - - while (mergedRow.length < this.board[row].length) { - mergedRow.unshift(0); - } - - for (let i = 0; i < this.board[row].length; i++) { - if (this.board[row][i] !== mergedRow[i]) { - moved = true; - break; - } - } - - this.board[row] = mergedRow; - } - - if (moved) { - this.addRandomCellAfterMoving(); - this.updateBoard(); - this.getStatus(); - } - - return moved; + this.moveHorizontal((array) => array.unshift(0)); + this.updateBoardAfterMoving(); } moveUp() { - let moved = false; - for (let col = 0; col < this.board.length; col++) { const newColumn = this.createColumn(col); const canMerge = new Array(newColumn.length).fill(true); @@ -269,9 +180,8 @@ export class Game { ) { newColumn[i] *= 2; newColumn.splice(i + 1, 1); - moved = true; canMerge[i] = false; - this.getScore(moved, newColumn[i]); + this.getScore(true, newColumn[i]); } } @@ -279,21 +189,13 @@ export class Game { newColumn.push(0); } - moved = this.updateColumn(col, newColumn) || moved; - } - - if (moved) { - this.addRandomCellAfterMoving(); - this.updateBoard(); - this.getStatus(); + this.updateColumn(col, newColumn); } - return moved; + this.updateBoardAfterMoving(); } moveDown() { - let moved = false; - for (let col = 0; col < this.board.length; col++) { const newColumn = this.createColumn(col); const canMerge = new Array(newColumn.length).fill(true); @@ -306,9 +208,8 @@ export class Game { ) { newColumn[i] *= 2; newColumn.splice(i - 1, 1); - moved = true; canMerge[i] = false; - this.getScore(moved, newColumn[i]); + this.getScore(true, newColumn[i]); } } @@ -316,16 +217,10 @@ export class Game { newColumn.unshift(0); } - moved = this.updateColumn(col, newColumn) || moved; - } - - if (moved) { - this.addRandomCellAfterMoving(); - this.updateBoard(); - this.getStatus(); + this.updateColumn(col, newColumn); } - return moved; + this.updateBoardAfterMoving(); } /** @@ -338,46 +233,56 @@ export class Game { getStatus() { if (this.score === 0) { this.status = IDLE; - } else { - let hasEmptyCell = false; - let has2048Cell = false; - let canMove = false; - - for (let row = 0; row < this.board.length; row++) { - for (let col = 0; col < this.board[row].length; col++) { - if (this.board[row][col] === 0) { - hasEmptyCell = true; - } - - if (this.board[row][col] === 2048) { - has2048Cell = true; - } - - if ( - row < this.board.length - 1 && - this.board[row][col] === this.board[row + 1][col] - ) { - canMove = true; - } - - if ( - col < this.board[row].length - 1 && - this.board[row][col] === this.board[row][col + 1] - ) { - canMove = true; - } + + return this.status; + } + + let has2048Cell = false; + let canMove = false; + + for (let row = 0; row < this.board.length; row++) { + for (let col = 0; col < this.board[row].length; col++) { + const currentCell = this.board[row][col]; + + if (currentCell === 2048) { + has2048Cell = true; + } + + if (canMove) { + continue; + } + + if (currentCell === 0) { + canMove = true; + continue; + } + + const canMoveVertically = + row < this.board.length - 1 && + currentCell === this.board[row + 1][col]; + + const canMoveHorrizontally = + col < this.board[row].length - 1 && + currentCell === this.board[row][col + 1]; + + if (canMoveVertically || canMoveHorrizontally) { + canMove = true; } } if (has2048Cell) { this.status = WIN; this.winCallback(); - } else if (hasEmptyCell || canMove) { + break; + } + + if (canMove) { this.status = PLAYING; - } else { - this.status = LOSE; - this.loseCallback(); + break; } + + this.status = LOSE; + this.loseCallback(); } return this.status; From 75e64a9287f9c4dbfae35d90b4944b59398ad987 Mon Sep 17 00:00:00 2001 From: Iryna Mariiko Date: Wed, 27 Nov 2024 21:39:57 +0200 Subject: [PATCH 14/14] fixed bug (when wrong status displayed) --- src/modules/Game.class.js | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/modules/Game.class.js b/src/modules/Game.class.js index 3622f8135..3f7a0ca5d 100644 --- a/src/modules/Game.class.js +++ b/src/modules/Game.class.js @@ -269,18 +269,14 @@ export class Game { canMove = true; } } + } - if (has2048Cell) { - this.status = WIN; - this.winCallback(); - break; - } - - if (canMove) { - this.status = PLAYING; - break; - } - + if (has2048Cell) { + this.status = WIN; + this.winCallback(); + } else if (canMove) { + this.status = PLAYING; + } else { this.status = LOSE; this.loseCallback(); }