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
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.
Call stack
Depth 0 of 4 max
- 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.
| Move | Disk | From | To |
|---|---|---|---|
| 1 | 1 | A | C |
| 2 | 2 | A | B |
| 3 | 1 | C | B |
| 4 | 3 | A | C |
| 5 | 1 | B | A |
| 6 | 2 | B | C |
| 7 | 1 | A | C |
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.javaIt 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 CChange 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:
| Line | Why it is there |
|---|---|
| 1 | Java 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. |
| 2 | static, 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–5 | Recursion 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. |
| 6 | Disk 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. |
| 7 | The 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. |
| 8 | Line 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–13 | main 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.javaOutput
(1L << 64) - 1 = 0
Math.pow(2, 64) - 1 = 9223372036854775806
BigInteger = 18446744073709551615
unsigned long = 18446744073709551615Java’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) - 1is 0.1L << 64is not the huge power of two it looks like: Java uses only the lowest six bits of the shift distance for along, so shifting by 64 is shifting by 0, and the result is 1.Math.pow(2, 64)cast to along, minus one, is 2⁶³ − 2.Math.powgets the size right but returns adouble, and adoubletoo large for alongis pinned toLong.MAX_VALUEby the cast — off by nine quintillion.
Two things work:
BigInteger, which has no upper limit and gives the exact value.Long.toUnsignedString(-1L). Alongalready has the right 64 bits in it if you stop reading them as signed:-1Lis all ones, which is 2⁶⁴ − 1 as an unsigned number, andLong.toUnsignedStringprints 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.javaRecursion 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
- Tower of Hanoi in PythonRecursive and iterative programs, why Python's recursion limit never bites here, and integers that simply do not overflow.
- Tower of Hanoi in JavaScriptWhy 2 ** 64 − 1 prints the wrong number, BigInt, and a generator that hands out one move at a time.
- Tower of Hanoi in CUndefined shifts, uint64_t, and a loop that reads every move straight off the bits of the move number.
- Tower of Hanoi in C++Collecting the moves in a std::vector, the 64-disk count checked by the compiler, and three pairs of towers in a loop.
- Tower of Hanoi in C#Top-level statements, an iterator whose moves LINQ can query, and ulong, checked arithmetic and UInt128 for the move count.
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.