martedì 18 settembre 2012

Generatore di labirinti

Il seguente codice è un semplice programma che permette di generare casualmente dei labirinti composti da caratteri e stamparli su schermo.
Il programma è stato commentato per renderne più facile la comprensione.
 
#include <iostream>
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<time.h>

#define MAX 81  // 40 * 2 + 1
#define CELLA 1600  // 40^2
#define MURO 1
#define VIA 0

using namespace std;

void iniz_labi(int labi[MAX][MAX]);
void labi_generator(int indiceks, int labi[MAX][MAX], int retrotraccia_x[CELLA], int retrotraccia_y[CELLA], int x, int y, int n, int visitato);
void stampa_labi(int labi[MAX][MAX], int labi_taglia);
int e_chiuso(int labi[MAX][MAX], int x, int y);

int main(void)
{
    srand((unsigned)time(NULL));

    int taglia, indiceks = 0;
    int labi[MAX][MAX], retrotraccia_x[CELLA], retrotraccia_y[CELLA];
    cout << "CREATORE LABIRINTO\n\n";
    cout << "input  (0 ~ 40): ";
    cin >> taglia;
    cout << endl;
   

    iniz_labi(labi);

    retrotraccia_x[indiceks] = 1;
    retrotraccia_y[indiceks] = 1;

    labi_generator(indiceks, labi, retrotraccia_x, retrotraccia_y, 1, 1, taglia, 1);
    stampa_labi(labi, taglia);

    getch();
    return EXIT_SUCCESS;
}
// inizializzazione labirinto vuoto e pieno
void iniz_labi(int labi[MAX][MAX])
{
     for(int a = 0; a < MAX; a++)
     {
         for(int b = 0; b < MAX; b++)
         {
             if(a % 2 == 0 || b % 2 == 0)
                 labi[a][b] = MURO;
             else
                 labi[a][b] = VIA;
         }
     }
}
// generazione aperture casuali nel percorso
void labi_generator(int indiceks, int labi[MAX][MAX], int retrotraccia_x[CELLA], int retrotraccia_y[CELLA], int x, int y, int n, int visitato)
{
    if(visitato < n * n)
    {
        int vicino_valido = -1;
        int vicino_x[4], vicino_y[4], passo[4];

        int x_prossimo;
        int y_prossimo;

        if(x - 2 > 0 && e_chiuso(labi, x - 2, y))  // sopra
        {
            vicino_valido++;
            vicino_x[vicino_valido]=x - 2;;
            vicino_y[vicino_valido]=y;
            passo[vicino_valido]=1;
        }

        if(y - 2 > 0 && e_chiuso(labi, x, y - 2))  // a sinistra
        {
            vicino_valido++;
            vicino_x[vicino_valido]=x;
            vicino_y[vicino_valido]=y - 2;
            passo[vicino_valido]=2;
        }

        if(y + 2 < n * 2 + 1 && e_chiuso(labi, x, y + 2))  // a destra
        {
            vicino_valido++;
            vicino_x[vicino_valido]=x;
            vicino_y[vicino_valido]=y + 2;
            passo[vicino_valido]=3;

        }

        if(x + 2 < n * 2 + 1 && e_chiuso(labi, x + 2, y))  // basso
        {
            vicino_valido++;
            vicino_x[vicino_valido]=x+2;
            vicino_y[vicino_valido]=y;
            passo[vicino_valido]=4;
        }

        if(vicino_valido == -1)
        {
            // traccia lasciata ed arretramento
            x_prossimo = retrotraccia_x[indiceks];
            y_prossimo = retrotraccia_y[indiceks];
            indiceks--;
        }

        if(vicino_valido!=-1)
        {
            // traccia lasciata ed arretramento
            int casualizzare = vicino_valido + 1, random = rand()%casualizzare;
            x_prossimo = vicino_x[random];
            y_prossimo = vicino_y[random];
            indiceks++;
            retrotraccia_x[indiceks] = x_prossimo;
            retrotraccia_y[indiceks] = y_prossimo;

            int rpasso = passo[random];

            if(rpasso == 1)
                labi[x_prossimo+1][y_prossimo] = VIA;
            else if(rpasso == 2)
                labi[x_prossimo][y_prossimo + 1] = VIA;
            else if(rpasso == 3)
                labi[x_prossimo][y_prossimo - 1] = VIA;
            else if(rpasso == 4)
                labi[x_prossimo - 1][y_prossimo] = VIA;
            visitato++;
        }

        // richiamo a se stessa
        labi_generator(indiceks, labi, retrotraccia_x, retrotraccia_y, x_prossimo, y_prossimo, n, visitato);
    }
}

// determina se cella chiusa
int e_chiuso(int labi[MAX][MAX], int x, int y)
{
    if(labi[x - 1][y]  == MURO && labi[x][y - 1] == MURO
       && labi[x][y + 1] == MURO && labi[x + 1][y] == MURO ) return 1;

    return 0;
}

// visualizzazione labirinto
void stampa_labi(int labi[MAX][MAX], int labi_taglia)
{
     for(int a = 0; a < labi_taglia * 2 + 1; a++)
     {
         for(int b = 0; b < labi_taglia * 2 + 1; b++)
         {
             if(labi[a][b] == MURO)
                 cout << "@";
             else
                 cout <<" ";
         }
         printf("\n");
     }
}

Nessun commento:

Posta un commento