[C] Esercizio vettori bi-dimensionali

meganerd_II
Ciao. Il testo dell'esercizio è questo

"Scrivete un programma che genen un "cammino casuale" in un vettore 10x10. Il vettore conterrà dei caratteri (inizialmente saranno tutti .. '). Il programma deve passare casualmente da un elemento all'altro, muovendosi in alto, in basso, a sinistra o a destra di una posizione soltanto. Gli elementi visitati dal programma dovranno essere etichettati con le lettere che vanno dalla A alla Z nell'ordine con cui vengono visitati.
Suggerimento: per generare i numeri casuali usate le funzioni srand e rand. Dopo aver generato un numero prendete il resto ottenuto e dividetelo per 4. I quattro possibili valori per il resto (O, 1, 2 e 3) indicano la direzione della prossima mossa. Prima di effettuare la mossa controllate che (a) non vada fuori dal vettore e (b) non ci porti in un elemento al quale è stata già assegnata una lettera. Se una delle due condizioni viene violata provate allora a muovervi in un'altra direzione. Se tutte e quattro le direzioni sono bloccate il programma deve termi­nare."

Il programma che ho creato sembra funzionare se non fosse per un piccolo particolare: anzichè creare un percorso casuale, fa il primo spostamento in maniera casuale ma poi continua dritto nella stessa direzione fin quando non finisce la matrice ed è costretto a "girare". Avrò fatto un errore con le funzioni di randomizzazione?

Ecco il mio codice:

//Si genera un numero casuale tra 0 e 3 corrispondente ad una delle 4 direzioni. Si controlla che i nuovi indici non siano negativi e che non siano superiori a 9; si
//controlla che il nuovo elemento sia non diverso dal punto (contiene una lettera); se queste condizioni non sono rispettate si passa all'iterazione successiva senza
//aumentare il contatore. Per inserire il carattere scrivi 'A' + [nome_contatore].

#include <stdio.h>

//Dichiarazione funzioni
void print_array(char walk[10][10]);
void generate_random_walk(char walk[10][10]);

int main(void)
{
    char a[10][10];

    generate_random_walk(a);

    print_array(a);

    return 0;
}

//Definizione funzioni

void print_array(char walk[10][10])
{
    for (int r = 0; r < 10; r++) {
        for (int c = 0; c < 10; c++) {
            printf("%c ", walk[r][c]);
        }
        printf("\n");
    }
}

void generate_random_walk(char walk[10][10])
{
    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h>

    int riga, colonna, contatore = 1, direzione, nuova_riga = 0, nuova_colonna = 0;

    //Impostiamo tutti gli elementi del vettore come punti
    for (int r = 0; r < 10; r++) {
        for (int c = 0; c < 10; c++) {
            walk[r][c] = '.';
        }
    }
    //Stampiamo la matrice per verificare che allo stato attuale sia composta solo da punti
    print_array(walk);
    printf("\n");

    //Generiamo random una riga e una colonna per scegliere casualmente la casella da dove partire
    srand((unsigned) time(NULL));
    riga = rand() % 10;
    srand((unsigned) time(NULL));
    colonna = rand() % 10;
    walk[riga][colonna] = ('A');

    while (contatore < 26) {
        riprova:
        nuova_riga = riga;
        nuova_colonna = colonna;
        srand((unsigned) time(NULL));
        direzione = rand() % 4;
        switch (direzione) {
            case 0: nuova_riga = riga - 1;
                    break;
            case 1: nuova_colonna = colonna + 1;
                    break;
            case 2: nuova_riga = riga + 1;
                    break;
            case 3: nuova_colonna = colonna - 1;
                    break;
            default: break;
        }

        //Controlliamo che il percorso non sia bloccato in tutte le direzioni
        if ( (((riga-1) < 0)||(walk[riga-1][colonna] != '.')) && (((colonna+1) > 9)||(walk[riga][colonna+1] != '.')) && (((riga+1) > 9)||(walk[riga+1][colonna] != '.')) && (((colonna-1) < 0)||(walk[riga][colonna-1] != '.'))) {
            break;
        }

        //Controlliamo che la nuova casella non esca dal quadrato e che non sia già occupata da una lettera ed aggiorniamo
        if ( (nuova_riga < 0) || (nuova_riga > 9) || (nuova_colonna < 0) || (nuova_colonna > 9) || (walk[nuova_riga][nuova_colonna] != '.') ) {
            goto riprova;
        } else {
                riga = nuova_riga;
                colonna = nuova_colonna;
                walk[riga][colonna] = ('A' + contatore);
                contatore += 1;
            }
    }
}



Risposte
apatriarca
srand va chiamato una sola volta.

meganerd_II
Era proprio quello. La spiegazione che avevo letto su quella funzione non era molto dettagliata, quindi credevo di doverla chiamare ad ogni chiamata della funzione rand per non ottenere lo stesso valore... non che bastava chiamarla una volta in tutto il corpo della funzione!

Grazie mille apatriarca, sempre molto disponibile

apatriarca
In realtà il comportamento è l'esatto opposto di quello che hai descritto. Un generatore di numeri pseudo-casuali non è altro che una funzione che genera una sequenza di numeri che sembrano casuali a partire da uno stato iniziale. Nel caso della funzione rand, questo stato (chiamato seed) è un singolo valore intero che vai a inizializzare con time. Siccome il valore restituito da time cambia solo una volta ogni secondo, il primo valore restituito da rand sarà sempre lo stesso nel tuo caso.

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.