<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Animated Tower of Hanoi (4 Disks Auto-Start)</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
display: flex;
flex-direction: column;
align-items: center;
font-family: sans-serif;
padding: 20px;
}
h1 {
margin-bottom: 20px;
}
#stage {
position: relative;
width: 600px;
height: 300px;
background: #f5f5f5;
border: 2px solid #333;
}
.peg {
position: absolute;
bottom: 0;
width: 8px;
height: 180px;
background: #333;
}
#peg0 { left: 100px; }
#peg1 { left: 300px; }
#peg2 { left: 500px; }
.disk {
position: absolute;
height: 20px;
border-radius: 4px;
transition: top 0.4s ease, left 0.4s ease;
}
</style>
</head>
<body>
<h1>Tower of Hanoi — 4 Disks</h1>
<div id="stage">
<div class="peg" id="peg0"></div>
<div class="peg" id="peg1"></div>
<div class="peg" id="peg2"></div>
</div>
<script>
const stage = document.getElementById('stage');
function setup(n) {
stage.querySelectorAll('.disk').forEach(d => d.remove());
const pegs = [[], [], []];
const pegXs = [100, 300, 500];
for (let i = n; i > 0; i--) {
const disk = document.createElement('div');
disk.className = 'disk';
disk.style.width = (i * 20 + 40) + 'px';
disk.style.background = `hsl(${i * 30}, 70%, 50%)`;
stage.appendChild(disk);
pegs[0].push(disk);
}
pegs.forEach((stack, pegIndex) => {
stack.forEach((disk, level) => {
disk.dataset.peg = pegIndex;
disk.dataset.level = level;
disk.style.left = pegXs[pegIndex] - disk.offsetWidth / 2 + 'px';
disk.style.top = stage.clientHeight - 20 * (level + 1) + 'px';
});
});
return { pegs, pegXs };
}
function gen(n, from, to, aux, moves) {
if (n > 1) gen(n - 1, from, aux, to, moves);
moves.push({ disk: n, from, to });
if (n > 1) gen(n - 1, aux, to, from, moves);
}
function animate(moves, pegs, pegXs) {
let i = 0;
function step() {
if (i >= moves.length) return;
const { disk, from, to } = moves[i++];
const d = pegs[from].pop();
pegs[to].push(d);
const level = pegs[to].length - 1;
d.style.left = pegXs[to] - d.offsetWidth / 2 + 'px';
d.style.top = stage.clientHeight - 20 * (level + 1) + 'px';
setTimeout(step, 500);
}
step();
}
window.addEventListener('load', () => {
const n = 4;
const { pegs, pegXs } = setup(n);
const moves = [];
gen(n, 0, 2, 1, moves);
setTimeout(() => animate(moves, pegs, pegXs), 200);
});
</script>
</body>
</html>
Nicely done