From 6858227b31693d8acec64373acb5b3c6697d6631 Mon Sep 17 00:00:00 2001 From: Anastasiia-Tatarchenko Date: Thu, 14 Nov 2024 17:56:35 +0100 Subject: [PATCH 1/6] task --- src/index.html | 5 +- src/modules/Game.class.js | 287 ++++++++++++++++++++++++++++++++++++-- src/scripts/main.js | 97 ++++++++++++- 3 files changed, 372 insertions(+), 17 deletions(-) diff --git a/src/index.html b/src/index.html index aff3d1a98..cdfcfd518 100644 --- a/src/index.html +++ b/src/index.html @@ -65,6 +65,9 @@

2048

- + diff --git a/src/modules/Game.class.js b/src/modules/Game.class.js index 65cd219c9..7e75f4934 100644 --- a/src/modules/Game.class.js +++ b/src/modules/Game.class.js @@ -20,25 +20,78 @@ class Game { * If passed, the board will be initialized with the provided * initial state. */ - constructor(initialState) { - // eslint-disable-next-line no-console - console.log(initialState); + constructor( + initialState = [ + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + ], + ) { + if ( + initialState.length === 4 && + initialState.every((row) => row.length === 4) + ) { + this.initialState = initialState; + this.restart(); + } else { + throw new Error('Initial state is not valid!'); + } } - moveLeft() {} - moveRight() {} - moveUp() {} - moveDown() {} + moveLeft() { + if (this.status === 'playing') { + const result = this.moveTiles(true, false); + + if (this.isStateDifferent(result.state)) { + this.updateGame(result); + } + } + } + + moveRight() { + if (this.status === 'playing') { + const result = this.moveTiles(true, true); + + if (this.isStateDifferent(result.state)) { + this.updateGame(result); + } + } + } + + moveUp() { + if (this.status === 'playing') { + const result = this.moveTiles(false, false); + + if (this.isStateDifferent(result.state)) { + this.updateGame(result); + } + } + } + + moveDown() { + if (this.status === 'playing') { + const result = this.moveTiles(false, true); + + if (this.isStateDifferent(result.state)) { + this.updateGame(result); + } + } + } /** * @returns {number} */ - getScore() {} + getScore() { + return this.score; + } /** * @returns {number[][]} */ - getState() {} + getState() { + return this.state; + } /** * Returns the current game status. @@ -50,19 +103,229 @@ class Game { * `win` - the game is won; * `lose` - the game is lost */ - getStatus() {} + getStatus() { + return this.status; + } /** * Starts the game. */ - start() {} + start() { + this.restart(); + this.status = 'playing'; + + this.putNewNumber(); + this.putNewNumber(); + } /** * Resets the game. */ - restart() {} + restart() { + this.state = this.cloneState(this.initialState); + this.score = 0; + this.status = 'idle'; + this.firstMoveMade = false; + } // Add your own methods here + cloneState(state) { + const newState = []; + + for (let row = 0; row < state.length; row++) { + newState.push([...state[row]]); + } + + return newState; + } + + isStateDifferent(newState) { + for (let row = 0; row < this.state.length; row++) { + for (let column = 0; column < this.state[row].length; column++) { + if (this.state[row][column] !== newState[row][column]) { + return true; + } + } + } + + return false; + } + + updateGame(result) { + this.state = result.state; + this.score += result.score; + this.firstMoveMade = true; + this.putNewNumber(); + + if (this.isGameOver()) { + this.status = 'lose'; + } else if (this.isGameWon()) { + this.status = 'win'; + } + } + + getFirstMoveMade() { + return this.firstMoveMade; + } + + getAvailableCell() { + const cell = []; + + this.state.forEach((row, y) => { + row.forEach((number, x) => { + if (!number) { + cell.push({ x, y }); + } + }); + }); + + return cell; + } + + getRandomElement(arr) { + const randomIndex = Math.floor(Math.random() * arr.length); + + return arr[randomIndex]; + } + + generateNumber() { + return Math.floor(Math.random() * 10) === 0 ? 4 : 2; + } + + putNewNumber() { + const availableCell = this.getAvailableCell(); + const randomCell = this.getRandomElement(availableCell); + + this.state[randomCell.y][randomCell.x] = this.generateNumber(); + } + + isGameOver() { + if (this.getAvailableCell().length === 0) { + const directions = [ + { horizontal: false, forward: false }, + { horizontal: true, forward: true }, + { horizontal: false, forward: true }, + { horizontal: true, forward: false }, + ]; + + return directions.every(({ horizontal, forward }) => { + const newState = this.moveTiles(horizontal, forward).state; + + return this.isStateDifferent(newState); + }); + } + + return false; + } + + isGameWon() { + return this.state.flat().includes(2048); + } + + getCellCoords(horizontal, firstCoord, position) { + return horizontal + ? { row: firstCoord, column: position } + : { row: position, column: firstCoord }; + } + + moveTiles(horizontal, forward, addScore) { + const state = this.cloneState(this.state); + let score = 0; + + const rowLength = state[0].length; + const columnLength = state.length; + let firstCoordLength; + let secondCoordLength; + + if (horizontal) { + firstCoordLength = columnLength; + secondCoordLength = rowLength; + } else { + firstCoordLength = rowLength; + secondCoordLength = columnLength; + } + + let initialSecondCoord; + let startOfStripe; + let endOfStirpe; + let step; + + if (forward) { + initialSecondCoord = secondCoordLength - 2; + startOfStripe = -1; + endOfStirpe = secondCoordLength; + step = 1; + } else { + initialSecondCoord = 1; + startOfStripe = secondCoordLength; + endOfStirpe = -1; + step = -1; + } + + for (let firstCoord = 0; firstCoord < firstCoordLength; firstCoord++) { + const mergedInStripe = Array(secondCoordLength).fill(false); + + for ( + let secondCoord = initialSecondCoord; + secondCoord !== startOfStripe; + secondCoord -= step + ) { + let merged = false; + let position = secondCoord; + + let currentCellCoords = this.getCellCoords( + horizontal, + firstCoord, + position, + ); + let nextCellCoords = this.getCellCoords( + horizontal, + firstCoord, + position + step, + ); + + while ( + position + step !== endOfStirpe && + (state[nextCellCoords.row][nextCellCoords.column] === 0 || + (state[nextCellCoords.row][nextCellCoords.column] === + state[currentCellCoords.row][currentCellCoords.column] && + !mergedInStripe[position + step] && + !merged)) + ) { + if (state[nextCellCoords.row][nextCellCoords.column] > 0) { + merged = true; + score += state[nextCellCoords.row][nextCellCoords.column] * 2; + } + + state[nextCellCoords.row][nextCellCoords.column] += + state[currentCellCoords.row][currentCellCoords.column]; + state[currentCellCoords.row][currentCellCoords.column] = 0; + position += step; + + currentCellCoords = this.getCellCoords( + horizontal, + firstCoord, + position, + ); + + nextCellCoords = this.getCellCoords( + horizontal, + firstCoord, + position + step, + ); + } + + if (merged) { + mergedInStripe[position] = true; + } + } + } + + return { + state: state, + score: score, + }; + } } module.exports = Game; diff --git a/src/scripts/main.js b/src/scripts/main.js index dc7f045a3..d1544379f 100644 --- a/src/scripts/main.js +++ b/src/scripts/main.js @@ -1,7 +1,96 @@ '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 +function updateTable(state) { + const fieldRows = document.querySelectorAll('.field-row'); + + fieldRows.forEach((rowElement, rowIndex) => { + const rowState = state[rowIndex]; + + rowState.forEach((cellState, columnIndex) => { + const cellElement = rowElement.children[columnIndex]; + + cellElement.className = `field-cell field-cell--${cellState}`; + cellElement.innerText = cellState > 0 ? cellState : ''; + + if (cellState > 0) { + cellElement.classList.add('merge'); + + setTimeout(() => cellElement.classList.remove('merge'), 600); + } + }); + }); +} + +function updateScore(score) { + document.querySelector('.game-score').innerText = score; +} + +function updateButton(firstMoveMade) { + if (firstMoveMade) { + button.className = 'button restart'; + button.innerText = 'Restart'; + } else { + button.className = 'button start'; + button.innerText = 'Start'; + } +} + +function updateMessage(gameStatus) { + const messageClasses = { + idle: 'message-start', + win: 'message-win', + lose: 'message-lose', + }; + + document.querySelectorAll('.message').forEach((message) => { + message.classList.add('hidden'); + }); + + const messageClass = messageClasses[gameStatus]; + + if (messageClass) { + document.querySelector(`.${messageClass}`).classList.remove('hidden'); + } +} + +function update() { + updateTable(game.getState()); + updateScore(game.getScore()); + updateButton(game.getFirstMoveMade()); + updateMessage(game.getStatus()); +} + +const button = document.querySelector('.button'); + +button.addEventListener('click', () => { + switch (button.innerText) { + case 'Start': + game.start(); + break; + case 'Restart': + game.restart(); + } + + update(); +}); + +document.addEventListener('keydown', (e) => { + const actions = { + ArrowUp: () => game.moveUp(), + ArrowRight: () => game.moveRight(), + ArrowDown: () => game.moveDown(), + ArrowLeft: () => game.moveLeft(), + }; + + const action = actions[e.key]; + + if (action) { + e.preventDefault(); + action(); + } + + update(); +}); From 364ad7bd60d3a297b6d421f00210c5f7836f3b01 Mon Sep 17 00:00:00 2001 From: Anastasiia-Tatarchenko Date: Thu, 14 Nov 2024 19:33:55 +0100 Subject: [PATCH 2/6] problem_wit_the_lose_command --- src/modules/Game.class.js | 7 +++++++ src/scripts/main.js | 37 ++++++++++++++++++++++--------------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/modules/Game.class.js b/src/modules/Game.class.js index 7e75f4934..043a6758a 100644 --- a/src/modules/Game.class.js +++ b/src/modules/Game.class.js @@ -20,6 +20,13 @@ class Game { * If passed, the board will be initialized with the provided * initial state. */ + + static STATUS = { + playing: 'playing', + win: 'win', + lose: 'lose', + }; + constructor( initialState = [ [0, 0, 0, 0], diff --git a/src/scripts/main.js b/src/scripts/main.js index d1544379f..604c5c3b5 100644 --- a/src/scripts/main.js +++ b/src/scripts/main.js @@ -3,6 +3,10 @@ const Game = require('../modules/Game.class'); const game = new Game(); +const startMessage = document.querySelector('.message-start'); +const loseMessage = document.querySelector('.message-lose'); +const winMessage = document.querySelector('.message-win'); + function updateTable(state) { const fieldRows = document.querySelectorAll('.field-row'); @@ -38,21 +42,24 @@ function updateButton(firstMoveMade) { } } -function updateMessage(gameStatus) { - const messageClasses = { - idle: 'message-start', - win: 'message-win', - lose: 'message-lose', - }; - - document.querySelectorAll('.message').forEach((message) => { - message.classList.add('hidden'); - }); - - const messageClass = messageClasses[gameStatus]; - - if (messageClass) { - document.querySelector(`.${messageClass}`).classList.remove('hidden'); +function updateMessage() { + switch (game.getStatus()) { + case Game.STATUS.idle: + startMessage.classList.remove('hidden'); + winMessage.classList.add('hidden'); + loseMessage.classList.add('hidden'); + break; + case Game.STATUS.playing: + startMessage.classList.add('hidden'); + break; + case Game.STATUS.win: + winMessage.classList.remove('hidden'); + break; + case Game.STATUS.lose: + loseMessage.classList.remove('hidden'); + break; + default: + break; } } From 089e046cfc0595fda911e1dcfb7d4c2209b4dcad Mon Sep 17 00:00:00 2001 From: Anastasiia-Tatarchenko Date: Wed, 20 Nov 2024 12:52:07 +0100 Subject: [PATCH 3/6] task_done --- src/modules/Game.class.js | 2 ++ src/styles/main.scss | 48 ++++++++++++++++++++------------------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/modules/Game.class.js b/src/modules/Game.class.js index 043a6758a..9ee42a54f 100644 --- a/src/modules/Game.class.js +++ b/src/modules/Game.class.js @@ -46,6 +46,8 @@ class Game { } } + static WIN_COUNT = 2048; + moveLeft() { if (this.status === 'playing') { const result = this.moveTiles(true, false); diff --git a/src/styles/main.scss b/src/styles/main.scss index c43f37dcf..4c1f7cd62 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -4,7 +4,7 @@ body { align-items: center; justify-content: center; min-height: 100vh; - background: #fbf8ef; + background: #7b68ee; font-family: sans-serif; font-size: 24px; font-weight: 900; @@ -22,61 +22,63 @@ body { user-select: none; &--2 { - background: #eee4da; + background: #b0c4de; + color: #000; } &--4 { - background: #ede0c8; + background: #b0e0e6; + color: #000; } &--8 { - background: #f2b179; - color: #f9f6f2; + background: #7fffd4; + color: #000; } &--16 { - background: #f59563; - color: #f9f6f2; + background: #add8e6; + color: #000; } &--32 { - background: #f67c5f; - color: #f9f6f2; + background: #40e0d0; + color: #000; } &--64 { - background: #f65e3b; - color: #f9f6f2; + background: #87ceeb; + color: #000; } &--128 { - background: #edcf72; - color: #f9f6f2; + background: #48d1cc; + color: #000; } &--256 { - background: #edcc61; - color: #f9f6f2; + background: #87cefa; + color: #000; } &--512 { - background: #edc850; - color: #f9f6f2; + background: #00ced1; + color: #000; } &--1024 { - background: #edc53f; - color: #f9f6f2; + background: #00bfff; + color: #000; } &--2048 { - background: #edc22e; - color: #f9f6f2; + background: #4682b4; + color: #000; } } .game-field { - background: #bbada0; + background: #00f; border-spacing: 10px; border-radius: 5px; } @@ -147,7 +149,7 @@ h1 { } .restart { - background: #f1b2b2; + background: #f4a460; &:hover { background: #f87474; From b3b2b780e2c98c0802afd482c038168da810ebf1 Mon Sep 17 00:00:00 2001 From: Anastasiia-Tatarchenko Date: Wed, 20 Nov 2024 13:27:51 +0100 Subject: [PATCH 4/6] task_done1 --- src/modules/Game.class.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/modules/Game.class.js b/src/modules/Game.class.js index 9ee42a54f..42568b536 100644 --- a/src/modules/Game.class.js +++ b/src/modules/Game.class.js @@ -21,12 +21,6 @@ class Game { * initial state. */ - static STATUS = { - playing: 'playing', - win: 'win', - lose: 'lose', - }; - constructor( initialState = [ [0, 0, 0, 0], @@ -46,8 +40,6 @@ class Game { } } - static WIN_COUNT = 2048; - moveLeft() { if (this.status === 'playing') { const result = this.moveTiles(true, false); From 95479bb7f1c8c525c26125d848d05ed052fbdda2 Mon Sep 17 00:00:00 2001 From: Anastasiia-Tatarchenko Date: Thu, 21 Nov 2024 19:51:54 +0100 Subject: [PATCH 5/6] fixed_two_erros --- src/images/2048.png | Bin 0 -> 16467 bytes src/index.html | 5 +++++ src/scripts/main.js | 37 +++++++++++++++---------------------- 3 files changed, 20 insertions(+), 22 deletions(-) create mode 100644 src/images/2048.png diff --git a/src/images/2048.png b/src/images/2048.png new file mode 100644 index 0000000000000000000000000000000000000000..ba4c0d48c47436d54e217764fe5ec1c1a24d548a GIT binary patch literal 16467 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 2048 + { + message.classList.add('hidden'); + }); + + const messageClass = messageClasses[gameStatus]; + + if (messageClass) { + document.querySelector(`.${messageClass}`).classList.remove('hidden'); } } From 43802f78b1faf33169b3db4112b0ec79b44156f9 Mon Sep 17 00:00:00 2001 From: Anastasiia-Tatarchenko Date: Thu, 21 Nov 2024 22:22:35 +0100 Subject: [PATCH 6/6] fixed_all_the_errors --- src/index.html | 6 +- src/modules/Game.class.js | 447 +++++++++++++++++++++++++++++++------- 2 files changed, 374 insertions(+), 79 deletions(-) diff --git a/src/index.html b/src/index.html index db4bea3ea..2601f24df 100644 --- a/src/index.html +++ b/src/index.html @@ -7,11 +7,11 @@ content="width=device-width, initial-scale=1.0" /> 2048 - + /> { - row.forEach((number, x) => { - if (!number) { - cell.push({ x, y }); + getAvailableSpace() { + return this.state.reduce((space, row, rowIndex) => { + row.forEach((cell, cellIndex) => { + if (cell === 0) { + space.push({ + x: cellIndex, + y: rowIndex, + }); } }); - }); - return cell; + return space; + }, []); } - getRandomElement(arr) { - const randomIndex = Math.floor(Math.random() * arr.length); - - return arr[randomIndex]; + getRandomElement(space) { + return space[Math.floor(Math.random() * space.length)]; } generateNumber() { @@ -194,39 +150,45 @@ class Game { } putNewNumber() { - const availableCell = this.getAvailableCell(); - const randomCell = this.getRandomElement(availableCell); + const availableSpace = this.getAvailableSpace(); + const randomSpace = this.getRandomElement(availableSpace); - this.state[randomCell.y][randomCell.x] = this.generateNumber(); + this.state[randomSpace.y][randomSpace.x] = this.generateNumber(); } isGameOver() { - if (this.getAvailableCell().length === 0) { - const directions = [ - { horizontal: false, forward: false }, - { horizontal: true, forward: true }, - { horizontal: false, forward: true }, - { horizontal: true, forward: false }, - ]; - - return directions.every(({ horizontal, forward }) => { - const newState = this.moveTiles(horizontal, forward).state; - - return this.isStateDifferent(newState); - }); + if (this.getAvailableSpace().length === 0) { + if ( + this.isStateDifferent(this.moveTiles(false, false).state) || + this.isStateDifferent(this.moveTiles(true, true).state) || + this.isStateDifferent(this.moveTiles(false, true).state) || + this.isStateDifferent(this.moveTiles(true, false).state) + ) { + return false; + } + + return true; } return false; } isGameWon() { - return this.state.flat().includes(2048); + return this.state.some((row) => row.some((cell) => cell === 2048)); } getCellCoords(horizontal, firstCoord, position) { - return horizontal - ? { row: firstCoord, column: position } - : { row: position, column: firstCoord }; + if (horizontal) { + return { + row: firstCoord, + column: position, + }; + } + + return { + row: position, + column: firstCoord, + }; } moveTiles(horizontal, forward, addScore) { @@ -330,3 +292,336 @@ class Game { } module.exports = Game; + +// '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. +// */ +// 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 = [ +// [0, 0, 0, 0], +// [0, 0, 0, 0], +// [0, 0, 0, 0], +// [0, 0, 0, 0], +// ], +// ) { +// if ( +// initialState.length === 4 && +// initialState.every((row) => row.length === 4) +// ) { +// this.initialState = initialState; +// this.restart(); +// } else { +// throw new Error('Initial state is not valid!'); +// } +// } + +// moveLeft() { +// if (this.status === 'playing') { +// const result = this.moveTiles(true, false); + +// if (this.isStateDifferent(result.state)) { +// this.updateGame(result); +// } +// } +// } + +// moveRight() { +// if (this.status === 'playing') { +// const result = this.moveTiles(true, true); + +// if (this.isStateDifferent(result.state)) { +// this.updateGame(result); +// } +// } +// } + +// moveUp() { +// if (this.status === 'playing') { +// const result = this.moveTiles(false, false); + +// if (this.isStateDifferent(result.state)) { +// this.updateGame(result); +// } +// } +// } + +// moveDown() { +// if (this.status === 'playing') { +// const result = this.moveTiles(false, true); + +// if (this.isStateDifferent(result.state)) { +// this.updateGame(result); +// } +// } +// } + +// /** +// * @returns {number} +// */ +// getScore() { +// return this.score; +// } + +// /** +// * @returns {number[][]} +// */ +// getState() { +// return this.state; +// } + +// /** +// * 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() { +// return this.status; +// } + +// /** +// * Starts the game. +// */ +// start() { +// this.restart(); +// this.status = 'playing'; + +// this.putNewNumber(); +// this.putNewNumber(); +// } + +// /** +// * Resets the game. +// */ +// restart() { +// this.state = this.cloneState(this.initialState); +// this.score = 0; +// this.status = 'idle'; +// this.firstMoveMade = false; +// } + +// // Add your own methods here +// cloneState(state) { +// const newState = []; + +// for (let row = 0; row < state.length; row++) { +// newState.push([...state[row]]); +// } + +// return newState; +// } + +// isStateDifferent(newState) { +// for (let row = 0; row < this.state.length; row++) { +// for (let column = 0; column < this.state[row].length; column++) { +// if (this.state[row][column] !== newState[row][column]) { +// return true; +// } +// } +// } + +// return false; +// } + +// updateGame(result) { +// this.state = result.state; +// this.score += result.score; +// this.firstMoveMade = true; +// this.putNewNumber(); + +// if (this.isGameOver()) { +// this.status = 'lose'; +// } else if (this.isGameWon()) { +// this.status = 'win'; +// } +// } + +// getFirstMoveMade() { +// return this.firstMoveMade; +// } + +// getAvailableCell() { +// const cell = []; + +// this.state.forEach((row, y) => { +// row.forEach((number, x) => { +// if (!number) { +// cell.push({ x, y }); +// } +// }); +// }); + +// return cell; +// } + +// getRandomElement(arr) { +// const randomIndex = Math.floor(Math.random() * arr.length); + +// return arr[randomIndex]; +// } + +// generateNumber() { +// return Math.floor(Math.random() * 10) === 0 ? 4 : 2; +// } + +// putNewNumber() { +// const availableCell = this.getAvailableCell(); +// const randomCell = this.getRandomElement(availableCell); + +// this.state[randomCell.y][randomCell.x] = this.generateNumber(); +// } + +// isGameOver() { +// if (this.getAvailableCell().length === 0) { +// const directions = [ +// { horizontal: false, forward: false }, +// { horizontal: true, forward: true }, +// { horizontal: false, forward: true }, +// { horizontal: true, forward: false }, +// ]; + +// return directions.every(({ horizontal, forward }) => { +// const newState = this.moveTiles(horizontal, forward).state; + +// return this.isStateDifferent(newState); +// }); +// } + +// return false; +// } + +// isGameWon() { +// return this.state.flat().includes(2048); +// } + +// getCellCoords(horizontal, firstCoord, position) { +// return horizontal +// ? { row: firstCoord, column: position } +// : { row: position, column: firstCoord }; +// } + +// moveTiles(horizontal, forward, addScore) { +// const state = this.cloneState(this.state); +// let score = 0; + +// const rowLength = state[0].length; +// const columnLength = state.length; +// let firstCoordLength; +// let secondCoordLength; + +// if (horizontal) { +// firstCoordLength = columnLength; +// secondCoordLength = rowLength; +// } else { +// firstCoordLength = rowLength; +// secondCoordLength = columnLength; +// } + +// let initialSecondCoord; +// let startOfStripe; +// let endOfStirpe; +// let step; + +// if (forward) { +// initialSecondCoord = secondCoordLength - 2; +// startOfStripe = -1; +// endOfStirpe = secondCoordLength; +// step = 1; +// } else { +// initialSecondCoord = 1; +// startOfStripe = secondCoordLength; +// endOfStirpe = -1; +// step = -1; +// } + +// for (let firstCoord = 0; firstCoord < firstCoordLength; firstCoord++) { +// const mergedInStripe = Array(secondCoordLength).fill(false); + +// for ( +// let secondCoord = initialSecondCoord; +// secondCoord !== startOfStripe; +// secondCoord -= step +// ) { +// let merged = false; +// let position = secondCoord; + +// let currentCellCoords = this.getCellCoords( +// horizontal, +// firstCoord, +// position, +// ); +// let nextCellCoords = this.getCellCoords( +// horizontal, +// firstCoord, +// position + step, +// ); + +// while ( +// position + step !== endOfStirpe && +// (state[nextCellCoords.row][nextCellCoords.column] === 0 || +// (state[nextCellCoords.row][nextCellCoords.column] === +// state[currentCellCoords.row][currentCellCoords.column] && +// !mergedInStripe[position + step] && +// !merged)) +// ) { +// if (state[nextCellCoords.row][nextCellCoords.column] > 0) { +// merged = true; +// score += state[nextCellCoords.row][nextCellCoords.column] * 2; +// } + +// state[nextCellCoords.row][nextCellCoords.column] += +// state[currentCellCoords.row][currentCellCoords.column]; +// state[currentCellCoords.row][currentCellCoords.column] = 0; +// position += step; + +// currentCellCoords = this.getCellCoords( +// horizontal, +// firstCoord, +// position, +// ); + +// nextCellCoords = this.getCellCoords( +// horizontal, +// firstCoord, +// position + step, +// ); +// } + +// if (merged) { +// mergedInStripe[position] = true; +// } +// } +// } + +// return { +// state: state, +// score: score, +// }; +// } +// } + +// module.exports = Game;