当模式不再只是模式:我与螺旋(蜗牛)矩阵的斗争
Source: Dev.to
1 2 3
8 9 4
7 6 5
我的大脑卡住的地方
在用 JavaScript 循环解答了 80 多道模式题后,我的大脑已经被训练(或毁掉)成把一切都看成:
- 基于数学
- 基于循环
i和j的操作- 星号、数字、对称
三角形、倒三角形、金字塔、沙漏、蝴蝶、空心图案……只要有名字,我几乎都会把它打印出来。
所以当这道题出现时,我的大脑立刻想强行给它套上数学公式。我一直在自问:
- 我该怎么操作
i和j? - 能否微调循环条件?
- 这背后有没有什么神奇的方程?
错误在于我没有把它当作行列来看待,也就是没有把它当作矩阵。我试图把它当成普通的图案题,却发现它根本不配合。
改变一切的思维转变
突破点并不是更多的循环,而是我看待问题的方式改变了。
这并不是一个图案题,而是一个 伪装成图案的矩阵遍历问题。
当我开始把输出当作二维网格来处理时,事情慢慢有了头绪。我仍然没有立刻看到完整的解法,但至少有了方向。
用边界思考,而不是公式
与其尝试计算位置,不如把思路简化为:
- 一层层填充矩阵。
- 按四个方向移动:
- 左 → 右
- 上 → 下
- 右 → 左
- 下 → 上
- 每走完一遍后收缩对应的边界。
变量 top、bottom、left、right 定义了当前层的边界。
最终奏效的代码
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。top、bottom、left、right定义了当前层的边界。- 每个内部循环填充螺旋的一个侧面。
- 完成一侧后,我们把对应的边界向内收缩。
- 当矩阵填满时,
while循环结束。
没有公式,没有图案技巧——只有受控的移动。
关于 Array.from() 那件事
最初我手动写矩阵的值。后来改成:
let matrix = Array.from({ length: n }, () => Array(n).fill(0));
它的作用:
- 创建一个长度为
n的外层数组(即n行)。 - 每一行都是一个 新 的、长度为
n的数组。 - 用
0填满每个单元格。
这避免了引用问题(当你需要独立的行时非常重要),并且让同一套逻辑可以适用于任意大小,而不局限于 3 × 3。
真正的教训(不是代码)
有时候问题并不难,而是你的思维模型错了。
我之所以卡住,并不是因为不会循环,而是把问题强行套进了不适合的形状。等我不再把它当作图案,而是把它当作矩阵遍历时,一切都恍然大悟。
在我过度解释之前先收尾
我仍然是新人。这个问题并没有让我觉得自己很聪明,反而让我卡住、随后松了一口气。如果你也在为这个图案苦恼,你并不孤单。它很让人困惑——直到它不再困惑。