Codice dei programmi nella directory:

///File: HanoiSimulatore.h
#ifndef HANOI_SIM_H #define HANOI_SIM_H #include "raylib.h" #include <stdbool.h> #define MAX_DISCHI 8 // Struttura interna per gestire lo stato della simulazione typedef struct { int pioli[3][MAX_DISCHI]; // CORRETTO: Matrice per i 3 pioli int conteggio[3]; // CORRETTO: Array per il numero di dischi su ciascuno dei 3 pioli int totaleDischi; bool erroreRegole; const char* messaggioErrore; } HanoiSim; // Variabile globale statica per mantenere lo stato nascosto all'utente static HanoiSim sim; // Inizializza la finestra grafica e i dischi sul primo piolo void InizializzaSimulazione(int numDischi) { if (numDischi > MAX_DISCHI) numDischi = MAX_DISCHI; if (numDischi < 1) numDischi = 1; sim.totaleDischi = numDischi; sim.erroreRegole = false; sim.messaggioErrore = ""; // Inizializza i conteggi dei tre pioli sim.conteggio[0] = numDischi; sim.conteggio[1] = 0; sim.conteggio[2] = 0; // Riempie il primo piolo (indice 0) con i dischi dal più grande al più piccolo for (int i = 0; i < numDischi; i++) { sim.pioli[0][i] = numDischi - i; } // --- AGGIUNGI QUESTA RIGA QUI ------------------------------------------ // Disabilita completamente i messaggi di testo iniziali di Raylib SetTraceLogLevel(LOG_NONE); // ----------------------------------------------------------------------- // Inizializza la finestra bloccata a 60 FPS fluidi InitWindow(800, 450, "Esercizio: Torre di Hanoi"); SetTargetFPS(60); } // Funzione di disegno interna (Resta pura, non chiama Begin/End Drawing) static void DisegnaElementiScena(int discoInMovimento, float movX, float movY) { float posizioniX[] = { 200.0f, 400.0f, 600.0f }; float basePegY = 350.0f; float altezzaDisco = 25.0f; float larghezzaUnita = 20.0f; // Dichiarazione e assegnazione separata dei colori Color colori[8]; colori[0] = GetColor(0xe12a2aff); // Rosso colori[1] = GetColor(0xff8100ff); // Arancione colori[2] = GetColor(0xffd300ff); // Giallo colori[3] = GetColor(0x27ae60ff); // Verde colori[4] = GetColor(0x2980b9ff); // Blu colori[5] = GetColor(0x8e44adff); // Viola colori[6] = GetColor(0xf1c40fff); // Giallo chiaro colori[7] = GetColor(0x2c3e50ff); // Blu scuro ClearBackground(RAYWHITE); if (sim.erroreRegole) { DrawText(sim.messaggioErrore, 20, 20, 20, RED); } // Base e pioli DrawRectangle(50, (int)basePegY, 700, 20, BROWN); for (int i = 0; i < 3; i++) { DrawRectangle((int)posizioniX[i] - 5, (int)basePegY - 220, 10, 220, GRAY); } // Dischi fermi for (int p = 0; p < 3; p++) { for (int d = 0; d < sim.conteggio[p]; d++) { int taglia = sim.pioli[p][d]; float larghezza = taglia * larghezzaUnita + 30; float x = posizioniX[p] - (larghezza / 2); float y = basePegY - ((d + 1) * altezzaDisco); DrawRectangleRounded((Rectangle){x, y, larghezza, altezzaDisco - 2}, 0.3f, 4, colori[taglia % 8]); DrawRectangleLinesEx((Rectangle){x, y, larghezza, altezzaDisco - 2}, 1, BLACK); } } // Disco in movimento animato if (discoInMovimento > 0) { float larghezza = discoInMovimento * larghezzaUnita + 30; float x = movX - (larghezza / 2); float y = movY; DrawRectangleRounded((Rectangle){x, y, larghezza, altezzaDisco - 2}, 0.3f, 4, colori[discoInMovimento % 8]); DrawRectangleLinesEx((Rectangle){x, y, larghezza, altezzaDisco - 2}, 1, BLACK); } } // Chiude la finestra di simulazione alla fine void ChiudiSimulazione(void) { while (!WindowShouldClose()) { BeginDrawing(); DisegnaElementiScena(0, 0, 0); EndDrawing(); } CloseWindow(); } /** * Muove un disco rispettando le regole con un'animazione a tempo costante e fluida. */ void MuoviDisco(int da, int a, int velocita) { if (sim.erroreRegole || WindowShouldClose()) return; if (velocita < 1) velocita = 1; if (velocita > 100) velocita = 100; int idxDa = da - 1; int idxA = a - 1; // Controlli didattici di sicurezza if (idxDa < 0 || idxDa > 2 || idxA < 0 || idxA > 2) { sim.erroreRegole = true; sim.messaggioErrore = "ERRORE: Indici dei pioli non validi! Usa valori da 1 a 3."; while (!WindowShouldClose()) { BeginDrawing(); DisegnaElementiScena(0, 0, 0); EndDrawing(); } return; } if (sim.conteggio[idxDa] <= 0) { sim.erroreRegole = true; sim.messaggioErrore = "ERRORE: Tentativo di muovere un disco da un piolo vuoto!"; while (!WindowShouldClose()) { BeginDrawing(); DisegnaElementiScena(0, 0, 0); EndDrawing(); } return; } int tagliaDiscoDaMuovere = sim.pioli[idxDa][sim.conteggio[idxDa] - 1]; if (sim.conteggio[idxA] > 0) { int tagliaDiscoDestinazione = sim.pioli[idxA][sim.conteggio[idxA] - 1]; if (tagliaDiscoDaMuovere > tagliaDiscoDestinazione) { sim.erroreRegole = true; sim.messaggioErrore = "ERRORE: Impossibile mettere un disco piu' grande sopra uno piu' piccolo!"; while (!WindowShouldClose()) { BeginDrawing(); DisegnaElementiScena(0, 0, 0); EndDrawing(); } return; } } // Estrazione logica temporanea per l'effetto visivo sim.conteggio[idxDa]--; // Configurazione geometrica float posizioniX[] = { 200.0f, 400.0f, 600.0f }; float basePegY = 350.0f; float altezzaDisco = 25.0f; float altezzaMassimaSollevamento = basePegY - 240.0f; float startX = posizioniX[idxDa]; float startY = basePegY - ((sim.conteggio[idxDa] + 1) * altezzaDisco); float endX = posizioniX[idxA]; float endY = basePegY - ((sim.conteggio[idxA] + 1) * altezzaDisco); // Se la velocità è al massimo, esegui all'istante senza frame intermedi if (velocita >= 98) { sim.pioli[idxA][sim.conteggio[idxA]] = tagliaDiscoDaMuovere; sim.conteggio[idxA]++; BeginDrawing(); DisegnaElementiScena(0, 0, 0); EndDrawing(); return; } // Calcolo del tempo totale del movimento (da 1.2 secondi a 0.05 secondi) float tempoTotaleAnimazione = 1.2f * (1.0f - (float)(velocita - 1) / 97.0f); if (tempoTotaleAnimazione < 0.05f) tempoTotaleAnimazione = 0.05f; float tempoTrascorso = 0.0f; float curX = startX; float curY = startY; // UNICO LOOP DI ANIMAZIONE SINCRONIZZATO CON IL MONITOR (60 FPS) while (tempoTrascorso < tempoTotaleAnimazione && !WindowShouldClose()) { tempoTrascorso += GetFrameTime(); if (tempoTrascorso > tempoTotaleAnimazione) tempoTrascorso = tempoTotaleAnimazione; // Frazione globale del tempo (va da 0.0 a 1.0) float p = tempoTrascorso / tempoTotaleAnimazione; // Suddividiamo il tempo totale equamente in 3 sotto-fasi (0.33 ciascuna) if (p <= 0.333f) { // Fase 1: Salita float tFase = p / 0.333f; curX = startX; curY = startY + (altezzaMassimaSollevamento - startY) * tFase; } else if (p <= 0.666f) { // Fase 2: Spostamento orizzontale float tFase = (p - 0.333f) / 0.333f; curX = startX + (endX - startX) * tFase; curY = altezzaMassimaSollevamento; } else { // Fase 3: Discesa float tFase = (p - 0.666f) / 0.334f; curX = endX; curY = altezzaMassimaSollevamento + (endY - altezzaMassimaSollevamento) * tFase; } // Singolo rendering a frame, fluido e privo di lag BeginDrawing(); DisegnaElementiScena(tagliaDiscoDaMuovere, curX, curY); EndDrawing(); } // Inserimento definitivo sim.pioli[idxA][sim.conteggio[idxA]] = tagliaDiscoDaMuovere; sim.conteggio[idxA]++; } #endif // HANOI_SIM_H
///(Fine file: HanoiSimulatore.h)

///File: main-errore-movimento.c
#include "HanoiSimulatore.h" int main(void) { int numeroDischi = 3; // Puoi cambiarlo liberamente (fino a un massimo di 8) // Inizializza l'ambiente grafico con il numero di dischi scelto InizializzaSimulazione(numeroDischi); // Avvia il tuo algoritmo dicendo di muovere i dischi dal piolo 1 al piolo 3 usando il 2 MuoviDisco(1,2,5); // terzo parametro velocità da 1 a 100 //MuoviDisco(1,2,30); // dovrebbe dare errore o rifiutarsi.... MuoviDisco(2,3,5); MuoviDisco(2,3,5); // dovrebbe dare errore piolo vuoto // Gestisce la chiusura finale e blocca la finestra per farti vedere il risultato ChiudiSimulazione(); return 0; }
///(Fine file: main-errore-movimento.c)

///File: TorreHanoi.html
<html> <head> <title>Dimostrazione Gioco Torre di Hanoi &mdash; </title> <link href='http://fonts.googleapis.com/css?family=Chewy&text=Tower%20of%20Hanoi%20Game' rel='stylesheet' type='text/css'> <link rel="stylesheet" type="text/css" href="css/TowerOfHanoi.min.css?v=0.1" /> <link rel="stylesheet" type="text/css" href="css/DemoPage.css?v=0.1" /> </head> <body> <div class="demo-block" id="main"> <h2>Gioco della Torre di Hanoi (max 7 dischi)</h2> <div id="game-container"></div> <p id="step-information"> Nuomero di passi che hai fatto: <span id="step">0</span>. Per vincere devi fare non piu' di <span id="max-step">0</span> passi. </p> <p> <label for="number-of-pegs">Numero di Pioli:</label> <select id="number-of-pegs"> <option>3</option> </select> | <label for="number-of-discs">Numero di Dischi:</label> <select id="number-of-discs"> <option>1</option> <option>2</option> <option selected>3</option> <option>4</option> <option>5</option> <option>6</option> <option>7</option> </select> | <a id="Pausa" href="#">Pause</a> | <a id="Ricomincia" href="#">Restart</a> </p> </div> <div class="demo-block" id="footer"> <p>Copyright &copy; 2012 Akeda Bagus admin at gedex.web.id - Modificato 2020</p> </div> <script src="js/jquery-1.7.1.min.js"></script> <script src="js/jquery-ui.min.js"></script> <script src="js/TowerOfHanoi.min.js?v=0.1"></script> <script> jQuery(function() { // Instantiate new game with numOfDiscs = 3. var game = new Game({ numOfDiscs: 3, // Callback after object game is initialized. afterInit: function(g) { jQuery('#max-step').text(g.maxSteps); }, // Callback after steps is performed. afterStep: function(g) { var steps = g.getSteps(); jQuery('#step').text(steps); setTimeout(function() { if ( g.isWin() === 1 ) { alert("Hai Vinto!"); g.freeze(); } else if (steps >= g.getMaxSteps()) { alert("Gioco Terminato"); g.freeze(); } }, 200); } }); var stepInformation = jQuery('#step-information'); var stepInfoText; // Callback can be given later to game object. // Callback when the game is paused. game.onPause = function(g) { // Backups the step text. stepInfoText = stepInformation.html(); // Replaces information step with pause information. stepInformation.html('Game paused'); jQuery('#pause').text('Resume'); }; game.onResume = function(g) { // Restores the steps information. stepInformation.html(stepInfoText); jQuery('#pause').text('Pause'); } jQuery('#pause').click(function(e) { if (game.state === 'playing') { game.pause(); } else if (game.state === 'pause') { game.resume(); } e.preventDefault(); }); jQuery('#restart').click(function(e) { game.restart(); jQuery('#max-step').text(game.maxSteps); jQuery('#step').text(0); e.preventDefault(); }); // Callback when number of discs or pegs is changed. function gameChange() { if (!confirm("Faccio ripartire il gioco, ok?")) { return false; } var pegs = jQuery('#number-of-pegs').val(); var discs = jQuery('#number-of-discs').val(); game.restart({ numOfPegs: pegs, numOfDiscs: discs, destinationPeg: pegs, }); jQuery('#max-step').text(game.maxSteps); jQuery('#step').text(0); } jQuery('#number-of-pegs').change(gameChange); jQuery('#number-of-discs').change(gameChange); }); </script> </body> </html>
///(Fine file: TorreHanoi.html)

///File: hanoi.c
#include "HanoiSimulatore.h" #include <stdio.h> unsigned int mosse=0; // --- IL TUO ESERCIZIO RICORSIVO ------------------------------------- void Hanoi(int n, int da, int a, int appoggio) { // n==dischi, da == piolo partenza, a == piolo arrivo, appoggio = piolo appoggio // Caso base: se c'è solo 1 disco, lo sposti direttamente dal piolo di partenza a quello di arrivo mosse++; if (n == 1) { //MuoviDisco(da, a, appoggio); printf("Muovi un disco da %d a %d\n",da,a); return; } // 1. Sposta n-1 dischi dal piolo di partenza a quello di appoggio, usando l'arrivo come transito Hanoi(n - 1, da, appoggio, a); // 2. Muovi il disco più grande rimasto sul piolo di partenza direttamente all'arrivo //MuoviDisco(da, a, 50); // Richiamo grafica Hanoi.h printf("Muovi un disco da %d a %d\n",da,a); // 3. Sposta gli n-1 dischi dall'appoggio al piolo di arrivo definitivo, usando la partenza come transito Hanoi(n - 1, appoggio, a, da); } // -------------------------------------------------------------------- int main(void) { int dischi; printf("Quanti dischi ? ->"); // fino a un massimo di 8 per la grafica scanf("%d", &dischi); // Inizializza l'ambiente grafico con il numero di dischi scelto // InizializzaSimulazione(dischi); // Avvia il tuo algoritmo dicendo di muovere i dischi dal piolo 1 al piolo 3 usando il 2 come appoggio Hanoi(dischi, 1, 3, 2); printf("\n\nMosse fatte = %d\n",mosse); // Gestisce la chiusura finale e blocca la finestra per farti vedere il risultato // ChiudiSimulazione(); return 0; }
///(Fine file: hanoi.c)