Create a 2D array. Maintain top, bottom, left, right. Fill four sides per layer, then move those walls inward until they cross.
Method
Idea
Best for
Four-boundary spiral
Fill top/right/bottom/left, then shrink
Learning, interviews, exams
Fixed-width print
String(v).padStart(4, " ")
Aligned columns for multi-digit values
Pseudocode
Pseudocode
top = 0, bottom = n - 1, left = 0, right = n - 1
val = 1
while top <= bottom and left <= right:
fill top row left→right; top = top + 1
fill right column top→bottom; right = right - 1
if top <= bottom:
fill bottom row right→left; bottom = bottom - 1
if left <= right:
fill left column bottom→top; left = left + 1
print the grid
for (i = top; i <= bottom; i++) a[i][right] = val++;
Bottom / left
Same idea reversed; guard with if (top <= bottom) / if (left <= right)
Print cell
line += String(a[i][j]).padStart(4, " ");
Printing Numbers vs Starting a New Line
API
Effect
Use for
line += …padStart(4)
Stays on the same row
Each cell in a row
console.log(line)
Ends the current row
After every row of n cells
Append cells without a newline, then end the row once.
Try it
Live Preview
Change the grid size and the clockwise spiral updates instantly — capped at 8 so the matrix stays readable.
Whole numbers from 1 to 8. Tap a chip or type a value — the preview redraws as you go.
Live resultn = 4 · 16 cells
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
Trace
Worked Walkthrough
Trace the outer layer for n = 4 so the four-side order and boundary shrink are clear.
Side
Action
Values filled
Top
a[0][0..3], then top++
1 2 3 4
Right
a[1..3][3], then right--
5 6 7
Bottom
a[3][2..0], then bottom--
8 9 10
Left
a[2..1][0], then left++
11 12
Inner 2×2 then fills 13 14 / 16 15. Total cells = n² → O(n²).
Code
JavaScript Programs
Three complete programs: fixed 10×10, prompt size, and a compact 4×4 demo. Use View Output for samples, or Try It Yourself to edit and run live.
Example 1 — Fixed 10×10 Spiral
Hard-coded size — fill with four boundaries, print with width 4 (numbers 1–100).
JavaScript
const n = 10;
const a = Array.from({ length: n }, () => Array(n).fill(0));
let top = 0, bottom = n - 1, left = 0, right = n - 1;
let val = 1;
while (top <= bottom && left <= right) {
for (let j = left; j <= right; j++) a[top][j] = val++;
top++;
for (let i = top; i <= bottom; i++) a[i][right] = val++;
right--;
if (top <= bottom) {
for (let j = right; j >= left; j--) a[bottom][j] = val++;
bottom--;
}
if (left <= right) {
for (let i = bottom; i >= top; i--) a[i][left] = val++;
left++;
}
}
for (let i = 0; i < n; i++) {
let line = "";
for (let j = 0; j < n; j++) {
line += String(a[i][j]).padStart(4, " ");
}
console.log(line);
}
1. Outer layer first. Top fills 1..10, right continues downward, then bottom and left close the ring.
2. Shrink inward. After each side, move that boundary so the next layer starts one cell inside.
3. Align.padStart(4, " ") keeps 1–100 lined up in neat columns.
Example 2 — User Input Size
Read n with prompt, validate, then run the same spiral fill.
JavaScript
const n = parseInt(prompt("Enter size n:"), 10);
if (!Number.isFinite(n) || n <= 0) {
console.log("Please enter a positive integer.");
} else {
const a = Array.from({ length: n }, () => Array(n).fill(0));
let top = 0, bottom = n - 1, left = 0, right = n - 1;
let val = 1;
while (top <= bottom && left <= right) {
for (let j = left; j <= right; j++) a[top][j] = val++;
top++;
for (let i = top; i <= bottom; i++) a[i][right] = val++;
right--;
if (top <= bottom) {
for (let j = right; j >= left; j--) a[bottom][j] = val++;
bottom--;
}
if (left <= right) {
for (let i = bottom; i >= top; i--) a[i][left] = val++;
left++;
}
}
for (let i = 0; i < n; i++) {
let line = "";
for (let j = 0; j < n; j++) {
line += String(a[i][j]).padStart(4, " ");
}
console.log(line);
}
}
1. Prompt and validate. Require a finite n > 0 before creating the grid.
2. Same core. Boundary fill matches Example 1 — only n comes from the user.
3. Safer input tip. Cap demos for readable console output:
Safer input
if (!Number.isFinite(n) || n < 1 || n > 20) {
console.log("Enter a whole number from 1 to 20.");
}
Example 3 — Compact 4×4 Trace
Sixteen cells — easy to dry-run every side of the outer and inner layers on paper.
JavaScript
const n = 4;
const a = Array.from({ length: n }, () => Array(n).fill(0));
let top = 0, bottom = n - 1, left = 0, right = n - 1;
let val = 1;
while (top <= bottom && left <= right) {
for (let j = left; j <= right; j++) a[top][j] = val++;
top++;
for (let i = top; i <= bottom; i++) a[i][right] = val++;
right--;
if (top <= bottom) {
for (let j = right; j >= left; j--) a[bottom][j] = val++;
bottom--;
}
if (left <= right) {
for (let i = bottom; i >= top; i--) a[i][left] = val++;
left++;
}
}
for (let i = 0; i < n; i++) {
let line = "";
for (let j = 0; j < n; j++) {
line += String(a[i][j]).padStart(4, " ");
}
console.log(line);
}