Le torri di Hanoi

Dopo tanti script "utili" eccone uno totalmente inutile. Si tratta del gioco delle Torri di Hanoi. Il gioco consiste in una serie di anelli, di dimensioni diverse, sistemati in un piolo; l'anello più grande in basso, quello più piccolo in alto. Scopo del gioco è spostare tutti gli anelli in un altro piolo, usando un terzo piolo come appoggio e seguendo le seguenti regole:
  • si può spostare solo un anello alla volta;
  • l'anello più piccolo si deve trovare sempre sopra quello più grande.



Il gioco fu inventato all'inizio del '900 e, per aiutarne il successo commerciale, fu accompagnato da un'atmosfera di leggenda. Si disse che il gioco fu scoperto in un monastero buddista, dove alcuni monaci erano addetti alla soluzione di una torre gigantesta di molte decine di anelli. Ogni giorno questi poveri monaci spostavano continuamente anelli da un palo all'altro; quando avrebbero completato lo spostamento di tutti gli anelli sarebbe arrivata la fine del mondo. Una fine angosciante, indubbiamente; però non c'è da essere molto preoccupati: il numero di mosse necessarie cresce in maniera esponenziale con il numero di anelli, con precisione sono esattamente 2n - 1. Con 50 anelli, il numero delle mosse è un numero illeggibile: 1.125.899.906.842.623, oltre un milione di miliardi. Anche spostando centinaia di anelli al giorno sarebbero stati necessari milioni di anni per arrivare alla fine.

Il gioco fu rispolverato negli anni '80, con i computer, perché si prestava ad illustrare quel procedimento di programmazione chiamato "ricorsione". Infatti il gioco può essere risolto in maniera semplice solo con una funzione del genere:
function hanoi(n, sorgente, destinazion, aux) {
if (n < 1) return;
hanoi(n - 1, sorgente, aux, destinazione);
muovi(sorgente, destinazione);
hanoi(n - 1, aux, destinazione, sorgente);
}
In altri termini, se voglio spostare n anelli dal piolo sorgente, a quello destinazione, usando come appoggio il piolo aux, devo prima spostare n - 1 anelli dal sorgente all'ausiliario, usando come appoggio il piolo destinazione; poi sposto l'unico anello rimasto dal sorgente al piolo destinazione; infine sposto gli n - 1 anelli che si trovano sull'ausilliario all'anello destinazione.

Quando si spostano gli n - 1 anelli la funzione hanoi richiama se stessa, cioè effettua una chiamata ricorsiva, semplificando però il problema perché bisogna spostare un numero di anelli inferiore. In pratica, con la ricorsione il problema viene continuamente ridotto di complessità fino alla soluzione banale in cui rimane solo un anello, che viene semplicemente spostato nel piolo destinazione.

Per evitare che la procedura richiami se stessa all'infinito bisogna prevedere una condizione di uscita, che si ha quando non vi sono più anelli da spostare (n < 1).

Per trovare le mosse di una torre con 8 anelli si richiama la funzione con hanoi(8, 1, 3, 2);

La funzione muovi(sorgente, destinazione) è di solito una funzione di stampa, qualcosa del tipo:
function muovi(a, b) { document.write(a + " -> " + b + "<br>");
}
che permette di visualizzare tutte le mosse.

Il nostro script, invece, muove effettivamente gli anelli. Ogni anello viene prima sollevato in alto, viene spostato sopra il piolo destinazione e infine lasciato cadere.

Cosa c'è di divertente in tutto questo? Beh, forse vedere il computer che gioca da solo non è il massimo del divertimento; però posso assicurare che io mi sono divertito molto a fare il programma. Ecco, forse potrà essere ritenuto interessante da chi ha il piacere di fare programmi.


Come si usa

Nell'head della propria pagina html si inserisce l'istruzione:
<script language="JavaScript" src="hanoi.js"></script> poi, per far partire il gioco, si richiama semplicemente con hanoi(n), dove n è il nunero di anelli (minimo 3, massimo 9).

All'interno del frame compaiono alcuni pulsantini:
  • " x ", interrompe l'animazione e chiude la finestra;
  • " start ", riavvia l'animazione, usando sempre lo stesso numero di anelli.
  • " stop ", ferma l'animazione.
Infine compare una combobox, sulla quale si può selezionare il numero di anelli.

Il frame si ridimensiona quando si cambiano il numero di anelli.

Cliccado sul link nella prossima riga può essere avviata l'animazione: