
本文介绍一种高效、原地操作的算法,用于将 4×4 二维数组中每行的非零元素全部左移并紧凑排列,零元素自动右移填充,适用于 2048 等滑动类游戏逻辑实现。
在实现类似 2048 的滑动逻辑时,swipeLeft() 的核心目标并非简单循环移位(如 (c+1) % 4),而是对每一行执行「非零元素左聚」操作:保持原有相对顺序,将所有非零值尽可能靠左排列,右侧用 0 填充。关键在于原地重排——不依赖额外数组,避免索引越界,同时确保移动后原位置被正确置零。
以下是一个清晰、健壮的实现方案:
public void swipeLeft() {
for (int[] row : gameBoard) {
int nextIndex = 0; // 指向当前行中首个待填充的空位(初始为最左)
// 步骤1:定位第一个零的位置(即首个可插入位置)
while (nextIndex < row.length && row[nextIndex] != 0) {
nextIndex++;
}
// 步骤2:从该位置向右扫描,遇到非零元素即搬移至 nextIndex,并将原位清零
for (int col = nextIndex; col < row.length; col++) {
if (row[col] != 0) {
row[nextIndex] = row[col];
row[col] = 0;
nextIndex++; // 指针前移,准备接收下一个非零值
}
}
}
}该算法时间复杂度为 O(N×M)(对 4×4 数组即 O(16)),空间复杂度为 O(1),完全原地完成。其逻辑分为两阶段:
- 定位阶段:找到每行最左侧的 0(即首个可写入位置);
- 填充阶段:从此处开始向右遍历,每发现一个非零数,就将其“搬运”至此位置,并立即将原位置设为 0,同时推进写入指针。
⚠️ 注意事项:
- 切勿使用 gameBoard[r][c] = gameBoard[r][(c+1) % 4] 类似逻辑——这属于错位赋值,会覆盖未读取数据,导致信息丢失和越界风险;
- 必须严格区分「读取位置」(col)与「写入位置」(nextIndex),二者独立演进;
- 若需支持合并(如 2048 中相邻相同数相加),应在搬运前增加合并判断逻辑,本例仅处理基础位移。
此方法简洁、可读性强,且已通过您提供的测试用例验证(输入 → 输出完全匹配),是实现游戏左滑动行为的推荐实践。










