Hanoi Tower

by Alex Ou

HTML

<div id='w'>

<div class='r a'><span>1</span></div>
<div class='r b'><span>2</span></div>
<div class='r c'><span>3</span></div>
</div>

CSS

#w{
  position: relative;
  height: 300px;
  width: 100%;
  border-bottom: 10px solid gray;
}
span{
  position: absolute;
  bottom: -30px;
}
.r {
  position: absolute;
  bottom: 0;
  height:130px;
  width: 6px;
  background: gray;
}
.a {
  transition: 1s;
  left: 20%;
}
.b {
  transition: 1s;
  left: 50%;
}
.c {
  transition: 1s;
  left: 80%;
}
.disk {
  border-radius: 6px;
  position: absolute;
  bottom: 0;
  height: 20px;
  transform: translateX(-45%);
}

.disk.size0{
   width: 80px;
}
.disk.size1{
   width: 70px;
}
.disk.size2{
  width: 60px;
}
.disk.size3{
  width: 50px;
}
.disk.size4{
  width: 40px;
}
.disk.size5{
  width: 30px;
}
.disk.l0{
  bottom: 0;
}
.disk.l1{
  bottom: 20px;
}
.disk.l2{
  bottom: 40px;
}
.disk.l3{
  bottom: 60px;
}
.disk.l4{
  bottom: 80px;
}
.disk.l5{
  bottom: 100px;
}

JavaScript

const q = (c) => document.querySelector(c);

const w = q('#w');
function createDisk(color) {
	const disk = document.createElement('div');
  disk.classList.add('disk');
  disk.classList.add(color);
  disk.style.background = color;
  return disk;
}

const disks = [
  'green',
  'yellow',
  'blue',
  'purple',
  'red'
];
const rods = [
'a', 'b', 'c'
];

function renderDisks(diskMap) {
  Object.keys(diskMap).forEach(r => {
  	const disks = diskMap[r];
    disks.forEach((color, index) => {
    	const disk = createDisk(color);
      disk.classList.add(r);
      disk.classList.add('size'+index);
      disk.classList.add('l'+index);
      w.appendChild(disk);
    })
  })
 
}

const diskMap = {
'a': [...disks],
'b': [],
'c': []
};

renderDisks(diskMap);

function moveDisk(color, onRod, toRod) {
 	var dfd = jQuery.Deferred();
	console.log(`${color} disk ${onRod} --> ${toRod}`);
  
  const disk = q('.'+color);
  
  disk.classList.remove(`l${diskMap[onRod].length - 1}`);
  
  diskMap[onRod].splice(diskMap[onRod].length - 1, 1);
  diskMap[toRod].push(color);
  disk.classList.remove(onRod);
  disk.classList.add(toRod);
  console.log(`l${diskMap[toRod].length - 1}`);
  disk.classList.add(`l${diskMap[toRod].length - 1}`);

  setTimeout(() => {
  	dfd.resolve();
	}, 1000)
  
  return dfd.promise(); 
}

function hanoi(disks, onRod, viaRod, toRod) {
  var dfd = jQuery.Deferred();
	if (disks.length === 0) {
  	dfd.resolve();
    return dfd.promise(); 
	} 

  return hanoi(disks.slice(1), onRod, toRod, viaRod).then(() => {
  	return moveDisk(disks[0], onRod, toRod);
  }).then(() => {
  	return hanoi(disks.slice(1), viaRod, onRod, toRod);
  });
  
}

setTimeout(() => {
	hanoi( [...disks], ...rods)
}, 1000);