Need Help or More Information?
Questions about this free C programming course, embedded C training or career guidance? Get in touch.
Spiral Matrix in C
Fill a 2-D array in clockwise spiral order with two clean, tested methods. A free C tutorial for embedded C programming beginners.
A spiral matrix in C is one of the best two-dimensional array exercises for sharpening your loop control. You fill an n × n grid with the numbers 1 to n² by starting at the top-left corner, walking clockwise, and curling inward until you reach the centre. In this lecture of our free C programming course you will build the spiral matrix in two original ways, trace every step by hand, and see why the same index-walking skill matters in embedded C programming whenever you scan an LED matrix, a display buffer or a sensor grid in a non-linear order.
Topics Covered
What You Will Learn
- What a spiral matrix is and how its numbers are laid out for odd and even sizes.
- The four-border idea: shrinking top, bottom, left and right limits after every edge.
- A complete, tested border-shrinking program with input validation.
- A second method that uses a direction table and turns when it hits a wall or a filled cell.
- How to choose between the two methods and avoid the classic centre-cell bug.
- Where this pattern appears in embedded systems work.
Prerequisites
- Declaring and initialising two-dimensional arrays (earlier lectures in this arrays chapter).
- Nested
forloops and thewhileloop. - Writing a small function that receives a 2-D array as a parameter.
- A C compiler such as GCC on Linux, or any embedded toolchain that supports C99 or newer.
What a Spiral Matrix Looks Like
Imagine writing numbers on graph paper. Put 1 in the top-left square, move right until the row ends, turn down, then left, then up, and keep turning clockwise whenever the next square is outside the grid or already used. The result for n = 4 and n = 5 is shown below. Notice that every number is exactly one step away from its predecessor, and that the final number n² always lands near the centre.
| row / col | 0 | 1 | 2 | 3 |
|---|---|---|---|---|
| 0 | 1 | 2 | 3 | 4 |
| 1 | 12 | 13 | 14 | 5 |
| 2 | 11 | 16 | 15 | 6 |
| 3 | 10 | 9 | 8 | 7 |
| row / col | 0 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|---|
| 0 | 1 | 2 | 3 | 4 | 5 |
| 1 | 16 | 17 | 18 | 19 | 6 |
| 2 | 15 | 24 | 25 | 20 | 7 |
| 3 | 14 | 23 | 22 | 21 | 8 |
| 4 | 13 | 12 | 11 | 10 | 9 |
The Four-Border Idea
Instead of tracking a walker that decides when to turn, think of the grid as a stack of rectangular rings. The outer ring is filled first, then you move one step inside and fill the next ring. To describe the ring that is still empty you only need four integers: top, bottom, left and right. After each edge is filled, the matching border moves one step inward. When the borders cross each other, the matrix is complete.
Spiral Matrix in C: Border-Shrinking Method
The program below keeps the filling logic inside fill_spiral() and the printing inside print_grid(), which makes both easy to test. The size is validated before use, because scanf can fail and an oversized n would write past the end of the array.
#include <stdio.h>
#define MAX_N 10
static void fill_spiral(int n, int grid[][MAX_N])
{
int top = 0, bottom = n - 1;
int left = 0, right = n - 1;
int value = 1;
while (top <= bottom && left <= right) {
for (int c = left; c <= right; c++) /* left to right */
grid[top][c] = value++;
top++;
for (int r = top; r <= bottom; r++) /* top to bottom */
grid[r][right] = value++;
right--;
if (top <= bottom) { /* right to left */
for (int c = right; c >= left; c--)
grid[bottom][c] = value++;
bottom--;
}
if (left <= right) { /* bottom to top */
for (int r = bottom; r >= top; r--)
grid[r][left] = value++;
left++;
}
}
}
static void print_grid(int n, int grid[][MAX_N])
{
for (int r = 0; r < n; r++) {
for (int c = 0; c < n; c++)
printf("%4d", grid[r][c]);
putchar('\n');
}
}
int main(void)
{
int grid[MAX_N][MAX_N] = {0};
int n;
printf("Enter n (1-%d): ", MAX_N);
if (scanf("%d", &n) != 1 || n < 1 || n > MAX_N) {
printf("Invalid size\n");
return 1;
}
fill_spiral(n, grid);
print_grid(n, grid);
return 0;
}
Build and run it like this:
gcc -std=c11 -Wall -Wextra -o spiral spiral.c
./spiral
Typing 5 at the prompt gives the following output, which matches the n = 5 diagram above:
Enter n (1-10): 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
How the Code Works
The while condition is the safety net: as long as the top border has not passed the bottom border and the left border has not passed the right border, there is at least one empty cell. The first two for loops always run inside a valid ring. The last two loops sit behind if guards because, after the top row and right column are done, the ring may have collapsed into a single row or a single column. Running the bottom row or left column in that situation would overwrite numbers that are already written.
Trace the Borders for n = 5
Work through the program on paper once and the logic sticks permanently. The table shows the borders at the end of each lap of the while loop.
| Lap | top | bottom | left | right | Values written |
|---|---|---|---|---|---|
| Start | 0 | 4 | 0 | 4 | none |
| 1 | 1 | 3 | 1 | 3 | 1 to 16 (outer ring) |
| 2 | 2 | 2 | 2 | 2 | 17 to 24 (middle ring) |
| 3 | 3 | 2 | 2 | 1 | 25 (centre cell) |
In lap 3 the top row loop writes 25 and moves top to 3. The right column loop then starts at row 3, which is already past bottom, so it writes nothing. Both guards fail, the borders have crossed, and the outer while ends.
if guards and every odd-sized matrix will have its centre value overwritten by the bottom-row and left-column loops. Even sizes may appear to work, which hides the bug until someone tests n = 3 or n = 5.Spiral Matrix in C: Direction-Table Method
The second approach uses a single walker. A small table stores the row and column step for each of the four directions: right, down, left and up. At every cell the walker writes the next number, looks at the square ahead, and if that square is outside the grid or already filled it rotates to the next direction. Because there are no per-edge loops, this version is shorter, and changing the spiral to counter-clockwise only means reordering the table.
#include <stdio.h>
#define N 6
int main(void)
{
static const int step_row[4] = { 0, 1, 0, -1 };
static const int step_col[4] = { 1, 0, -1, 0 };
int grid[N][N] = {0};
int row = 0, col = 0, dir = 0;
for (int value = 1; value <= N * N; value++) {
grid[row][col] = value;
int next_row = row + step_row[dir];
int next_col = col + step_col[dir];
if (next_row < 0 || next_row >= N || next_col < 0 || next_col >= N ||
grid[next_row][next_col] != 0) {
dir = (dir + 1) % 4; /* turn clockwise */
next_row = row + step_row[dir];
next_col = col + step_col[dir];
}
row = next_row;
col = next_col;
}
for (int r = 0; r < N; r++) {
for (int c = 0; c < N; c++)
printf("%4d", grid[r][c]);
putchar('\n');
}
return 0;
}
Output for n = 6:
1 2 3 4 5 6
20 21 22 23 24 7
19 32 33 34 25 8
18 31 36 35 26 9
17 30 29 28 27 10
16 15 14 13 12 11
Two details deserve attention. First, a filled cell is detected by checking for zero, so the array must start zeroed, which the initialiser {0} guarantees. Second, after the very last number is written the walker computes a next position that is never used, so the loop ends safely even though that position may point at a filled cell.
Which Method Should You Use
| Point | Border shrinking | Direction table |
|---|---|---|
| Core idea | Fill ring by ring using four limits | Walk one cell at a time and turn at walls |
| Code size | Longer, four loops | Shorter, one loop |
| Needs zeroed array | No | Yes, zero means empty |
| Edge cases | Two guards for odd and thin rings | Handled by the turn test |
| Change to counter-clockwise | Rewrite loop order | Reorder the table |
| Extra memory | Four integers | Two tiny constant tables |
For learning, start with border shrinking because each edge is visible in the code. For production code that may need other scan orders, the direction table is easier to extend and to review.
Real-World Embedded C Uses
- LED matrix animations: lighting pixels in a spiral order gives a classic loading effect on an 8 × 8 panel driven by a microcontroller.
- Display and camera buffers: some image scanning patterns visit pixels from the outside inwards to detect edges early.
- Sensor grids: a thermal sensor array can be read in spiral order so that the centre of interest is sampled last or first, depending on the algorithm.
- Lookup tables: generate the spiral order once, store it as a
constarray of indices, and let the linker place it in flash instead of recomputing it at run time.
Common Mistakes and Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Centre value wrong for odd n | Missing guards before the last two loops | Add the two if checks shown above |
| Crash or garbage for large n | n larger than the array dimension | Validate n against MAX_N before filling |
| Walker spins in place or repeats numbers | Array not zeroed before using the direction method | Initialise with {0} or memset |
| Numbers start at 0 | Counter initialised to 0 | Start value at 1 and increment after each write |
| Output columns misaligned | Width too small for two-digit numbers | Use a field width such as %4d |
Best Practices, Performance and Security
- Keep fill logic and printing in separate functions so you can test one without the other.
- Both methods run in O(n²) time because each cell is written exactly once, and both need only O(1) extra memory beyond the grid.
- On a small microcontroller, declare large grids
staticor at file scope so they do not consume stack space, and useuint8_twhen values fit in a byte. - Always check the return value of
scanfand reject sizes outside the valid range. Unchecked sizes are a classic source of buffer overflows. - Compile with
-Wall -Wextraand treat warnings as defects.
Summary
- A spiral matrix visits every cell once, turning clockwise at the grid edge or at a used cell.
- The border-shrinking method needs four limits and two guards for thin rings.
- The direction-table method needs a zeroed array and a turn test.
- Tracing borders on paper is the fastest way to debug either version.
You now have two reliable ways to solve this classic problem and the reasoning skills to adapt them to other traversal orders. Practise by producing a counter-clockwise spiral and a spiral that starts from the centre.
FAQ: Spiral Matrix in C
What is a spiral matrix in C?
It is an n × n two-dimensional array filled with the numbers 1 to n² in a clockwise spiral that starts at the top-left cell and ends near the centre.
Which method is faster, border shrinking or the direction table?
Both are O(n²) because every cell is written once. Differences are tiny, so pick the one that is easier for you to read and extend.
Why does the centre cell break for odd sizes?
When the ring collapses to a single row or column, the bottom-row and left-column loops would run again over cells already written. The two if guards prevent that.
Can I generate a counter-clockwise spiral?
Yes. With the direction table, reorder the steps to right, up, left, down or start by moving down. With borders, swap the order of the edge loops.
Is this useful in embedded C programming?
Yes. Grid scan orders for LED panels, displays and sensor arrays use the same index logic, and precomputed order tables can be stored in flash as constant arrays.
Can n be even or odd?
Both work. Even sizes finish with a 2 × 2 ring, while odd sizes finish with a single centre cell.
Keep Going With the Free C Programming Course
Every lecture in this free C tutorial for embedded systems is original, tested and written for beginners who want real embedded C programming skills. Move on to the next lecture or return to the course index.
<divNeed Help or More Information?
Questions about this free C programming course, embedded C training or career guidance? Get in touch.

2 Comments