How do I print a number spiral using loops in Java?

You can create a clockwise number spiral by filling a two-dimensional array one layer at a time. Start at the top-left corner, move right, down, left, and up, then repeat inside the remaining area. After filling the array, print its rows in order.

Source code

Save this example as NumberSpiralExample.java. It uses a Java 25 compact source file with void main() and the IO console methods. Use JDK 25 or later; no preview flags or external libraries are required. This example introduces arrays and a while loop alongside the for loops used in earlier patterns.

void main() {
    int size = 5;
    int[][] spiral = new int[size][size];
    int top = 0;
    int bottom = size - 1;
    int left = 0;
    int right = size - 1;
    int number = 1;

    while (top <= bottom && left <= right) {
        for (int column = left; column <= right; column++) {
            spiral[top][column] = number++;
        }
        top++;

        for (int row = top; row <= bottom; row++) {
            spiral[row][right] = number++;
        }
        right--;

        if (top <= bottom) {
            for (int column = right; column >= left; column--) {
                spiral[bottom][column] = number++;
            }
            bottom--;
        }

        if (left <= right) {
            for (int row = bottom; row >= top; row--) {
                spiral[row][left] = number++;
            }
            left++;
        }
    }

    int width = String.valueOf(size * size).length();
    for (int row = 0; row < size; row++) {
        for (int column = 0; column < size; column++) {
            if (column > 0) {
                IO.print(" ");
            }
            String value = String.valueOf(spiral[row][column]);
            for (int space = value.length(); space < width; space++) {
                IO.print(" ");
            }
            IO.print(value);
        }
        IO.println();
    }
}

Explanation

The declaration int[][] spiral = new int[size][size] creates a square array. Access each position with spiral[row][column]. A size of five gives 25 positions, which the program fills with the integers 1 through 25.

Four variables describe the unfilled area:

Variable Initial value for size 5 Meaning
top 0 First unfilled row
bottom 4 Last unfilled row
left 0 First unfilled column
right 4 Last unfilled column

The while loop continues as long as the top boundary has not passed the bottom boundary and the left boundary has not passed the right boundary. The logical AND operator, &&, requires both comparisons to be true.

Each iteration fills the available edges in clockwise order:

  1. Fill the top row from left to right, then increase top.
  2. Fill the right column from top to bottom, then decrease right.
  3. If a row remains, fill the bottom row from right to left, then decrease bottom.
  4. If a column remains, fill the left column from bottom to top, then increase left.

Updating each boundary before moving to the next edge prevents corners from being filled twice. The two if statements check whether the corresponding boundaries still permit another edge. This matters near the center, where the remaining area may be only one row or one column. The for loop conditions also prevent traversal when their ranges are empty.

The expression number++ uses the current value for the assignment and then increases it by one. For example, spiral[0][0] = number++ stores 1 and leaves number equal to 2.

After the outer layer is complete, the boundaries enclose a smaller area. The next iteration fills that layer, continuing until the array is full. For an odd size, the last layer is a single center position; for an even size, it is a two-by-two layer.

Aligning the output

The array is filled in spiral order but printed in ordinary row order. The two output loops visit every row and column from index zero onward.

String.valueOf(size * size).length() calculates the number of digits in the largest value. For this example, the largest value is 25, so the field width is two characters. A one-digit value receives one leading space, while a two-digit value receives none.

The program also prints one separator space before every column except the first. This keeps the columns readable without adding a separator after the last value. IO.println() ends each row. The IO class belongs to java.lang, so no explicit import is needed.

Run the example

With JDK 25 or later installed, open a terminal in the directory containing the source file and run it directly:

java NumberSpiralExample.java

You can also compile the source file explicitly and then run the compiled program:

javac NumberSpiralExample.java
java NumberSpiralExample

Output

 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

Display the output in a monospaced font to preserve column alignment.

Try it yourself

Change size to 4. Trace how the four boundaries move after filling the outer layer, then check the two-by-two inner layer. Compare this with the single center position for size = 5.

Try size = 1, which prints only 1. A size of zero creates an empty array and prints no rows. A negative size causes NegativeArraySizeException when the array is created. Use small positive sizes, such as 3 through 10, for this exercise.

Finally, replace number++ with the constant 1 in all four filling loops. Observe that every position is filled once, even though the traversal changes direction at each edge.

How do I print a heart pattern using loops in Java?

You can print a filled heart by visiting points on a grid and checking whether each point belongs to a heart-shaped region. Nested for loops produce the rows and columns, while a mathematical condition selects the positions that contain stars.

Source code

Save this example as HeartPatternExample.java. It uses a Java 25 compact source file with void main() and the IO console methods. Use JDK 25 or later; no preview flags or external libraries are required.

void main() {
    int rows = 20;
    int columns = 40;

    for (int row = 0; row <= rows; row++) {
        double y = 1.5 - 3.0 * row / rows;

        for (int column = 0; column <= columns; column++) {
            double x = -1.5 + 3.0 * column / columns;
            double a = x * x + y * y - 1;

            if (a * a * a - x * x * y * y * y <= 0) {
                IO.print("*");
            } else {
                IO.print(" ");
            }
        }
        IO.println();
    }
}

Explanation

The pattern uses the heart-shaped region defined by this inequality:

(x² + y² - 1)³ - x²y³ <= 0

You do not need to derive the formula to practice the loops. Treat it as a membership test: a point that satisfies the condition gets a star; any other point gets a space. Unlike a circle, this region has two rounded lobes at the top and a point at the bottom.

The outer loop selects the row and calculates its vertical coordinate, y. It starts at 1.5 and moves downward to -1.5. Console output grows downward, so decreasing y keeps the heart upright.

The inner loop visits each column and calculates its horizontal coordinate, x, from -1.5 to 1.5. The constants 3.0 represent the width and height of this coordinate range. Using 3.0 makes the arithmetic floating-point rather than integer division, allowing neighboring positions to have fractional coordinates.

The variables rows and columns specify the number of intervals across the coordinate range. Because both loops include their final index with <=, the program prints rows + 1 lines with columns + 1 character positions per line. The example therefore samples a grid of 21 rows and 41 columns.

For each position, a stores x * x + y * y - 1. The condition then multiplies the values to calculate the powers in the inequality. In Java, ^ is an exclusive-OR operator, not exponentiation, so it would not express these powers.

IO.print("*") and IO.print(" ") each occupy one character position. After the inner loop finishes, IO.println() starts the next row. The IO class belongs to java.lang, so no explicit import is needed.

There are about twice as many horizontal intervals as vertical intervals. This helps balance the proportions in terminal fonts whose characters are taller than they are wide. The result remains a stepped approximation, and its appearance depends on the font. Rows outside the heart contain only spaces and appear blank.

Run the example

With JDK 25 or later installed, open a terminal in the directory containing the source file and run it directly:

java HeartPatternExample.java

You can also compile the source file explicitly and then run the compiled program:

javac HeartPatternExample.java
java HeartPatternExample

Output

           ******       ******
        ************ ************
      *****************************
      *****************************
     *******************************
     *******************************
      *****************************
      *****************************
       ***************************
        *************************
          *********************
            *****************
              *************
                *********
                   ***

Display the output in a monospaced font to preserve alignment. Trailing spaces are omitted from the output shown here; leading spaces and blank rows are preserved.

Try it yourself

Change rows to 30 and columns to 60. The coordinate range stays the same, but the denser grid gives the heart more detail. Keep both values positive to sample the full range correctly.

Replace IO.print("*") with IO.print("#") to change the drawing character without changing the shape.

Finally, change the condition to x * x + y * y <= 1. The same loops now draw a filled circle in the sampled coordinate range. Compare this coordinate-based approach with How do I print a circle pattern using loops in Java?.

How do I print a hollow circle pattern using loops in Java?

You can approximate a hollow circle in the console by printing stars only at grid points within a narrow ring. Nested for loops visit the grid, and an if statement checks whether each point lies between an inner and an outer radius.

Source code

Save this example as HollowCirclePatternExample.java. It uses a Java 25 compact source file with void main() and the IO console methods. Use JDK 25 or later; no preview flags or external libraries are required.

void main() {
    int radius = 5;
    int innerRadius = radius - 1;
    int outerRadiusSquared = radius * radius;
    int innerRadiusSquared = innerRadius * innerRadius;

    for (int y = -radius; y <= radius; y++) {
        for (int x = -radius; x <= radius; x++) {
            int distanceSquared = x * x + y * y;

            if (distanceSquared >= innerRadiusSquared
                    && distanceSquared <= outerRadiusSquared) {
                IO.print("* ");
            } else {
                IO.print("  ");
            }
        }
        IO.println();
    }
}

Explanation

Imagine a circle centered at (0, 0). The squared distance from the center to a point (x, y) is x * x + y * y. Comparing squared distances lets the program test positions without calculating square roots.

The outer radius is five, and the inner radius is four. A position contains a star when its squared distance is at least 16 and at most 25. This selects a ring between the two radii, including both boundaries.

Condition Purpose
distanceSquared >= innerRadiusSquared Exclude points strictly inside the inner circle.
distanceSquared <= outerRadiusSquared Exclude points outside the outer circle.

The logical AND operator, &&, requires both conditions to be true. Points too close to the center remain empty, as do points outside the ring.

The outer loop visits vertical coordinates from -radius through radius. The inner loop visits horizontal coordinates over the same range. Including both endpoints produces an 11-by-11 grid of logical positions for a radius of five.

Each star position prints "* ", and each empty position prints " ". Both strings occupy two character positions, preserving alignment. The extra horizontal spacing often makes the circle look more balanced because terminal characters are usually taller than they are wide. Its apparent proportions still depend on the font.

IO.print() stays on the current line, while IO.println() ends each grid row. The IO class belongs to java.lang, so no explicit import is needed.

The ring is an approximation on a discrete grid. Its edge will look stepped, and the number of stars per row will vary. Keep the radius small for this beginner example; very large values can overflow the int arithmetic and produce impractically large output.

Run the example

With JDK 25 or later installed, open a terminal in the directory containing the source file and run it directly:

java HollowCirclePatternExample.java

You can also compile the source file explicitly and then run the compiled program:

javac HollowCirclePatternExample.java
java HollowCirclePatternExample

Output

          *
    * * * * * * *
  * *           * *
  *               *
  *               *
* *               * *
  *               *
  *               *
  * *           * *
    * * * * * * *
          *

Display the output in a monospaced font to preserve alignment. Trailing spaces are omitted from the output shown here; leading spaces are preserved.

Try it yourself

Change radius to 8 and keep innerRadius = radius - 1. Compare the larger pattern with the original. More grid positions give the circle more detail, though its outline remains stepped.

For the original radius of five, change innerRadius to radius - 2. The inner radius becomes three, creating a thicker ring. Use an inner radius greater than zero and smaller than the outer radius to keep a hole in the center.

Try radius = 1 with the original innerRadius = radius - 1. The inner radius becomes zero, so the center is included and the result has no hole. Use a radius of at least two for a hollow pattern with this formula.

Finally, remove the inner-radius test and keep only distanceSquared <= outerRadiusSquared. The result becomes a filled circle, as in How do I print a circle pattern using loops in Java?.

How do I print a butterfly pattern using loops in Java?

You can print a butterfly pattern by placing two groups of stars on each row with a gap between them. Grow the groups toward the middle of the pattern, then shrink them again to create mirrored wings.

Source code

Save this example as ButterflyPatternExample.java. It uses a Java 25 compact source file with void main() and the IO console methods. Use JDK 25 or later; no preview flags or external libraries are required.

void main() {
    int halfHeight = 5;

    for (int row = 1; row <= halfHeight; row++) {
        for (int star = 0; star < row; star++) {
            IO.print("*");
        }
        for (int space = 0; space < 2 * (halfHeight - row); space++) {
            IO.print(" ");
        }
        for (int star = 0; star < row; star++) {
            IO.print("*");
        }
        IO.println();
    }

    for (int row = halfHeight - 1; row >= 1; row--) {
        for (int star = 0; star < row; star++) {
            IO.print("*");
        }
        for (int space = 0; space < 2 * (halfHeight - row); space++) {
            IO.print(" ");
        }
        for (int star = 0; star < row; star++) {
            IO.print("*");
        }
        IO.println();
    }
}

Explanation

The variable halfHeight controls the number of rows from the top edge through the center, including the center row. For a positive value n, the complete pattern has 2 * n - 1 rows and a width of 2 * n characters.

The first outer loop counts from 1 through halfHeight. Each row contains three parts, printed by three inner loops in sequence:

  1. row stars for the left wing.
  2. 2 * (halfHeight - row) spaces for the middle gap.
  3. row stars for the right wing.

With halfHeight = 5, the upper half uses these counts:

Row counter Left stars Middle spaces Right stars
1 1 8 1
2 2 6 2
3 3 4 3
4 4 2 4
5 5 0 5

Each step adds one star to each wing and removes two spaces from the gap. The total width stays constant because row + 2 * (halfHeight - row) + row simplifies to 2 * halfHeight.

On the center row, the gap contains zero spaces. The middle loop does not execute, so the two groups meet and produce a solid line of ten stars.

The second outer loop starts at halfHeight - 1 and counts down to 1. It uses the same three inner loops, shrinking the wings and widening the gap. Starting one step below halfHeight prints the center row only once and mirrors the rows above it.

Each star and space occupies one character position. IO.print() writes the three parts on the current line, while IO.println() starts the next row. The IO class belongs to java.lang, so no explicit import is needed.

Run the example

With JDK 25 or later installed, open a terminal in the directory containing the source file and run it directly:

java ButterflyPatternExample.java

You can also compile the source file explicitly and then run the compiled program:

javac ButterflyPatternExample.java
java ButterflyPatternExample

Output

*        *
**      **
***    ***
****  ****
**********
****  ****
***    ***
**      **
*        *

Display the output in a monospaced font to preserve alignment. The spaces between the wings are part of the pattern.

Try it yourself

Change halfHeight to 3, then to 7. Before running each version, calculate the total number of rows, the width, and the gap on the first row. For a positive value n, these are 2 * n - 1, 2 * n, and 2 * (n - 1), respectively.

Try halfHeight = 1. The first outer loop prints two adjacent stars, and the second outer loop does not execute. With a value of zero, neither outer loop executes and the program prints nothing. Use positive values to produce a visible pattern.

Change the second outer loop to start at row = halfHeight. This repeats the solid center row and produces a pattern with 2 * halfHeight rows instead.

Finally, compare the changing middle gap with the changing leading spaces in How do I print an hourglass pattern using loops in Java?. In both examples, the spaces are calculated from the current row counter.

How do I print an hourglass pattern using loops in Java?

You can print an hourglass pattern by combining a shrinking, centered triangle with a growing one. Nested for loops control the leading spaces and stars on each row. Print the narrowest row only once so the two halves meet at a single center star.

Source code

Save this example as HourglassPatternExample.java. It uses a Java 25 compact source file with void main() and the IO console methods. Use JDK 25 or later; no preview flags or external libraries are required.

void main() {
    int halfHeight = 5;

    for (int row = halfHeight; row >= 1; row--) {
        for (int space = 0; space < halfHeight - row; space++) {
            IO.print(" ");
        }
        for (int star = 0; star < 2 * row - 1; star++) {
            IO.print("*");
        }
        IO.println();
    }

    for (int row = 2; row <= halfHeight; row++) {
        for (int space = 0; space < halfHeight - row; space++) {
            IO.print(" ");
        }
        for (int star = 0; star < 2 * row - 1; star++) {
            IO.print("*");
        }
        IO.println();
    }
}

Explanation

The variable halfHeight sets the number of rows from the top edge through the center, including the center row. For a positive value n, the complete hourglass has 2 * n - 1 rows. A value of five therefore produces nine rows.

The first outer loop counts down from halfHeight to 1. For each value of row, it prints halfHeight - row leading spaces followed by 2 * row - 1 stars. The number of stars decreases by two per row, while the number of leading spaces increases by one.

With halfHeight = 5, the upper half looks like this:

Row counter Leading spaces Stars
5 0 9
4 1 7
3 2 5
2 3 3
1 4 1

The second outer loop reverses that progression. It starts at row = 2 and counts up to halfHeight, producing 3, 5, 7, and 9 stars. Starting at 2 avoids printing the single-star center row twice.

Both halves use the same spacing formulas. As the lower half grows, its leading-space count decreases, keeping the stars centered around the same column.

Each leading space and each star occupies one character position. IO.print() keeps writing on the current line, and IO.println() ends the row after both inner loops finish. The IO class belongs to java.lang, so no explicit import is needed.

Run the example

With JDK 25 or later installed, open a terminal in the directory containing the source file and run it directly:

java HourglassPatternExample.java

You can also compile the source file explicitly and then run the compiled program:

javac HourglassPatternExample.java
java HourglassPatternExample

Output

*********
 *******
  *****
   ***
    *
   ***
  *****
 *******
*********

Display the output in a monospaced font to preserve alignment. Leading spaces are part of the pattern.

Try it yourself

Change halfHeight to 3, then to 7. Before running each version, calculate the total height and the number of stars in the widest row. Both are 2 * halfHeight - 1 for a positive value.

Try halfHeight = 1. The first outer loop prints one star, and the second outer loop does not execute. A zero or negative value produces no output because neither outer loop executes.

Change the second outer loop to start at row = 1. Observe how repeating the center row changes the shape and adds one line to the output.

Finally, compare this pattern with How do I print a diamond pattern using loops in Java?. A diamond grows toward its center and then shrinks; the hourglass shrinks toward its center and then grows.