У меня есть матрица 4x4, как в игре 2048, и мне нужно вывести результат одного хода вправо. Например, у нас есть матрица:
0 0 2 2
4 4 8 4
64 64 8 4
16 8 64 8
Result is:
0 0 0 4
0 8 8 4
0 128 8 4
16 8 64 8
Мой код:
function solution(x){
for (let i = 0; i < x.length; i++){
for (let j = 0; j < x.length; j++){
if (x[i][j] == x[i][j+1]){
x[i][j+1] = x[i][j+1] * 2;
x[i][j] = 0;
}
}
}
return JSON.stringify(x)
}
console.info(solution([[0,0,2,2], [4,4,8,4], [64,64,8,4], [16,8,64,8]]));
console.info(solution([[2,2,4,8],[8,8,64,64],[64,8,16,8],[8,8,8,8]]))
console.info(solution([[64,64,64,64],[8,8,8,8],[4,4,4,4],[2,2,2,2]]))
console.info(solution([[0,0,4,4],[4,8,4,8],[8,8,8,8],[64,8,16,8]]))
console.info(solution([[2,0,4,4],[4,4,4,4],[8,0,0,8],[0,64,64,64]]))
Во второй версии я получаю неправильный результат в первой строке [0,0,0,16], правильный результат [0, 4, 4, 8]
@Кайидо [0, 8, 0, 8]
затем выполните итерацию справа налево, как это сделал @corschdi (они даже добавили выравнивание вправо, но если вы удалите его, вы получите ожидаемые результаты.
Вы изменяете числа впереди и тогда проверяете следующее. Таким образом, вы фактически создаете промежуточный результат и окончательный результат, поэтому, в некотором смысле, является правильный:
[ 2, 2, 4, 8] -> [ 0, 4, 4, 8 ] -> [ 0, 0, 8, 8 ] -> [ 0, 0, 0, 16 ]
^ ^ ^ ^ ^ ^ ^
Если вы хотите игнорировать изменения, сделанные в том же прогоне, вы можете увеличить j
на 1
, как только обнаружите изменение:
function solution(x) {
for (let i = 0; i < x.length; i++) {
for (let j = 0; j < x.length; j++) {
if (x[i][j] == x[i][j + 1] && x[i][j] !== 0) {
x[i][j + 1] = x[i][j] * 2;
x[i][j] = 0;
j += 1;
}
}
}
return JSON.stringify(x)
}
console.info(solution([[0,0,2,2], [4,4,8,4], [64,64,8,4], [16,8,64,8]]));
console.info(solution([[2,2,4,8],[8,8,64,64],[64,8,16,8],[8,8,8,8]]))
console.info(solution([[64,64,64,64],[8,8,8,8],[4,4,4,4],[2,2,2,2]]))
console.info(solution([[0,0,4,4],[4,8,4,8],[8,8,8,8],[64,8,16,8]]))
console.info(solution([[2,0,4,4],[4,4,4,4],[8,0,0,8],[0,64,64,64]]))
Если вы просто хотите 1 изменение в строке, вы можете использовать break
break
, обновляется только 1 для каждой строкиfunction solution(x) {
for (let i = 0; i < x.length; i++) {
for (let j = 0; j < x.length; j++) {
if (x[i][j] == x[i][j + 1] && x[i][j] !== 0) {
x[i][j + 1] = x[i][j] * 2;
x[i][j] = 0;
// If you only want one move, you can break here
break;
}
}
}
return JSON.stringify(x)
}
console.info(solution([[0,0,2,2], [4,4,8,4], [64,64,8,4], [16,8,64,8]]));
console.info(solution([[2,2,4,8],[8,8,64,64],[64,8,16,8],[8,8,8,8]]))
console.info(solution([[64,64,64,64],[8,8,8,8],[4,4,4,4],[2,2,2,2]]))
console.info(solution([[0,0,4,4],[4,8,4,8],[8,8,8,8],[64,8,16,8]]))
console.info(solution([[2,0,4,4],[4,4,4,4],[8,0,0,8],[0,64,64,64]]))
Они на самом деле хотят изменить на месте... [4,4,4,4] должно быть [0,8,0,8] (или [0,0,8,8] если выровнено)
А, спасибо за наводку. Не видел этого дополнительного требования. Я быстро обновлю свой ответ.
@ user3297291 Спасибо!
Если вы хотите переместить числа вправо, вам нужно пройти массив справа налево. Кроме того, в 2048 году вам нужно будет перемещать все числа вправо после каждого слияния.
Это будет работать:
function solution(x) {
for (let i = 0; i < x.length; i++) {
for (let j = x.length - 1; j >= 0; j--) {
if (x[i][j - 1] == x[i][j]) {
x[i][j] = x[i][j] * 2;
// move all numbers on the left to the right by one
if (j > 1) {
for (let k = j - 1; k > 0; k--) {
x[i][k] = x[i][k - 1];
}
}
x[i][0] = 0;
}
}
}
return JSON.stringify(x)
}
console.info(solution([
[0, 0, 2, 2],
[4, 4, 8, 4],
[64, 64, 8, 4],
[16, 8, 64, 8]
]));
console.info(solution([
[2, 2, 4, 8],
[8, 8, 64, 64],
[64, 8, 16, 8],
[8, 8, 8, 8]
]))
console.info(solution([
[64, 64, 64, 64],
[8, 8, 8, 8],
[4, 4, 4, 4],
[2, 2, 2, 2]
]))
console.info(solution([
[0, 0, 4, 4],
[4, 8, 4, 8],
[8, 8, 8, 8],
[64, 8, 16, 8]
]))
console.info(solution([
[2, 0, 4, 4],
[4, 4, 4, 4],
[8, 0, 0, 8],
[0, 64, 64, 64]
]))
Вот простое, подробное решение. (Я уверен, что возможен гораздо более элегантный вариант):
function newState(oldState){
// Defines an array to hold our result
let result = [];
// Examines each row of the old state separately
for (let row of oldState){
// Names the columns a, b, c, & d
let a = row[0], b = row[1], c = row[2], d = row[3];
// Checks for match in the rightmost pair
if (d == c && d != 0){
d = d * 2; // Combines matching cells
// Checks for secondary match
if (b == a && b != 0){
// Traditional 2048 logic: combines matching cells *into 'c'* & shifts the rest
c = b * 2; b = 0; a = 0;
// For the alternative logic requested in a comment by OP,
// replace the above line with `c = 0; b = b * 2; a = 0;`
}
else{
c = b; b = a; a = 0; // Shifts the rest
}
}
else{
// Checks for match in the middle pair
if (c == b && c != 0){
c = c * 2; b = a; a = 0; // Combines matching cells and shifts the rest
}
else{
// Checks for match in the leftmost pair
if (b == a && b != 0){
b = b * 2; a = 0; // Combines matching cells and shifts the rest
}
}
}
// Populates the current row in the result matrix
result.push([a, b, c, d]);
}
// Returns the result matrix
return JSON.stringify(result);
}
console.info(newState([[0,0,2,2], [4,4,8,4], [64,64,8,4], [16,8,64,8]]));
console.info(newState([[2,2,4,8],[8,8,64,64],[64,8,16,8],[8,8,8,8]]));
console.info(newState([[64,64,64,64],[8,8,8,8],[4,4,4,4],[2,2,2,2]]));
console.info(newState([[0,0,4,4],[4,8,4,8],[8,8,8,8],[64,8,16,8]]));
console.info(newState([[2,0,4,4],[4,4,4,4],[8,0,0,8],[0,64,64,64]]));
Каким должен быть результат, скажем, [4,4,4,4]?