The following code is the beginning of an attempt to make my version of 2048 (the game) using lodash-fp. I'm used to regular lodash, but this is my first contact with the fp flavor.
It implements the action of pushing to the right the tiles of one row, using two functions:
slide
pushes the row to the right, provided there are empty spaces (represented by the value 0). In effect, this amounts to putting all the zeros on the left.merge
merges pairs of contiguous tiles of same value, generating an empty space and a new tile of doubled value.
(slide
is called a second time after merge
to clean up the zeros that may result from that step).The functions use the _.reduceRight
method, which iterates over the tiles from right to left.
import _ from "lodash/fp";
let game = [[2, 2, 0, 0], [4, 0, 4, 0], [8, 0, 0, 8], [16, 16, 0, 0]]; // Sample state
let slide = _.flow(
_.reduceRight(
(v, acc) =>
v === 0 ? [_.concat(acc[0], v), acc[1]] : [acc[0], _.concat(v, acc[1])],
[[], []]
),
_.flatten
);
let merge = _.flow(
_.reduceRight(
(v, acc) => {
acc[0].unshift(v);
if (acc[0].length === 2) {
if (acc[0][0] === acc[0][1]) {
acc[1] = _.concat(0, _.concat(acc[0][0] + acc[0][1], acc[1]));
acc[0] = [];
} else {
acc[1] = _.concat(acc[0].pop(), acc[1]);
}
}
return acc;
},
[[], []]
),
_.flatten
);
// Moves one line
let moveLine = _.flow(
slide,
merge,
slide
);
// Moves the 4 lines
let moveBoard = _.map(moveLine);
moveLine
seems to work well. For instance, moveLine(game[0])
transforms [2, 2, 0, 0]
into [0, 0, 0, 4]
.
Strangely, moveBoard(game)
(which maps moveLine
over the 4 rows) gives a weird result, getting longer on each iteration, as though the results from the previous steps were appended:
[
[0,0,0,4],
[0,0,0,0,0,0,8,4],
[0,0,0,0,0,0,0,0,0,16,8,4],
[0,0,0,0,0,0,0,0,0,0,0,0,32,16,8,4]
]
I see that the problem comes from merge
, but I really fail to see what's going on here.
change move
method to remove the first 4 elements.
for some weird reason for each iteration of merge
the acc[1] of ReduceRight as the previous array in it
this patch will fix it
let take = arr => arr.slice(0,4);
// Moves one line
let moveLine = _.flow(
slide,
merge,
take
);
here is a runkit with the implementation