Skip to content

Commit

Permalink
resolution game_2048
Browse files Browse the repository at this point in the history
  • Loading branch information
LuckaeTha committed Dec 11, 2024
1 parent a6d3781 commit c5c73f6
Show file tree
Hide file tree
Showing 6 changed files with 426 additions and 19 deletions.
29 changes: 29 additions & 0 deletions .github/workflows/test.yml-template
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ You can change the HTML/CSS layout if you need it.
## Deploy and Pull Request
1. Replace `<your_account>` with your Github username in the link
- [DEMO LINK](https://<your_account>.github.io/js_2048_game/)
- [DEMO LINK](https://14lucas-mendes.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;
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
292 changes: 281 additions & 11 deletions src/modules/Game.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,93 @@ class Game {
* If passed, the board will be initialized with the provided
* initial state.
*/
constructor(initialState) {
constructor(
initialState = [
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
],
) {
// eslint-disable-next-line no-console
console.log(initialState);
this.state = 'idle';
this.score = 0;
this.initialState = initialState;
}

moveLeft() {}
moveRight() {}
moveUp() {}
moveDown() {}
moveLeft() {
if (this.state !== 'idle') {
const moveTheLeft = this.initialState.map((row) => mergeToTheLeft(row));

this.state = loseWinState(moveTheLeft);

this.score += calculateScore(this.initialState, moveTheLeft);

const newCellAdded = addNewCellRandomCell(moveTheLeft, 1);

this.initialState = newCellAdded;

return this.initialState;
}
}
moveRight() {
if (this.state !== 'idle') {
const moveTheRight = this.initialState.map((row) => mergeToTheRight(row));

this.state = loseWinState(moveTheRight);

this.score += calculateScore(this.initialState, moveTheRight);

const newCellAdded = addNewCellRandomCell(moveTheRight, 1);

this.initialState = newCellAdded;

return this.initialState;
}
}
moveUp() {
if (this.state !== 'idle') {
const moveAllNonZeroToTheUp = mergeUp(this.initialState);

this.state = loseWinState(moveAllNonZeroToTheUp);

this.score += calculateScore(this.initialState, moveAllNonZeroToTheUp);

const newCellAdded = addNewCellRandomCell(moveAllNonZeroToTheUp, 1);

this.initialState = newCellAdded;

return this.initialState;
}
}
moveDown() {
if (this.state !== 'idle') {
const moveAllNonZeroToTheDown = mergeDown(this.initialState);

this.score += calculateScore(this.initialState, moveAllNonZeroToTheDown);
this.state = loseWinState(moveAllNonZeroToTheDown);

const newCellAdded = addNewCellRandomCell(moveAllNonZeroToTheDown, 1);

this.initialState = newCellAdded;

return this.initialState;
}
}

/**
* @returns {number}
*/
getScore() {}
getScore() {
return this.score;
}

/**
* @returns {number[][]}
*/
getState() {}
getState() {
return this.initialState;
}

/**
* Returns the current game status.
Expand All @@ -50,19 +118,221 @@ class Game {
* `win` - the game is won;
* `lose` - the game is lost
*/
getStatus() {}
getStatus() {
return this.state;
}

/**
* Starts the game.
*/
start() {}
start() {
const allInitialDateIsZero = this.initialState
.flat()
.every((value) => value === 0);

const returnToInitialArray = allInitialDateIsZero
? addNewCellRandomCell(this.initialState, 2)
: addNewCellRandomCell(this.initialState, 1);

this.initialState = returnToInitialArray;
this.score = 0;
this.state = 'playing';

return this.initialState;
}

/**
* Resets the game.
*/
restart() {}
restart() {
this.initialState = [
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
];
this.score = 0;
this.state = 'idle';

return this.initialState;
}

// Add your own methods here
}

function addNewCellRandomCell(initialState, qntOfRandomCellsToAdd) {
const flatGameInARow = initialState.flat();
const availableIndices = flatGameInARow
.map((value, i) => (value === 0 ? i : null))
.filter((value) => value !== null);

if (availableIndices.length === 0) {
return initialState;
}

for (let i = 0; i < qntOfRandomCellsToAdd; i++) {
if (availableIndices.length === 0) {
break;
}

const randomIndex = Math.floor(Math.random() * availableIndices.length);
const indexToAdd = availableIndices.splice(randomIndex, 1)[0];
const randomValue = Math.random() < 0.9 ? 2 : 4;

flatGameInARow[indexToAdd] = randomValue;
}

const returnToInitialArray = [];

while (flatGameInARow.length) {
returnToInitialArray.push(flatGameInARow.splice(0, 4));
}

return returnToInitialArray;
}

function mergeToTheLeft(result) {
for (let i = 0; i < result.length - 1; i++) {
if (result[i] === result[i + 1] && result[i] !== 0) {
result[i] *= 2;
result[i + 1] = 0;
}
}

const filtered = result.filter((num) => num !== 0);

while (filtered.length < result.length) {
filtered.push(0);
}

return filtered;
}

function mergeToTheRight(result) {
let nonZeroValues = result.filter((value) => value !== 0);

for (let i = nonZeroValues.length - 1; i > 0; i--) {
if (nonZeroValues[i] === nonZeroValues[i - 1]) {
nonZeroValues[i] *= 2;
nonZeroValues[i - 1] = 0;
}
}
// Remove zeros again after merging
nonZeroValues = nonZeroValues.filter((value) => value !== 0);

// Add zeros to the left to maintain the row length
while (nonZeroValues.length < result.length) {
nonZeroValues.unshift(0);
}

return nonZeroValues;
}

function mergeDown(initialState) {
const result = initialState.map((col) => [...col]);

for (let col = 0; col < result[0].length; col++) {
const column = result.map((row) => row[col]);

for (let i = column.length - 1; i > 0; i--) {
if (column[i] === column[i - 1] && column[i] !== 0) {
column[i] *= 2;
column[i - 1] = 0;
}
}

const filtered = column.filter((num) => num !== 0);

while (filtered.length < column.length) {
filtered.unshift(0);
}

for (let i = 0; i < result.length; i++) {
result[i][col] = filtered[i];
}
}

return result;
}

function mergeUp(initialState) {
const result = initialState.map((col) => [...col]);

for (let col = 0; col < result[0].length; col++) {
const column = result.map((row) => row[col]);

for (let i = 0; i < column.length - 1; i++) {
if (column[i] === column[i + 1] && column[i] !== 0) {
column[i] *= 2;
column[i + 1] = 0;
}
}

const filtered = column.filter((num) => num !== 0);

while (filtered.length < column.length) {
filtered.push(0);
}

for (let i = 0; i < result.length; i++) {
result[i][col] = filtered[i];
}
}

return result;
}

function checkIfWin(initialState) {
for (let i = 0; i < initialState.length; i++) {
for (let j = 0; j < initialState[i].length; j++) {
if (initialState[i][j] === 2048) {
return true;
}
}
}

return false;
}

function checkIfLose(initialState) {
for (let i = 0; i < initialState.length; i++) {
for (let j = 0; j < initialState[i].length; j++) {
if (initialState[i][j] === 0) {
return false;
}
}
}

return true;
}

function loseWinState(initialState) {
const lose = checkIfLose(initialState);
const win = checkIfWin(initialState);

if (lose) {
return 'lose';
}

if (win) {
return 'win';
}

return 'playing';
}

function calculateScore(initialState, finalState) {
let score = 0;

for (let i = 0; i < initialState.length; i++) {
for (let j = 0; j < initialState[i].length; j++) {
if (finalState[i][j] > initialState[i][j]) {
score += finalState[i][j];
}
}
}

return score;
}

module.exports = Game;
Loading

0 comments on commit c5c73f6

Please sign in to comment.