
本文详解如何在 java 中对二维数组每行内相邻相等的非零元素进行左向合并(如 2+2→4,右侧置0),重点规避越界访问,并提供健壮、可复用的实现方案。
本文详解如何在 java 中对二维数组每行内相邻相等的非零元素进行左向合并(如 2+2→4,右侧置0),重点规避越界访问,并提供健壮、可复用的实现方案。
在实现类似“2048”风格的滑动合并逻辑时,一个常见需求是:对二维数组每一行中从左到右连续出现的两个相等且非零元素,将其合并为两倍值,并置于左侧位置,右侧元素清零。注意:该操作仅作用于相邻且严格相等的元素,且必须避免数组索引越界。
原始代码存在两个关键问题:
- 内层循环条件 col
- 未排除 0 的参与——合并 0 == 0 会产生无意义的 0 → 0, 0,违背游戏逻辑(0 表示空位,不可合并)。
以下是修正后的专业实现:
import java.util.Arrays;
public class ArrayMerger {
/**
* 对二维数组每行执行左向相邻合并:仅合并相邻且相等的非零元素
* 合并后左侧元素变为原值两倍,右侧元素置为 0
*/
public static void mergeAdjacentLeft(int[][] board) {
if (board == null) return;
for (int row = 0; row < board.length; row++) {
// 确保行不为空,且至少有2列才能比较相邻元素
if (board[row] == null || board[row].length < 2) continue;
for (int col = 0; col < board[row].length - 1; col++) {
int current = board[row][col];
int next = board[row][col + 1];
// 关键约束:仅当两者均非零且相等时才合并
if (current != 0 && current == next) {
board[row][col] = current * 2;
board[row][col + 1] = 0;
// 注意:此处不跳过下一位置(即不写 col++),因为合并后右侧为0,
// 后续可能与更右侧元素再次形成有效对(如 [2,2,2] → [4,0,2],不应再合并 0 和 2)
}
}
}
}
// 测试示例
public static void main(String[] args) {
int[][] board = {
{0, 2, 4, 2},
{0, 0, 2, 2},
{2, 2, 0, 0},
{0, 5, 0, 2},
{2, 2, 2, 2}, // 预期: [4, 0, 4, 0]
{2, 2, 2, 0} // 预期: [4, 0, 2, 0]
};
System.out.println("合并前:");
System.out.println(Arrays.deepToString(board));
mergeAdjacentLeft(board);
System.out.println("合并后:");
System.out.println(Arrays.deepToString(board));
// 输出:
// [[0, 2, 4, 2], [0, 0, 4, 0], [4, 0, 0, 0], [0, 5, 0, 2], [4, 0, 4, 0], [4, 0, 2, 0]]
}
}✅ 关键要点总结:
立即学习“Java免费学习笔记(深入)”;
- 边界安全:内层循环上限设为 board[row].length - 1,确保 col + 1 始终合法;
- 语义正确:显式检查 current != 0,避免 0 == 0 的无效合并;
- 单次扫描:本实现为“一次遍历、仅合并首个匹配对”,符合典型游戏规则;若需连击合并(如 [2,2,2,2] → [8,0,0,0]),需额外实现“压缩+再合并”两阶段逻辑;
- 健壮性增强:增加 null 和空行防护,提升生产环境可用性。
该方案可直接集成至矩阵类或游戏引擎中,作为 moveLeft() 操作的核心子步骤。如需支持列方向合并或自动压缩空位,可在本函数基础上扩展 shiftZeros() 辅助方法。










