Sempre Tombola, generazione delle tabelle

di il
54 risposte

Sempre Tombola, generazione delle tabelle

Allora... scusate se apro mille topic ma sono sempre problemi diversi, ma sullo stesso progetto.
Dunque, stamattina mi sono svegliato con l'algoritmo bello chiaro in testa (spero).
Ecco cosa ho pensato:
Per prima cosa creo una cartella base (array CB). Sapendo che le cartelle sono formate da una tabella di 3x9, creo un array 2D. In ogni tabella però ci sono solo 15 numeri, ma non avrebbe senso creare un array 3x5 perchè mi genererebbe solo dei numeri da 1 da 59, e a me servono da 1 a 90. Ho pensato di riempire le cartelle di numeri random per colonna, e non per riga. Quindi prima riempio la prima colonna (numeri da 1 a 9), poi la seconda (da 10 a 19), ecc... Quindi, faccio il rand da 1 a 90 per un numero pseudocasuale e lo divido per 10 per vedere se può andare in quella colonna (esempio: sto lavorando sulla prima colonna... esce 49. Lo divido per 10 diventa (considerandolo int) 4, quindi la quarta colonna. Visto che 4 non corrisponde a 0 (indice che mi punta la colonna sulla quale sto lavorando), ripete l'estrazione. esce 3. 3/10 = 0. Corrisponde con l'indice, posso inserirlo). Sposto l'indice che guarda la riga non di 1 ma di un valore che può essere 1 o 2, in modo da non riempire l'intera colonna con i numeri. Ripeto tutto. Quindi sulla colonna avrò 2 numeri (9 e 4, ad esempio). faccio l'ordinamento (non considerando gli zero) in modo che mi ritrovo 4 e 9, poi vado alla colonna successiva. Finite le colonne, il processo è terminato.
Tutto fila, no?
Al resto ci penso dopo... in ogni caso... questo è il codice che ho scritto:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

//Dichiarazione array
int CB[3][15];
//Dichiarazione variabili
int i,j,rnd,cl,exists,jmp,min,temp,n;

void main()
{
srand(time(NULL));
//for (i=0; i<=14; ++i) {CB[i]=0;}
printf("Benvenuto nel gioco della Tombola!\nPremere un tasto per iniziare...");
getch();
system("cls");
for (n=0; n<14; ++n){
genera();
for (i=0; i<3; ++i){
    printf("\n");
    for (j=0; j<14; ++j)
    {
       printf("%d",CB[i][j]);
    }
    } }
system("PAUSE");
}

int genera() {
while (j<4) {
rnd = 1+rand()%90;
jmp = rand()%1;
cl = (rnd/10)+1;
if (cl == j) {
esiste();
if (exists == 0) {CB[j][i] = rand; j=j+jmp;} else {genera();}
ordina_I();
}
else {genera();}}
}

int esiste() {
for (j=0; j<9; ++j) {
for (i=0; i<3; ++i) {
if (rnd == CB[i][j]) {exists = 1;} else {exists = 0;}
}
}
}

int ordina_I() {
for (j=0; j<9;) {
for (i=0; i<3; ++i) {
cerca_min();
if (CB[i][j] != 0) {
if (CB[i][j] > min) {
temp = CB[0][j];
CB[0][j] = min;
A:
j++;
if (CB[j] != 0) CB[i][j] = temp; else goto A;
}}}}}

int cerca_min() {
for (j=0; j<9; ) {
for (i=0; i<3; ++i) {
min = CB[i][j];
A:
j++;
if (CB[i][j] < min) {
min = CB[i][j]; }
goto A;
}}}
A quanto pare non ci sono errori... ho dichiarato tutte le variabili che uso, ho dichiarato l'array, ho fatto più function in modo da rendere tutto chiaro... eppure non parte, mi riporta (Visual C++ 2010 Express) il seguente errore:
1>LINK : error LNK2001: simbolo esterno _mainCRTStartup non risolto
1>C:\Users\...\Debug\Prova.exe : fatal error LNK1120: 1 esterni non risolti
Cioè un problema nel linking, giusto?
Mi aiutate? Dove ho sbagliato? Non riesco a capirlo...

54 Risposte

  • Re: Sempre Tombola, generazione delle tabelle

    La funzione genera () in questa parte del codice :
    
    void main()
    {
    srand(time(NULL));
    //for (i=0; i<=14; ++i) {CB[i]=0;}
    printf("Benvenuto nel gioco della Tombola!\nPremere un tasto per iniziare...");
    getch();
    system("cls");
    for (n=0; n<14; ++n){
    genera();  <--------------------------------------------------------------
    for (i=0; i<3; ++i){
    .......
    ....
    ...
    int genera() {
    while (j<4) {   <---------------------------------------------
    rnd = 1+rand()%90;
    jmp = rand()%1;
    cl = (rnd/10)+1;
    if (cl == j) {   <------------------------------------------
    ....
    ..
    
    ma j l' hai solo dichiarata , dove la inizializzi?

    Comunque in generale, imposti il programma in un modo a che io odio xD, le variabili globali non si usano quasi mai e si utilizzano funzioni nelle quali gli passi le variabili ( parametri ), perchè io ( inteso come un qualsiasi programmatore esterno ) che leggo il programma, è difficile da comprendere oltre al fatto che tutte le variabili non servono sempre in tutto il programma ma solo in certi blocchi . Un' altra cosa , il void main non esiste , il main è solo di tipo int con un return 0
    
    int main () {
    
    programma...
    
    return 0 ;
    }
    
  • Re: Sempre Tombola, generazione delle tabelle

    La creazione di una tabelle non puoi semplicemetne creare una variabile che cambia nella funzione random?
    
    int aumento=1, appoggio =0 ;
    for ( int i = 0 ; i < colonne ; i ++ ) {
          for ( int j = 0 ; j < righe ; j ++ ) {
                    rnd = (aumento+rand()%(9+appoggio));
                      .................
          }
          appoggio=1; 
          aumento +=10;  // significa aumento = aumento+10;
    }
    
    Nella prima colonna rnd = 1+rand()%9 ;   ( numeri da 1 a 9 ) ( aumento = 1 e appoggio = 0 ) 
    Nella seconda colonna  rnd = 10+rand()%10 ( numeri da 10 a 19 )   ( aumento = 10 e appoggio= 1) 
    Nella terza  colonna rnd = 20+rand()%10   ( numeri da 20 a 29 ) ( aumento = 20 e appoggio = 1 ) 
    ec..... 
    
  • Re: Sempre Tombola, generazione delle tabelle

    E come fai a definire Nella prima colonna, nella seconda colonna, ecc..?
    Inoltre... è vero, ho dichiarato i.. ma che intendi per "dove l'hai inizializzata?"?
    Altra cosa..
    A che servono le variabili aumento e appoggio?
  • Re: Sempre Tombola, generazione delle tabelle

    Allora dove ho messo i puntini sta per dire lì va messo l' inserimento del valore che acquisisce rnd nella matrice CB che hai . aumento e appoggio servono per creare man mano numeri random adatti alla colonna, ti ho scritto
    
    Nella prima colonna rnd = 1+rand()%9 ;   ( numeri da 1 a 9 ) ( aumento = 1 e appoggio = 0 ) 
    Nella seconda colonna  rnd = 10+rand()%10 ( numeri da 10 a 19 )   ( aumento = 10 e appoggio= 1) 
    Nella terza  colonna rnd = 20+rand()%10   ( numeri da 20 a 29 ) ( aumento = 20 e appoggio = 1 ) 
    
    Tu fai una serie di calcoli per cercare di capire il numero se fa parte della prima , seconda terza ecc colonna , ma invece puoi benissimo eliminare tutto quell' algoritmo , che ti produce solo errrori. Ti spiego meglio cosa servono aumento e appoggio:

    nel tuo algorimo hai usato rnd = 1+rand()%90 che genera numeri da 1 a 90 perchè rand()%90 genera numeri da 0 a 89 e se metti un +1 diventa da 1 a 90 giusto?
    io ho fatto la stessa cosa solo che :

    i due cicli for sono i due famosi cicli per l' inserimento di valori in una matrice ( blocco righe e aumenti colonne o viceversa ) . In questo caso blocco le colonne e aumento le righe ( come anche te hai detto nella spiegazione )quindi nella prima colonna quali numeri ci devono essere? da 0 a 9 e quindi ho messo un :
    
    rnd = aumento+rand()%(9+appoggio); 
    
    dove aumento inizialmente vale 1 e appoggio 0 quindi diventa :
    
    rnd = 1+rand()%9 ; 
    
    giusto? e quindi genera numeri da 1 a 9 ( rand()%9 genererà numeri da 0 a 8 ma il +1 lo fa diventare da 1 a 9 )

    Ora finisce il ciclo interno, aumento incrementa di 10 , appoggio di 1 e quindi e si incrementa la colonna , quindi passiamo alla seconda colonna in cui ci devono essere valori da 10 a 19
    
    rnd = 10+rand()%(9+1) ; 
    
    genererà numeri da 10 a 19 perchè rand()%10 generà numeri da 0 a 9 ma mettendo un +10 genererà da 10 a 19 .

    Itera il procedimento in cui aumenta di 10 ogni volta e vedi che avrai sempre numeri da 10 a 19 , 20 a 29 , 30 a 39 .

    Ora che ci penso però ci sono due problemi :
    1) La prima volta aumento = 1 e facendo aumento = aumento+10 esso andrà a 11 , quindi si deve modificare

    2) L' ultima colonna è formata da numeri da 80 a 90 e no da 80 a 89 e quindi appoggio deve ritornare a 0 quindi possiamo modificarlo in questo modo:
    
    
    int aumento=1, appoggio =0, incremento=0 ;
    for ( int i = 0 ; i < colonne ; i ++ ) {
          for ( int j = 0 ; j < righe ; j ++ ) {
                    rnd = (aumento+rand()%(9+appoggio));
                    CB[j][i] = rnd;
          }
          if ( j == righe-2 ) 
                        appoggio=0;
          else 
                  appoggio = 1;
          incremento +=10; 
          aumento=incremento ;  
    }
    
  • Re: Sempre Tombola, generazione delle tabelle

    Sembra funzionare alla perfezione, dal punto di vista logico!
    Però ti prego, aiutami ancora un po'.. quel codice che hai messo tu.. dove lo devo inserire nel mio algoritmo intero? Mi copi il mio algoritmo opportunamente modificato con il tuo? Così lo leggo intero e lo capisco non al 90 ma al 100%! E così vedo anche se funziona, direttamente xD
  • Re: Sempre Tombola, generazione delle tabelle

    Ti consiglio di modificare anche le altre funzioni . Inanzitutto :
    
    int esiste() {
    for (j=0; j<9; j++) {
    for (i=0; i<3; i++) {
    if (rnd == CB[i][j]) {exists = 1;} else {exists = 0;}
    }
    }
    } 
    
    le funzioni non di tipo void ( nel tuo caso è int ) devono restituire un valore ( nel tuo caso un valore int ) quindi la funzione diventa così, te lo indento anche:
    
    int esiste() {
      for (j=0; j<9; j++) {
          for (i=0; i<3; i++) {
              if (rnd == CB[i][j]) return 1; 
              else return 0;
          }
       }
    }
    
    Ora il problema della creazione di una tabella è che in una colonna non devono esistere due numeri uguali , però non ti conviene che ogni volta che devi vedere se esiste in una colonna verifichi in tutta la matrice. Le variabili i e j nn devono essere globali perchè nella funzione esiste hanno un valore mentre nel main ne hanno un altro. Studiati bene il concetto di scope di una variabile.
    
    int rnd, CB[4][16];
    
    int main () {
       int i , j ;
       int aumento=1, appoggio =0, incremento=0 ;
       for ( int i = 0 ; i < colonne ; i ++ ) {
          for ( int j = 0 ; j < righe ; j ++ ) {
                    rnd = (aumento+rand()%(9+appoggio));
                    if ( esiste() == 0 )
                              CB[j][i] = rnd;  
                    else 
                           j--; // poichè non c'è stato inserimento allora ripeti questo ciclo decrementando j
          }
          if ( j == righe-2 ) 
                        appoggio=0;
          else 
                  appoggio = 1;
          incremento +=10; 
          aumento=incremento ;  
       }
       stampa();
       return 0;
    }
    
    int esiste() {
       int i , j ;
      for (j=0; j<9; ++j) {
          for (i=0; i<3; ++i) {
              if (rnd == CB[i][j]) return 1; 
              else return 0;
          }
       }
    }
    
    
    void stampa() {
       int i , j ; 
       for ( i = 0 ; i < 9 ; i ++ ) {
              for ( j = 0 ; j < 3 ; j++ ) 
           ..... 
    }
    
  • Re: Sempre Tombola, generazione delle tabelle

    C'era qualche erroruccio ovviamente ma ho corretto, niente di spaventoso xD
    Ora il mio codice è questo:
        #include <stdio.h>
        #include <stdlib.h>
        #include <time.h>
    
           int rnd, CB[4][16];
        int main () {
            srand(time(NULL));
           int i , j ;
           int aumento=1, appoggio =0, incremento=0 ;
           for ( i = 0 ; i < 9 ; i ++ ) {
              for ( j = 0 ; j < 3 ; j ++ ) {
                        rnd = (aumento+rand()%(9+appoggio));
                        if ( esiste() == 0 )
                                  CB[j][i] = rnd;
                        else
                               j--; // poichè non c'è stato inserimento allora ripeti questo ciclo decrementando j
              }
              if ( j == 3-2 )
                            appoggio=0;
              else
                      appoggio = 1;
              incremento +=10;
              aumento=incremento ;
           }
           stampa();
           return 0;
        }
    
        int esiste() {
           int i , j ;
          for (j=0; j<9; ++j) {
              for (i=0; i<3; ++i) {
                  if (rnd == CB[i][j]) return 1;
                  else return 0;
              }
           }
        }
    
    
        void stampa() {
           int i , j ;
           for ( i = 0 ; i < 3 ; i ++ ) {
               printf("\n");
                  for ( j = 0 ; j < 9 ; j++ ) {
    printf("%d ",CB[i][j]);
    
                  }
        }}
    
    Risultato:

    Praticamente ho perso il controllo dei numeri uguali... inoltre non stampa 15 numeri ma tutti... come devo fare?
  • Re: Sempre Tombola, generazione delle tabelle

    Ah mmm , allora forse è sbagliato questo approccio, allora vorrei capire per bene le regole della creazione delle tabelle ( non conosco molto la tombola XD )
    Nella tabella ci devono essere 15 numeri in posizioni random ovviamente rispettando la colonna ( da 20 a 29 nella terza colonna ecc... ) e poi ci deve essere almeno un numero per ogni colonna o può essere anche vuota?
  • Re: Sempre Tombola, generazione delle tabelle

    Le regole sono le seguenti:
    Una cartella è costituita da 9 colonne e 3 righe.
    In ogni riga ci sono cinque numeri.
    I numeri, come abbiamo visto, sono ordinati per colonna (prima colonna: da 1 a 9, seconda colonna: da 10 a 19, terza colonna: da 20 a 29, ecc... fino alla nona colonna: da 80 a 90 (eccezione)).
    Inoltre, i numeri sono ordinati in ordine crescente, in ogni colonna, dall'alto verso il basso.
    Ovviamente i numeri non possono essere uguali.
    Inoltre in ogni colonna ci possono essere 1 o 2 numeri, mai 3 (in quanto ogni colonna deve averne almeno uno, non ci può essere una colonna vuota).
    <- Esempio di cartelle già fatte
  • Re: Sempre Tombola, generazione delle tabelle

    Allora dobbiamo cambiare un pò tutto , guarda questo l' ho scritta stesso nel forum non in un editore e nè l' ho compilata , comunque ti vorrei far capire che poichè ci sono tante condizioni da verificare ( massimo due valori per colonna , 5 valori per riga , valori non uguali ecc... ) è meglio utilizzare più funzioni possibili per dividere il lavoro. Ecco una bozza , dovrebbe funzionare ma non te lo assicuro vedi se lo capisci ho cercato di indentare anche se non scrivendo in un editor ho dovuto fare manualmente :D. Ovviamente prima di fare l' insermento dei valori devi inserire il valore 0 a tutte le posizioni della matrice CB ( si dice inizializzare la matrice a 0 ) . Per l' ordinamento decrescente si deve utilizzare uno dei modi per l' ordinamento , tipo il bubblesort quello più conosciuto
    
    int rnd , CB[4][9],pos_riga;
    
    bool massimo_per_riga (  ) {  // funzione che controlla se nella riga ci sono 5 valori , in caso positivo restituisce true , altrimenti false
           int i , cont=0;
           for ( i = 0 ; i < 9 ; i++ ) {
                  if ( CB[pos_riga][i] != 0 ) cont++;
           }
           if ( cont == 5 ) return true;
           else return false;
    }
    
    bool pieno ( int appoggio ) {     // Se ci sono due valori diversi da 0 nella colonna appoggio allora restituisce true alrimenti false
          int i , cont=0; 
          for ( i = 0 ; i < 3 ; i++ ) {
                    if ( CB[i][appoggio] != 0 ) cont++;
          }
          if ( cont == 2 ) return true;
          else return false;
    }
    
    bool inserisci ( int appoggio ) {
         int i, int;
         bool continuo=true;
         if ( pieno(appoggio) )  // se nella colonna ci sono già due valori allora false diretto
                      return false;
         else { 
             for ( i = 0 ; i < 3 ; i ++ ) {    // controllo se esiste il valore nella colonna indicata da appoggio
                    if ( CB[i][appoggio] == rnd ) 
                                      return false;
              }   // se finisce il for significa che non esiste il valore rnd nella colonna appoggio
              while (continuo) {   // va a prendere la posizione della riga in cui non c'è già un valore nella colonna
                       pos_riga = rand()%3;   // la riga deve essere casuale , almeno così è dall' immagine che mi hai dato
                       if ( CB[pos_riga][appoggio] == 0 ); // se non c'è il valore abbiamo trovato la riga 
                                    break;
               }
               if ( !massimo_per_riga() ) return true;
               else return false;
    }
               
          
    
    int main ()  {
        int i , j , appoggio; 
        srand(time(null));
        for ( i = 0 ; i < 15 ; i ++ )  {  // 15 sta per quanti numeri devono essere inseriti nella matrice
                  rnd = 1+rand()%90;   // genera da 1 a 90 
                  appoggio = rnd/10;  // indicherà la colonna 
                  if ( appoggio == 9 ) appoggio = 8 ; // se il numero è 90 deve stare nella colonna 8
                  if ( !inserisci( appoggio) ) i--;  // se non è stato inserito ripeti il ciclo
                  else CB[pos_riga][appoggio] = rnd;
        }
        return 0 ;
    } 
    
  • Re: Sempre Tombola, generazione delle tabelle

    Con il bool mi da questo errore:
    |7|error: expected '=', ',', ';', 'asm' or '__attribute__' before 'massimo_per_riga'|
    Che significa? o.o
  • Re: Sempre Tombola, generazione delle tabelle

    Mmmm prova a chiamare la funzione massimo e basta
  • Re: Sempre Tombola, generazione delle tabelle

    Ok, l'ho corretto e si avvia.
    Genera "correttamente" la cartella, tranne per alcune cose.
    1. I numeri estratti non sono 15. A volte sono 13, altre 14, altre 12, ecc...
    2. Compaiono colonne vuote (giustamente, mancando quei due-tre numeri...
    Il codice attuale è questo:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
        int rnd , CB[4][9],pos_riga;
    
        int massimo_per_riga() {  // funzione che controlla se nella riga ci sono 5 valori , in caso positivo restituisce true , altrimenti false
               int i , cont=0;
               for ( i = 0 ; i < 9 ; i++ ) {
                      if ( CB[pos_riga][i] != 0 ) cont++;
               }
               if ( cont == 5 ) return 1;
               else return 0;
        }
    
        int pieno(int appoggio) {     // Se ci sono due valori diversi da 0 nella colonna appoggio allora restituisce true alrimenti false
              int i, cont=0;
              for (i = 0; i<3; i++) {
                        if ( CB[i][appoggio] != 0 ) cont++;
              }
              if ( cont == 2 ) return 1;
              else return 0;
        }
    
        int inserisci (int appoggio) {
             int i;
             int continuo=1;
             if (pieno(appoggio))  // se nella colonna ci sono già due valori allora false diretto
                          return 0;
             else {
                 for ( i = 0 ; i < 3 ; i ++ ) {    // controllo se esiste il valore nella colonna indicata da appoggio
                        if ( CB[i][appoggio] == rnd )
                                          return 0;
                  }   // se finisce il for significa che non esiste il valore rnd nella colonna appoggio
                  while (continuo) {   // va a prendere la posizione della riga in cui non c'è già un valore nella colonna
                           pos_riga = rand()%3;   // la riga deve essere casuale , almeno così è dall' immagine che mi hai dato
                           if ( CB[pos_riga][appoggio] == 0 ); // se non c'è il valore abbiamo trovato la riga
                                        break;
                   }
                   if ( !massimo_per_riga() ) return 1;
                   else return 0;
        }}
    
    
    
        int main () {
            int i , j , appoggio;
            srand(time(NULL));
            for ( i = 0 ; i < 15 ; i ++ )  {  // 15 sta per quanti numeri devono essere inseriti nella matrice
                      rnd = 1+rand()%90;   // genera da 1 a 90
                      appoggio = rnd/10;  // indicherà la colonna
                      if ( appoggio == 9 ) appoggio = 8 ; // se il numero è 90 deve stare nella colonna 8
                      if ( !inserisci( appoggio) ) i--;  // se non è stato inserito ripeti il ciclo
                      else CB[pos_riga][appoggio] = rnd;
            }
    		stampa();
    		getch();
            return 0 ;
        }
    
    
    		int stampa()
    {
        int i,j;
        printf("\nCartella base:\n");
        for (i=0; i<=2; i++)
        {
            printf("\n");
            for (j=0; j<=8; j++)
            {
                printf("%d\t",CB[i][j]);
            }
        }
    		}
  • Re: Sempre Tombola, generazione delle tabelle

    Sera a tutti. Io suggerirei di modifcare un pò il codice. Se come dici tu ogni scheda contiene 15 numeri, potresti creare semplicemente una matrice 3 x 5 , e dato che i numei vanno da 0 a 90, ogni colonna comprende valori che vanno da '(i*18)+1' a '(i*18)+18', con 'i' il numero di colonna ( essendo 18= 90 / 5 ) . dato che inserisci i numeri per colonna potresti definirti prima il tipo Colonna di dimensione 3 , e poi un array di Colonne che definisce la tua Cartella, ad esempio:
    
    typedef int Colonna[3];    //definisci il tipo Colonna
    typedef Colonna Cartella[5];    /definisci un tipo Cartella
    
    Le funzioni per la generazione dei numeri e per il controllo della duplicazione potrebbero essere implementate in questo modo:
    
    void GeneraCartella(Cartella& cartella){  //funzione per generare i numeri casuali nella cartella
        const int base[]={1,19,37,55,73};
        srand(time(NULL));
        for (int i=0;i<=4;++i){
            for(int j=0;j<=2;++j){
                int rnd;
                do{
                    rnd=base[i]+(rand() % 18);
                }while(NumeroEsistente(cartella[i],j,rnd));
                cartella[i][j]=rnd;
            }
        }
        cout<<"\nCartella generata!\n";
    }
    
    bool NumeroEsistente(const Colonna& colonna,int dim,int num){  //funzione per verificare l'esistenza di un numero in una colonna
        for(int i=0;i<dim;++i)
            if (colonna[i]==num) return true;
        return false;
    }
    
    eventualmente una funzione per la stampa della cartella:
    
    void StampaCartella(const Cartella& cartella){
        for(int i=0;i<=2;++i){
            printf("\n")
            for (int j=0;j<=4;++j)
                printf("%4d",cartella[j][i]);
        }
    }
    
    Prova e vedi se può essere una scelta valida
Devi accedere o registrarti per scrivere nel forum
54 risposte