当模式不再只是模式:我与螺旋(蜗牛)矩阵的斗争

发布: (2026年2月6日 GMT+8 00:06)
5 min read
原文: Dev.to

Source: Dev.to

1 2 3
8 9 4
7 6 5

我的大脑卡住的地方

在用 JavaScript 循环解答了 80 多道模式题后,我的大脑已经被训练(或毁掉)成把一切都看成:

  • 基于数学
  • 基于循环
  • ij 的操作
  • 星号、数字、对称

三角形、倒三角形、金字塔、沙漏、蝴蝶、空心图案……只要有名字,我几乎都会把它打印出来。

所以当这道题出现时,我的大脑立刻想强行给它套上数学公式。我一直在自问:

  • 我该怎么操作 ij
  • 能否微调循环条件?
  • 这背后有没有什么神奇的方程?

错误在于我没有把它当作行列来看待,也就是没有把它当作矩阵。我试图把它当成普通的图案题,却发现它根本不配合。

改变一切的思维转变

突破点并不是更多的循环,而是我看待问题的方式改变了。

这并不是一个图案题,而是一个 伪装成图案的矩阵遍历问题
当我开始把输出当作二维网格来处理时,事情慢慢有了头绪。我仍然没有立刻看到完整的解法,但至少有了方向。

用边界思考,而不是公式

与其尝试计算位置,不如把思路简化为:

  1. 一层层填充矩阵。
  2. 按四个方向移动:
    • 左 → 右
    • 上 → 下
    • 右 → 左
    • 下 → 上
  3. 每走完一遍后收缩对应的边界。

变量 topbottomleftright 定义了当前层的边界。

最终奏效的代码

let n = 3;

let matrix = Array.from({ length: n }, () => Array(n).fill(0));

let num = 1;

// Boundaries
let top = 0,
    bottom = n - 1;
let left = 0,
    right = n - 1;

while (num = left; i--) {
        matrix[bottom][i] = num++;
    }
    bottom--;

    // bottom → top
    for (let i = bottom; i >= top; i--) {
        matrix[i][left] = num++;
    }
    left++;
}

// Print result
for (let row of matrix) {
    console.log(row.join(' '));
}

这里到底发生了什么(通俗解释)

  • num 从 1 增加到 n * n
  • topbottomleftright 定义了当前层的边界。
  • 每个内部循环填充螺旋的一个侧面。
  • 完成一侧后,我们把对应的边界向内收缩。
  • 当矩阵填满时,while 循环结束。

没有公式,没有图案技巧——只有受控的移动。

关于 Array.from() 那件事

最初我手动写矩阵的值。后来改成:

let matrix = Array.from({ length: n }, () => Array(n).fill(0));

它的作用:

  1. 创建一个长度为 n 的外层数组(即 n 行)。
  2. 每一行都是一个 的、长度为 n 的数组。
  3. 0 填满每个单元格。

这避免了引用问题(当你需要独立的行时非常重要),并且让同一套逻辑可以适用于任意大小,而不局限于 3 × 3。

真正的教训(不是代码)

有时候问题并不难,而是你的思维模型错了

我之所以卡住,并不是因为不会循环,而是把问题强行套进了不适合的形状。等我不再把它当作图案,而是把它当作矩阵遍历时,一切都恍然大悟。

在我过度解释之前先收尾

我仍然是新人。这个问题并没有让我觉得自己很聪明,反而让我卡住、随后松了一口气。如果你也在为这个图案苦恼,你并不孤单。它很让人困惑——直到它不再困惑。

Back to Blog

相关文章

阅读更多 »