Skip to content

Tower of Hanoi in Java

A complete Java program that solves the puzzle recursively, stepped through line by line beside the board — then the same moves with no recursion at all.

On this page
  1. The recursive solution, running
  2. Run it yourself
  3. Line by line
  4. Counting the moves
  5. Without recursion, using an explicit stack
  6. The same algorithm in other languages
  7. Frequently asked questions

The recursive solution, running

Step through the program. The lit line is the one executing, the towers are labelled for the call that is running, and the stack lists every call still waiting to finish.

hanoi(3, 'A', 'C', 'B')

Move 3 disks from A to C.

Nothing is running yet. The first step makes this call.

Step 0 of 43

Call stack

Depth 0 of 4 max

  1. Empty. Nothing has been called yet.

Hanoi.java

public class Hanoi {
    static void hanoi(int n, char source, char target, char spare) {
        if (n == 0) {
            return;
        }
        hanoi(n - 1, source, spare, target);
        System.out.println("Move disk " + n + " from " + source + " to " + target);
        hanoi(n - 1, spare, target, source);
    }

    public static void main(String[] args) {
        hanoi(3, 'A', 'C', 'B');
    }
}

Moves

7 in all

Choose a row to jump the program to that move.

Every move the program makes for 3 disks
MoveDiskFromTo
11AC
22AB
31CB
43AC
51BA
62BC
71AC

Run it yourself

Save the listing as Hanoi.java. On Java 10 or older, compile it first with javac Hanoi.java and then run the class with java Hanoi. Since Java 11 the launcher does both in one step for a single source file, which is all this program needs:

Run it

java Hanoi.java

It prints the seven moves of the three-disk puzzle:

Output

Move disk 1 from A to C
Move disk 2 from A to B
Move disk 1 from C to B
Move disk 3 from A to C
Move disk 1 from B to A
Move disk 2 from B to C
Move disk 1 from A to C

Change the 3 in the call to solve a bigger puzzle. Every disk you add doubles the output, plus one line.

Line by line

Not what each line says — the listing says that — but why it has to be there:

LineWhy it is there
1Java has nowhere to put a function except inside a class, so this class is here to satisfy the language rather than to model anything. The file has to be named for the public class, which is a rule of the compiler and not of the puzzle.
2static, so main can call it without first creating a Hanoi object. The function keeps no state between calls, so an object would have nothing to hold. The towers are chars because a one-letter name needs no more than that.
3–5Recursion needs a size it can answer without calling itself, or it never stops. Zero disks is that size. Stopping at n == 1 would work and would halve the calls, but the move would then have to be written twice.
6Disk n is heading for target, so target must be clear when it arrives, which rules it out as a home for the n - 1 disks above it. They go to spare — which is why the last two arguments trade places on the way in.
7The only line that moves a disk, and it is legal precisely because line 6 has just finished: nothing smaller than n is left on either tower. Because the expression starts with a String, the int and the chars after it are appended as text rather than added as numbers.
8Line 6 mirrored. The n - 1 disks are on spare now, so that is the source, and the tower everything started on is free to be the working space. It is the last thing the method does, and it still gets a stack frame of its own: Java never turns a call in tail position into a jump. That costs nothing here, where the stack is only n + 1 deep.
11–13main is the entry point the JVM looks for. Its arguments are in the function's order rather than the puzzle's: three disks, source A, target C, and B as whatever is left.

Why those three lines are enough — the correctness proof, the recurrence and the complexity — is on the Tower of Hanoi algorithm page, and holds for every language here.

Counting the moves

CountMoves.java

import java.math.BigInteger;

public class CountMoves {
    public static void main(String[] args) {
        // Java uses only the low six bits of a long shift distance, so this is 1L << 0.
        long shifted = (1L << 64) - 1;
        System.out.println("(1L << 64) - 1      = " + shifted);

        // 2^64 does not fit in a long, so the cast pins it to Long.MAX_VALUE first.
        long rounded = (long) Math.pow(2, 64) - 1;
        System.out.println("Math.pow(2, 64) - 1 = " + rounded);

        // BigInteger has no ceiling.
        BigInteger exact = BigInteger.ONE.shiftLeft(64).subtract(BigInteger.ONE);
        System.out.println("BigInteger          = " + exact);

        // Or keep all 64 bits in a long and print them as unsigned.
        System.out.println("unsigned long       = " + Long.toUnsignedString(-1L));
    }
}

Run it

java CountMoves.java

Output

(1L << 64) - 1      = 0
Math.pow(2, 64) - 1 = 9223372036854775806
BigInteger          = 18446744073709551615
unsigned long       = 18446744073709551615

Java’s long is a signed 64-bit integer, so its largest value is 2⁶³ − 1: one bit short of the 64-disk move count. The two obvious ways to write 2⁶⁴ − 1 both fail, and neither complains.

  • (1L << 64) - 1 is 0. 1L << 64 is not the huge power of two it looks like: Java uses only the lowest six bits of the shift distance for a long, so shifting by 64 is shifting by 0, and the result is 1.
  • Math.pow(2, 64) cast to a long, minus one, is 2⁶³ − 2. Math.pow gets the size right but returns a double, and a double too large for a long is pinned to Long.MAX_VALUE by the cast — off by nine quintillion.

Two things work:

  • BigInteger, which has no upper limit and gives the exact value.
  • Long.toUnsignedString(-1L). A long already has the right 64 bits in it if you stop reading them as signed: -1L is all ones, which is 2⁶⁴ − 1 as an unsigned number, and Long.toUnsignedString prints it that way.

C# has the type Java leaves out: ulong, an unsigned 64-bit integer whose maximum is the move count itself.

Without recursion, using an explicit stack

HanoiStack.java

import java.util.ArrayDeque;
import java.util.Deque;

public class HanoiStack {
    // A job still to do: move n disks, or, when single is true, move just disk n.
    record Job(int n, char source, char target, char spare, boolean single) {}

    static void hanoi(int disks, char source, char target, char spare) {
        Deque<Job> jobs = new ArrayDeque<>();
        jobs.push(new Job(disks, source, target, spare, false));

        while (!jobs.isEmpty()) {
            Job job = jobs.pop();
            if (job.single()) {
                System.out.println("Move disk " + job.n() + " from " + job.source() + " to " + job.target());
            } else if (job.n() > 0) {
                // Pushed in reverse: a stack hands back the last thing pushed first.
                jobs.push(new Job(job.n() - 1, job.spare(), job.target(), job.source(), false));
                jobs.push(new Job(job.n(), job.source(), job.target(), job.spare(), true));
                jobs.push(new Job(job.n() - 1, job.source(), job.spare(), job.target(), false));
            }
        }
    }

    public static void main(String[] args) {
        hanoi(3, 'A', 'C', 'B');
    }
}

Run it

java HanoiStack.java

Recursion is a stack you do not have to manage. This version manages it. Each entry on the ArrayDeque is a job still to do: move n disks, or, when single is true, move disk n by itself. Popping a transfer of n disks pushes its three parts back on — the second transfer, the single move, the first transfer — in reverse, because a stack hands back the last thing pushed first. The loop ends when there is nothing left to do.

It prints the same seven lines as the recursive program. This is the mechanical way to turn any recursive function into a loop, and it makes the call stack from the trace at the top of the page into an ordinary data structure you can inspect. record needs Java 16 or newer; on older versions, a small static class with the same five fields does the same job.

The same algorithm in other languages

Frequently asked questions

How do you solve Tower of Hanoi in Java?

With a static recursive method: if n is 0, return; otherwise call hanoi(n - 1, source, spare, target), print the move of disk n, and call hanoi(n - 1, spare, target, source). Calling hanoi(3, 'A', 'C', 'B') from main prints the seven moves of the three-disk puzzle.

Why is (1L << 64) − 1 zero in Java?

Java uses only the lowest six bits of the shift distance when shifting a long, so 1L << 64 is the same as 1L << 0, which is 1. Subtracting 1 gives 0. The exact move count for 64 disks needs BigInteger, or a long printed with Long.toUnsignedString: the bit pattern of -1L is exactly 2⁶⁴ − 1.

How do I write Tower of Hanoi in Java without recursion?

Replace the call stack with your own. Push a job describing the whole transfer onto an ArrayDeque, then loop: pop a job and, if it is more than one disk, push its three parts — the second transfer, the single move and the first transfer — in reverse order. The moves come out in exactly the same order as the recursive version.