[C] Mischiare e distribuire carte

di il
10 risposte

[C] Mischiare e distribuire carte

Ciao a tutti,
premetto che sono alle prime armi per quanto riguarda i puntatori, ho scritto un programma in C per la distribuzione di un mazzo di carte francesi (52 carte), in maniera casuale. Le carte vengono distribuite in una mano da poker all'italiana (5 carte). E devo vedere se nella mano sono presenti coppie, doppie coppie, tris, poker, colore e scala.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SIZE 5

void shuffle (int wDeck[][ 13 ] );
int* deal(const int wDeck[][13], const char *wFace[], const char *wSuit[]);
void pair(const int* hand[SIZE] ,const char *wFace[]);
void tris(const int* hand[SIZE], const char *wFace[]);
void poker(const int* hand[SIZE], const char *wFace[]);
void color(const int* hand[SIZE], const char *wSuit[]);

int main(int argc, char **argv){

    const char *suit[4] = {"Cuori", "Quadri", "Fiori", "Picche"};               //dichiaro e inizializzo il vettore dei semi
    const char *face[13] = {"Asso", "Due", "Tre", "Quattro", "Cinque",          //dichiaro e inizializzo il vettore delle facce
                            "Sei", "Sette", "Otto", "Nove", "Dieci",
                            "Jack", "Regina", "Re"};

    int deck[4][13] = {{0}};                                                    //dichiaro e inizializzo la matrice delle carte a zero
    int hand[SIZE];

    srand(time(NULL));                                                          //metto il time come seme per la randomicità

    shuffle(deck);                                                              //mischio il mazzo di carte
    hand[SIZE] = deal(deck, face, suit);                                        //distribuisco le carte
    pair(hand[SIZE], face);                                                     //controllo se ci sono copp i
    tris(hand[SIZE], face);                                                     //controllo se c'è untris
    poker(hand[SIZE], face);                                                    //controllo se c'è un poker
    color(hand[SIZE], suit);                                                    //controllo se c'è un colore

	return 0;
}

//mischia il mazzo di carte
void shuffle(int wDeck[][13]){
    int row;                                                                    //riga
    int column;                                                                 //colonna
    int card;                                                                   //contatore

    for(card = 0; card < 52; card++){
        do{
            row = rand() % 4;
            column = rand() % 13;
        }while(wDeck[row][column] != 0);

        wDeck[row][column] = card;
    }
}

//distribuisce le carte apppena mischiate
int* deal(const int wDeck[][13], const char *wFace[], const char *wSuit[]){
    int card;                                                                   //contatore delle carte
    int row;                                                                    //riga
    int column;                                                                 //colonna
    int hand[SIZE];

    for(card = 0; card < SIZE; card++){
        for(row = 0; row < 4; row++){
            for(column = 0; column < 13; column++){
                if(wDeck[row][column] == card){                                 //se la casella contiene la carta corrente la visualizza
                    hand[card] = wFace[column];
                    printf("%5s di %-8s\n", wFace[column], wSuit[row]);
                }
            }
        }
    }
    return hand[SIZE];
}

//controlla se è presente una coppia nella mano del giocatore
void pair(const int* hand[SIZE], const char *wFace[]){
    int key;                                                                    //chiave da ricercare nel vettore
    int count = 0;                                                              //contatore che stabilisce il punto
    int point;                                                                  //indica il punto
    int i, j;                                                                   //contatori

    for(i = 0; i < SIZE; i++){
        key = hand[i];
        for(j = 0; j < SIZE; j++){
            if(hand[j] == key && j != i){
                count++;
                point = hand[j];
                if(count == 2){
                    printf("\nCoppia di: %s", point);
                }
            }
        }
    }
}

//controlla se è presente un tris nella mano del giocatore
void tris(const int* hand[SIZE], const char *wFace[]){
    int key;                                                                    //chiave da ricercare nel vettore
    int count = 0;                                                              //contatore che stabilisce il punto
    int point;                                                                  //indica il punto
    int i, j;                                                                   //contatori

    for(i = 0; i < SIZE; i++){
        key = hand[i];
        for(j = 0; j < SIZE; j++){
            if(hand[j] == key && j != i){
                count++;
                point = hand[j];
                if(count == 3){
                    printf("\nTris di: %s", point);
                }
            }
        }
    }
}

//controlla se è presente un poker nella mano del giocatore
void poker(const int* hand[SIZE], const char *wFace[]){
    int key;                                                                    //chiave da ricercare nel vettore
    int count = 0;                                                              //contatore che stabilisce il punto
    int point;                                                                  //indica il punto
    int i, j;                                                                   //contatori

    for(i = 0; i < SIZE; i++){
        key = hand[i];
        for(j = 0; j < SIZE; j++){
            if(hand[j] == key && j != i){
                count++;
                point = hand[j];
                if(count == 4){
                    printf("\nPoker di: %s", point);
                }
            }
        }
    }
}

void color(const int* hand[SIZE], const char *wSuit[]){
    int key;                                                                    //chiave da ricercare nel vettore
    int count = 0;                                                              //contatore che stabilisce il punto
    int point;                                                                  //indica il punto
    int i, j;                                                                   //contatori

    for(i = 0; i < SIZE; i++){
        key = hand[i];
        for(j = 0; j < SIZE; j++){
            if(hand[j] == key && j != i){
                count++;
                point = hand[j];
                if(count == 5){
                    printf("\nColore di: %s", point);
                }
            }
        }
    }
}
Il programma va in segmentation fault da quando ho provato a far "ritornare" un vettore dalla funzione deal, in modo che la mano potesse essere la stessa per le altre funzioni come pair, tris, poker, color. Come posso risolvere?

10 Risposte

  • Re: [C] Mischiare e distribuire carte

    Da dove hai copiato quel codice? Sicuro che la funzione deal sia scritta così ?
  • Re: [C] Mischiare e distribuire carte

    oregon ha scritto:


    Da dove hai copiato quel codice? Sicuro che la funzione deal sia scritta così ?
    Si, come vedi ora la distribuzione delle carte funziona ed è perfetto. Ma il problema si è evoluto ora
  • Re: [C] Mischiare e distribuire carte

    Che vuol dire "il problema si è evoluto"??
  • Re: [C] Mischiare e distribuire carte

    oregon ha scritto:


    Che vuol dire "il problema si è evoluto"??
    Ho aggiornato il codice, cercando di distribuire una mano di poker (5 carte) e riesce. Ma al momento di calcolare i punti in mano va in segmentation fault.
    Devo aprire un nuovo thread perchè ho risolto per quanto riguarda la distribuzione o posso modificare questo?
  • Re: [C] Mischiare e distribuire carte

    Uno dei problemi fondamentali per i neofiti (ma non e', ovviamente, una colpa), e' non riuscire a capire quando le cose FUNZIONANO PER SBAGLIO.

    Cioe' SEMBRANO funzionare, ma in realta', ci sono degli errori di fondo che non permettono di 'continuare' lo sviluppo.

    Ora, il tuo codice e' TROPPO COMPLESSO per le tue attuali conoscenze: mantenere in parallelo DUE strutture dati sempre coerenti, non e' semplice.

    Prova a semplificare il tutto nel seguente modo:

    1) le carte sono 13 per 4 segni diversi. INVECE di usare 2 vettori, usa questo trucco: CARTA = SEGNO*100+VALORE,
    dove SEGNO=1,2,3,4 e VALORE=1,2,...13.

    in questo modo hai un unico numero intero che contiene entrambe le informazioni.

    2) usi UN VETTORE di 52 interi che inizializzi opportunamente (101, ...112,201,...413): e' come avere le carte belle che ordinate
    3) ora MESCOLI il vettore, scambiando un indice del vettore (scelto in modo ordinato) con un'altro scelto a caso. In questo modo ottieni un mazzo perfettamente mescolato.
    4) mantieni un indice di qualle sia la prossima carta dispoinibile: tale indice non e' altro che in indice del vettore.
    5) quando assegni una carta ad un giocatore, usi l'indice nel vettore delle carte per scegliere la carta, quindi incrementi l'indice: questo non e altro che la gestione di uno stack usando un array e degli indici.

    Ovviamente, per sapere il valore della carta, basta fare (CARTA %100) e per avere il segno (CARTA/100)

    Questo ti semplifica notevolmente il codice che hai scritto e ti permette di identificare meglioeventuali errori.
  • Re: [C] Mischiare e distribuire carte

    migliorabile ha scritto:


    Uno dei problemi fondamentali per i neofiti (ma non e', ovviamente, una colpa), e' non riuscire a capire quando le cose FUNZIONANO PER SBAGLIO.

    Cioe' SEMBRANO funzionare, ma in realta', ci sono degli errori di fondo che non permettono di 'continuare' lo sviluppo.

    Ora, il tuo codice e' TROPPO COMPLESSO per le tue attuali conoscenze: mantenere in parallelo DUE strutture dati sempre coerenti, non e' semplice.

    Prova a semplificare il tutto nel seguente modo:

    1) le carte sono 13 per 4 segni diversi. INVECE di usare 2 vettori, usa questo trucco: CARTA = SEGNO*100+VALORE,
    dove SEGNO=1,2,3,4 e VALORE=1,2,...13.

    in questo modo hai un unico numero intero che contiene entrambe le informazioni.

    2) usi UN VETTORE di 52 interi che inizializzi opportunamente (101, ...112,201,...413): e' come avere le carte belle che ordinate
    3) ora MESCOLI il vettore, scambiando un indice del vettore (scelto in modo ordinato) con un'altro scelto a caso. In questo modo ottieni un mazzo perfettamente mescolato.
    4) mantieni un indice di qualle sia la prossima carta dispoinibile: tale indice non e' altro che in indice del vettore.
    5) quando assegni una carta ad un giocatore, usi l'indice nel vettore delle carte per scegliere la carta, quindi incrementi l'indice: questo non e altro che la gestione di uno stack usando un array e degli indici.

    Ovviamente, per sapere il valore della carta, basta fare (CARTA %100) e per avere il segno (CARTA/100)

    Questo ti semplifica notevolmente il codice che hai scritto e ti permette di identificare meglioeventuali errori.
    Ti ringrazio per il consiglio, ma l'esercizio si trova proprio alla fine del capitolo dei puntatori, quindi dovrei risolvero utilizzando principalmente puntatori e vettori, potresti spiegarmi precisamente dove ho sbagliato? Perchè, personalmente, credo di aver fatto qualche errore per quanto riguarda il passaggio di puntatori e vettori a funzioni.
  • Re: [C] Mischiare e distribuire carte

    Ma tu hai compilato quel codice senza errori? Mi sembra impossibile.

    Non puoi scrivere

    hand[SIZE] = deal(deck, face, suit);

    dato che deal restituisce un puntatore e tanto meno nella stessa deal puoi usare un vettore locale per restituirne il valore (fra l'altro in modo sbagliato con la return che hai usato).

    Insomma, controlla gli errori che ti fornisce il compilatore prima di tutto.
  • Re: [C] Mischiare e distribuire carte

    oregon ha scritto:


    Ma tu hai compilato quel codice senza errori? Mi sembra impossibile.

    Non puoi scrivere

    hand[SIZE] = deal(deck, face, suit);

    dato che deal restituisce un puntatore e tanto meno nella stessa deal puoi usare un vettore locale per restituirne il valore (fra l'altro in modo sbagliato con la return che hai usato).

    Insomma, controlla gli errori che ti fornisce il compilatore prima di tutto.
    Allora: il codice è stato ripristinato al semplice problema originario di mescolamento e distribuzione di carte.
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    void shuffle (int wDeck[][ 13 ] );
    void deal(const int wDeck[][13], const char *wFace[], const char *wSuit[]);
    
    
    int main(int argc, char **argv){
    
        const char *suit[4] = {"Cuori", "Quadri", "Fiori", "Picche"};               //dichiaro e inizializzo il vettore dei semi
        const char *face[13] = {"Asso", "Due", "Tre", "Quattro", "Cinque",          //dichiaro e inizializzo il vettore delle facce
                                "Sei", "Sette", "Otto", "Nove", "Dieci",
                                "Jack", "Regina", "Re"};
    
        int deck[4][13] = {{0}};                                                    //dichiaro e inizializzo la matrice delle carte a zero
    
        srand(time(NULL));                                                          //metto il time come seme per la randomicità
    
        shuffle(deck);                                                              //mischio il mazzo di carte
        deal(deck, face, suit);                                                     //distribuisco le carte
    
    	return 0;
    }
    
    //mischia il mazzo di carte
    void shuffle(int wDeck[][13]){
        int row;                                                                    //riga
        int column;                                                                 //colonna
        int card;                                                                   //contatore
    
        for(card = 0; card < 52; card++){
            do{
                row = rand() % 4;
                column = rand() % 13;
            }while(wDeck[row][column] != 0);
    
            wDeck[row][column] = card;
        }
    }
    
    //distribuisce le carte apppena mischiate
    void deal(const int wDeck[][13], const char *wFace[], const char *wSuit[]){
        int card;                                                                   //contatore delle carte
        int row;                                                                    //riga
        int column;                                                                 //colonna
    
        for(card = 0; card < 5; card++){
            for(row = 0; row < 4; row++){
                for(column = 0; column < 13; column++){
                    if(wDeck[row][column] == card){                                 //se la casella contiene la carta corrente la visualizza
                        printf("%5s di %-8s\n", wFace[column], wSuit[row]);
                    }
                }
            }
        }
    }
    Di errori non ce ne sono, ma ci sono due Warning:
    -pokerCasualCards'nPoints.c:45:5: warning: passing argument 1 of ‘deal’ from incompatible pointer type [enabled by default]
    -pokerCasualCards'nPoints.c:30:6: note: expected ‘const int (*)[13]’ but argument is of type ‘int (*)[13]’

    Non saprei cosa andare a vedere per risolvere questi due Warning. Per quanto invece riguarda il sistema dei punti pensavo di far tornare (non so in che modo) i valori dalla funzione deal poichè ora come ora stampa solo a schermo i risultati della distribuzione, Una volta restituita la mano dalla funzione deal poi credo di sapere come vedere eventuali punti, eccetto le scale.
  • Re: [C] Mischiare e distribuire carte

    
    void shuffle(int wDeck[][13]){
        int row;                                                                    //riga
        int column;                                                                 //colonna
        int card;                                                                   //contatore
    
        for(card = 0; card < 52; card++){
            do{
                row = rand() % 4;
                column = rand() % 13;
            }while(wDeck[row][column] != 0);
    
            wDeck[row][column] = card;
        }
    }
    
    Questo codice NON HA SENSO!

    Oppure, facciamo una cosa un po' piu' seria: DESCRIVI DETTAGLIATAMENTE cosa DOVREBBE fare
    Aggiungi le note come commenti.
    In questo modo possiamo capire dove il tuo ragionamento fa acqua

    Ricorda: si impara SOLO sbagliando Nessuno nasce IMPARATO
  • Re: [C] Mischiare e distribuire carte

    Perchè dici che non ha senso? Inizializzo tutte le caselle dalla matrice "MAZZO" con 0. Poi attraverso il ciclo for e successivamente grazie al do-while, estraggo a caso una colonna (FACCIA) e una riga (SEME), e se non è già stata assegnata, assegno a quella casella la carta.
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    void shuffle (int wDeck[][ 13 ] );
    void deal(const int wDeck[][13], const char *wFace[], const char *wSuit[]);
    
    
    int main(int argc, char **argv){
    
        const char *suit[4] = {"Cuori", "Quadri", "Fiori", "Picche"};               //dichiaro e inizializzo il vettore dei semi
        const char *face[13] = {"Asso", "Due", "Tre", "Quattro", "Cinque",          //dichiaro e inizializzo il vettore delle facce
                                "Sei", "Sette", "Otto", "Nove", "Dieci",
                                "Jack", "Regina", "Re"};
    
        int deck[4][13] = {{0}};                                                    //dichiaro e inizializzo la matrice delle carte a zero
    
        srand(time(NULL));                                                          //metto il time come seme per la randomicità
    
        shuffle(deck);                                                              //mischio il mazzo di carte
        deal(deck, face, suit);                                                     //distribuisco le carte
    
    	return 0;
    }
    
    //mischia il mazzo di carte
    void shuffle(int wDeck[][13]){
        int row;                                                                    //riga
        int column;                                                                 //colonna
        int card;                                                                   //contatore
    
        for(card = 0; card < 52; card++){           //eseguo il ciclo che deve mischiare le carte
            do{
                row = rand() % 4;                   //casualmente estraggo un seme
                column = rand() % 13;               //casualmente estraggo una faccia
            }while(wDeck[row][column] != 0);        //il do-while si ripete ogni volta che incontro una casella già assegnata (una carta già mescolata)
    
            wDeck[row][column] = card;              //se la casella non è assegnata gli assegno la carta
        }
    }
    
    //distribuisce le carte apppena mischiate
    void deal(const int wDeck[][13], const char *wFace[], const char *wSuit[]){
        int card;                                                                   //contatore delle carte
        int row;                                                                    //riga
        int column;                                                                 //colonna
    
        for(card = 0; card < 5; card++){                                            //distribuisco le prime 5 carte del mazzo
            for(row = 0; row < 4; row++){                                           //scorro i semi (colonne)
                for(column = 0; column < 13; column++){                             //scorro le faccie (righe)
                    if(wDeck[row][column] == card){                                 /*se la casella ha lo stesso indice del contatore allora la stampa
                                                                                    significa che scorrendo la matrice cerco la prima del mazzo, la seconda ecc...*/
                        printf("%5s di %-8s\n", wFace[column], wSuit[row]);         //visualizzo le prime 5 carte del mazzo con relativo seme
                    }
                }
            }
        }
    }
    Questo è il codice commentato con maggiore precisione.
Devi accedere o registrarti per scrivere nel forum
10 risposte