Dealing playing cards to four arrays

Viewed 113

when I am trying to deal 52 card to four players using structure, The code works but the problem is in output it got some mistake:

#include <stdio.h>
#include <time.h>

typedef struct {
    char *value;
    char *type;
}card;


int main()
{
    srand(time(NULL));
    int i, r;
    char name[4][9] = {{"diamonds"},{"clubs"},{"hearts"},{"spades"}};
    char num[13][6] = {{"ace"},{"two"},{"three"},{"four"},{"five"},{"six"},{"seven"},{"eight"},{"nine"},{"ten"},{"jack"},{"queen"},{"king"}};
    
    card c[52];
    card temp;
    card player1[13], player2[13], player3[13], player4[13];
    
    for (i=0 ; i<52 ; i++){
        c[i].type = name[i % 4];
        c[i].value = num[i % 13];
    }
    
    for (i=0 ; i<52 ; i++){
    r= rand() % 52;
    temp = c[i];
    c[i] = c[r];
    c[r] = temp;
        
    }
    
    for (i=0 ; i<52 ; i++){
        switch(i+1 % 4){
            case 0:
                player1[i].type= c[i].type;
                player1[i].value= c[i].value;
                break;
            case 1:
                player2[i].type= c[i].type;
                player2[i].value= c[i].value;
                break;
            case 2:
                player3[i].type= c[i].type;
                player3[i].value= c[i].value;
                break;
            default:
                player4[i].type= c[i].type;
                player4[i].value= c[i].value;
        }
    }
    
    printf("Player 1 \n");
    for (i=0 ; i<13 ; i++){
        printf("%s %s\n" , player1[i].type, player1[i].value);
    }
    printf("\n");
    
    printf("Player 2 \n");
    for (i=0 ; i<13 ; i++){
        printf("%s %s\n" , player2[i].type, player2[i].value);
    }
    printf("\n");
    
    printf("Player 3 \n");
    for (i=0 ; i<13 ; i++){
        printf("%s %s\n" , player3[i].type, player3[i].value);
    }
    printf("\n");
    
    printf("Player 4 \n");
    for (i=0 ; i<13 ; i++){
        printf("%s %s\n" , player4[i].type, player4[i].value);
    }
    printf("\n");
    
    
    

    return 0;
}

output: Player 1 hearts nine diamonds king hearts ten diamonds ten spades jack clubs king hearts four spades eight spades king clubs jack spades two diamonds jack hearts jack

Player 2 spades six hearts queen diamonds ace spades five diamonds six hearts seven clubs eight clubs seven spades ace hearts three hearts king diamonds two clubs six

Player 3 spades three diamonds seven clubs queen hearts six hearts five diamonds three spades nine clubs three spades queen clubs ace clubs two diamonds four hearts ace

Player 4 à└ëD$@ï╪☼ê°♥ (null) (null) (null) hearts two hearts eight diamonds nine clubs five spades seven clubs nine spades four clubs ten diamonds eight diamonds queen clubs four

It got in player 4 null and strange characters, any solution please.

3 Answers

Your problem occurs in your deal loop when you loop for (i=0 ; i<52 ; i++) setting player1[i], player2[i], and so on. You declare your player arrays with 13 elements. So in your loop, when i > 12 you invoke Undefined Behavior attempting to write to the 13th element and beyond.

To solve the problem, you need to limit your player index to 0-12 you can either use i % 13, e.g.

    for (i=0 ; i<52 ; i++) {
        switch (i % 4){
            case 0:
                player1[i%13] = c[i];
                break;
            case 1:
                player2[i%13] = c[i];
                break;
            case 2:
                player3[i%13] = c[i];
                break;
            default:
                player4[i%13] = c[i];
        }
    }

Or keep separate counters for your player indexes and increment each as the cards are dealt. Making the changes, you would have, e.g.

    int p1 = 0, p2 = 0, p3 = 0, p4 = 0;
    ...
    for (i=0 ; i<52 ; i++) {
        switch (i % 4){
            case 0:
                player1[p1++] = c[i];
                break;
            case 1:
                player2[p2++] = c[i];
                break;
            case 2:
                player3[p3++] = c[i];
                break;
            default:
                player4[p4++] = c[i];
        }
    }

(note: you can simply assign the structs, no need for separate values. you can remove the +1 from switch (i % 4).)

Now your hands will deal without a SegFault.

Since you declared Player structure array size 13 but you are passing upto 52 that's why it's showing null name. You should always pass upto <13 index in Player structure. To do that pass player[i%13] value by Mod of 13.

player[i%13].type= c[i].type;
player[i%13].value= c[i].value;

When you pass for(i=0 ; i<52 ; i++) your loop pass big size. Mod 13 indicate a player will take upto 12 value.

#include <stdio.h>
#include<math.h>

typedef struct {
    char *value;
    char *type;
}card;


int main()
{
    int i, r;
    char name[4][9] = {{"diamonds"},{"clubs"},{"hearts"},{"spades"}};
    char num[13][6] = {{"ace"},{"two"},{"three"},{"four"},{"five"},{"six"},{"seven"},{"eight"},{"nine"},{"ten"},{"jack"},{"queen"},{"king"}};

    card c[52];
    card temp;
    card player1[13], player2[13], player3[13], player4[13];

    for (i=0 ; i<52 ; i++){
        c[i].type = name[i % 4];
        c[i].value = num[i % 13];
    }

    for (i=0 ; i<52 ; i++){
    r= rand() % 51;
    temp = c[i];
    c[i] = c[r];
    c[r] = temp;

    }
    for (i=0 ; i<52 ; i++){
        int ind=i+1;
        switch(ind % 4){
            case 0:
                player1[i%13].type= c[i].type;
                player1[i%13].value= c[i].value;
                break;
            case 1:
                player2[i%13].type= c[i].type;
                player2[i%13].value= c[i].value;
                break;
            case 2:
                player3[i%13].type= c[i].type;
                player3[i%13].value= c[i].value;
                break;
            default:
                player4[i%13].type= c[i].type;
                player4[i%13].value= c[i].value;
        }
    }

    printf("Player 1 \n");
    for (i=0 ; i<13 ; i++){
        printf("%s %s\n" , player1[i].type, player1[i].value);
    }
    printf("\n");

    printf("Player 2 \n");
    for (i=0 ; i<13 ; i++){
        printf("%s %s\n" , player2[i].type, player2[i].value);
    }
    printf("\n");

    printf("Player 3 \n");
    for (i=0 ; i<13 ; i++){
        printf("%s %s\n" , player3[i].type, player3[i].value);
    }
    printf("\n");

    printf("Player 4 \n");
    for (i=0 ; i<13 ; i++){
        printf("%s %s\n" , player4[i].type, player4[i].value);
    }
    printf("\n");

    return 0;
}

Here's a possible implementation that does what you asked:

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

#define PLAYERS_NUM 4
#define CARDS_PER_PLAYER 13
#define NAMES_NUM 4
#define VALUES_NUM 13
#define TOTAL_CARDS NAMES_NUM*VALUES_NUM

typedef struct {
    char *value;
    char *type;
} card;

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

    unsigned int i, j, r;
    char *name[NAMES_NUM] = {"diamonds", "clubs", "hearts", "spades"};
    char *num[VALUES_NUM] = {"ace", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "jack",
                             "queen", "king"};

    // Initialize pile.
    card cards[TOTAL_CARDS];
    for (i = 0; i < NAMES_NUM; i++) {
        for (j = 0; j < VALUES_NUM; j++) {
            cards[(i * VALUES_NUM) + j] = (card) {name[j], num[i]};
        }
    }

    card tmp;
    // Shuffle pile.
    for (i = 0; i < TOTAL_CARDS; i++) {
        r = rand() % TOTAL_CARDS;
        tmp = cards[r];
        cards[r] = cards[i];
        cards[i] = tmp;
    }

    card players[PLAYERS_NUM][CARDS_PER_PLAYER];

    // Deal cards.
    for (i = 0; i < PLAYERS_NUM; i++) {
        for (j = 0; j < CARDS_PER_PLAYER; j++) {
            players[i][j] = cards[i * CARDS_PER_PLAYER + j];
        }
    }

    // Printing.
    for (i = 0; i < PLAYERS_NUM; i++) {
        printf("Player %d\n", i);
        for (j = 0; j < CARDS_PER_PLAYER; j++) {
            printf("%s %s\n", players[i][j].type, players[i][j].value);
        }
        printf("\n");
    }

    return 0;
}

A couple of points:

  • You didn't include #include <stdlib.h>.
  • You didn't deal the cards, there could have been duplicated cards, this implementation shuffles the cards and deals them without repetitions.
  • You don't need 4 arrays to hold the players, a two-dimensional array is better (also later to pass on to functions).
  • The code can look cleaner if you use defined values instead of repeating them over and over again, that way they can also be changed in one place and take effect everywhere.
  • You don't need to define the names and values' sizes, if you're not planning on changing them, they will be a static const string, so just defines as char *, that way you don't need to find the longest string, and allocate useless data.
Related