Search code examples
javascriptarrays2048

How can I implement the merge and score functionality of 2048?


Here's the problem, simplified to the problem that I'm facing.

I have an object, consisting of a score counter and an arbitrary 1D array of elements, filled with numbers:

{ score: 0, board: [4, 2, 2] }

I am looking for a function, that will do a 2048-ish move left (as if these numbers are tiles are on one row of a 2048 game board), and will also add score to the counter (merging into an 8 adds 8 to the score).

I have searched, and found functions, that do this, but i found none that also counted score. how can I accomplish this?

Here are some test cases:

{ score: 0, board: []          } => { score: 0,    board: []     }
{ score: 0, board: [2,2]       } => { score: 4,    board: [4]    }
{ score: 4, board: [2,2,2]     } => { score: 8,    board: [4,2]  }
{ score: 6, board: [4,2,2]     } => { score: 10,   board: [4,4]  }
{ score: 0, board: [2,2,2,2]   } => { score: 8,    board: [4,4]  }
{ score: 8, board: [4,4]       } => { score: 16,   board: [8]    }
{ score: 2, board: [8,8]       } => { score: 18,   board: [16]   }
{ score: 0, board: [16,16]     } => { score: 32,   board: [32]   }
{ score: 0, board: [1024,1024] } => { score: 2048, board: [2048] }

Solution

  • A comment under my post gave me an idea on how to approach this, and I wrote a function, that has passed all of my tests:

    const mergeFunc = ({score, board}) => {
      let returnObject = {
        score: score,
        board: [...board] // just in case
      };
      for(let i=0; i<returnObject.board.length-1; i++)
      // parsing through the array left to right,
        if(returnObject.board[i] === returnObject.board[i+1]){
        // if an element is the same as the element to it's right,
          returnObject.score += returnObject.board[i]*2;
          // add the value of the new tile to the score,
          returnObject.board.splice(i,2,returnObject.board[i]*2)
          // and merge the two tiles.
        }
      return returnObject;
    }
    
    console.log(mergeFunc({score:0,board:[2,2,2,2]}))

    The function iterates over the array left to right, merging any two identical neighbouring numbers that it finds using .splice(), and adds the value of the new cell to the score.

    Here's the function, edited to work for 2D arrays (though, it still only merges left):

    const mergeFunc2D = ({score, board}) => {
      let returnObject = {
        score: score || 0,
        board: board.map(x=>x.filter(y=>y!==undefined))
      };
      for(let j=0; j<returnObject.board.length; j++) { // for each array:
        for(let i=0; i<returnObject.board[j].length-1; i++) // parsing through the array left to right,
          if(returnObject.board[j][i] === returnObject.board[j][i+1]){ // if an element is the same as the element to it's right,
            returnObject.score += returnObject.board[j][i]*2; // add the value of the new tile to the score,
            returnObject.board[j].splice(i,2,returnObject.board[j][i]*2) // and merge the two tiles.
          }
          // optionally, cut to specific width and pad with undefs
          returnObject.board[j] = returnObject.board[j].concat([undefined,undefined,undefined,undefined]).splice(0,4);
      }
      return returnObject;
    }
    console.log(mergeFunc2D({
      board:[
        [2,2,undefined,undefined],
        [2,undefined,2,2],
        [2,2,2,2],
        [2,2,4,4],
      ]
    }))