Programma semplice in C "lancio di due dadi"

di il
5 risposte

Programma semplice in C "lancio di due dadi"

Ciao ragazzi,
sto impazzendo!!!
Ho provato ad implementare un programmino con una funzione esterna.
si tratterebbe di visualizzare la somma dei lanci casuali di due dadi(per 3600 volte), ma la visualizzazione mi dà un risultato errato. Che cosa sbaglio?


#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define lancio 3600

int lanciocasuale(void);/*prototipo di funzione*/

int main(void){ /* inizio funzione main*/
int i,sum,j;
int vett[12];

for(i=0;i<lancio;i++) /*uso il valore somma come indice del vettore ed incrementane il valore per ogni lancio*/
{
sum=lanciocasuale();/*richiamo della funzione esterna*/
++vett[sum];
}

for(sum=0;sum<12;sum++)/*visualizzo i risultati della somma precedentemente immagazzinati in un vettore*/
{
printf("%d%10d",sum,vett[sum]);/*stampa degli elementi del vettore in formato tabulare*/
}
for(j=0;j<vett[sum];j++)
{ /*per
printf("%d",vett[sum]+1);
printf("\n");}
return 0;}


/*definizione di funzione*/
int lanciocasuale(void){
int dado1,dado2,somma;
srand(time(NULL)); /*generazione randomizzata del seme per ogni lancio di funzione*/
dado1=rand()% 7;
dado2=rand()% 7;
somma=dado1+dado2;
return somma;


}

5 Risposte

  • Re: Programma semplice in C "lancio di due dadi"

    
    for(i=0;i<lancio;i++) /*uso il valore somma come indice del vettore ed incrementane il valore per ogni lancio*/
    { 
    sum=lanciocasuale();/*richiamo della funzione esterna*/
    ++vett[sum];
    }
    
    C'è tantissima logica sbagliata nell'esercizio. Utilizzare il valore della somma come indice per memorizzare la somma nel vettore vett non ha proprio senso. Se poi la somma è maggiore di 11 dove lo memorizza? E se esce una somma già uscita?

    La parte della stampa di vett anche è sballata quindi ti darà risultati sballati.

    La funziona lanciocasuale può salvarsi il problema che se vuoi simulare un dado devi aggiungere +1 e fare %6 ad entrambe le estrazioni random dei dadi.

    Comunque devi fare un vettore di 3600 elmenti, creare una variabile contatore i e memorizzare nell'i-simo elemento l'i-simo lancio dei dadi.
  • Re: Programma semplice in C "lancio di due dadi"

    Ti spiego: nello sviluppo del programma dovrebbe essere scritto che poichè il lancio random dei due dadi è un numero compreso fra 1 e 6, la somma dovrebbe essere compresa fra 2 e 12, per logica.
    Questo e' il motivo per cui ho utilizzato quell'indice.
    Se la somma esce due volte, dovrebbe incrementare l'indice corrispondente.
    per esempio se esce 2 una volta, vett[2]=1, se esce una seconda volta, vett[2]=2 e così via.
    Ho pensato anch'io a creare un contatore di 3600 elementi, ma così non mi darebbe la frequenza delle uscite e poi come si crea l'istogramma?
    Ho preso spunto da diversi programmi trovati sul manuale.
    comunque ho trovato l'errore, sembra che la randomizzazione sia nel posto sbagliato.
    la devo mettere nella main prima del richiamo della funzione, allora il risultato e' quello corretto.
    Grazie dell'intervento.
    Serena
  • Re: Programma semplice in C "lancio di due dadi"

    serenazoso ha scritto:


    la devo mettere nella main prima del richiamo della funzione, allora il risultato e' quello corretto.
    Il risultato è comunque sbagliato.
    L'inzializzazione del seme per il LCG deve essere fatta una sola volta, come hai già scoperto. Ma anche i valori pseudorandom devono essere modificati, come ti è già stato fatto notare. Inoltre, non è affatto necessario richiamare due volte di seguito il generatore pseudorandom: è sufficiente una sola chiamata, che fornisca in modo equiprobabile (per quanto possibile con i banali LCG delle librerie standard... ) un valore tra gli undici possibili nell'intervallo chiuso [2, 12].
    La sintassi corretta è quindi la seguente:
    
    somma = 2 + (rand() % 11);
    
  • Re: Programma semplice in C "lancio di due dadi"

    Ora riesco a dare un senso al tuo codice, era meglio esplicitare prima il testo.

    Il seed hai capito che va fatto una sola volta e quindi messo nel main all'inizio.
    Inoltre il tuo vettore delle occorrenze va inizializzato con tutti gli elementi almeno a 0 altrimenti è riempito di valori sporchi.
    Questo vettore delle occorrenze magari potresti dichiararlo con uno spazio di 11 elementi (essendo possibile solo 11 risultati e sottrargli due quando ti serve riconoscere l'indice. (es. l'indice delle occorrenze delle somme 10 è uguale a .

    Quindi diventerebbe una cosa del genere:
    
    for(i=0;i<lancio;i++) /*uso il valore somma come indice del vettore ed incrementane il valore per ogni lancio*/
    {
    sum=lanciocasuale();/*richiamo della funzione esterna*/
    vett[sum-2]+=1;
    }
    
    Inoltre come giustamente ti è stato suggerito potresti sostituire i due dadi direttamente con l'estrazione del numero tra 2 e 12.
  • Re: Programma semplice in C "lancio di due dadi"

    Più in generale, questo genere di esercizi è pensato come simulazione in piccolo per familiarizzare gli studenti con la legge dei grandi numeri e le distribuzioni stocastiche. Il numero di iterazioni può quindi potenzialmente essere molto elevato.

    Volendo simulare il lancio di n dadi a sei facce, con n opportuno intero positivo, si avrà, con intuitivo significato dei simboli:
    Intervallo_dei_valori = [n, 6*n]
    Numero_di_valori = 6*n - n +1 = 5*n +1
    Valore_per_modulo = Numero_di_valori
    Offset = n

    In teoria, ogni lancio di n dadi è emulato dalla seguente singola linea di codice:
     
        val = Offset + (rand() % Valore_per_modulo);
    
    Si può però fare un ulteriore passo. Non avendo in genere alcuna necessità di visualizzare (né memorizzare) i singoli valori estratti, è possibile ignorare l'offset e sintetizzare il tutto in una singola assegnazione:
    
        Freq[rand() % Numero_di_valori] += 1;
    
    Dove Freq è ovviamente l'array delle frequenze, di dimensione pari a 5*n +1, opportunamente inizializzato con ogni locazione a zero.


    Ultima nota: la variabile di induzione per il loop principale dovrebbe (sempre) essere di tipo size_t e in ogni caso unsigned, tranne nei rarissimi casi in cui risulta esplicitamente necessario usare valori signed. Ciò, in casi come il presente, al fine di garantire il massimo range possibile in caso di numero elevato di simulazioni, ma soprattutto perché nel caso generale non ha alcun senso usare variabili di induzione (e indici) potenzialmente negative in linguaggio C.


    PS: Usa i tag code per presentare il codice sorgente!
Devi accedere o registrarti per scrivere nel forum
5 risposte