0

These are my two structs:

typedef struct _card {
    int suit;
    int value;
} card;

typedef struct _deck {
    int num_cards;
    card *cards;
} deck;

This is my make a card function:

card *make_card(int suit, int value)
{
  card *newCard = malloc(sizeof(card));
  newCard->suit = suit;
  newCard->value = value;

  return newCard;
}

Now is where I am a bit stuck. I have to make a deck of cards. I know how to assign each value to the card, but I am stumped on how to allocate it in memory. I know it has to do with an array of cards in the deck struct but i cant figure out how.

deck *make_standard_deck()
{
  for (int i = 0; i <= 3; i++)
  {
    for (int j = 1; j <= 13; j++)
    {
      deck.cards[i] = make_card(int suit, int value);
    }
  }
}
AndersK
  • 35,813
  • 6
  • 60
  • 86
user3380850
  • 11
  • 1
  • 3
  • 8
  • You should pick one of C or C++. The answers would be different in either language. Your code looks more like C. – juanchopanza Apr 11 '14 at 05:56
  • You need to `malloc` the deck struct, `malloc` the cards within it, set the deck size, and figure out how to index the deck elements given your `i` and `j` values. – ooga Apr 11 '14 at 06:00

4 Answers4

1

You should allocate the whole array of cards first then assign the individual cards later. Alt. you could also use realloc to make the array increasingly longer but that seems unnecessary here.

first change make_card (and maybe rename it)

card *init_card(card* newCard, int suit, int value)
{
  newCard->suit = suit;
  newCard->value = value;
  return newCard;
}

then change make_standard_deck

deck *make_standard_deck()
{
  const int numberOfValues = 13; // use constants when you can
  const int numberOfSuits = 4;

  deck* d = malloc(sizeof(deck)); // normally check return value
  d->num_cards = numberOfValues*numberOfSuits;
  d->cards = malloc(sizeof(card) * (d->num_cards));

  for (int i = 0; i < numberOfSuits; i++)
  {
    for (int j = 0; j < numberOfValues; j++)
    {
      // pass the card to initialized to the function
      // same as &(d->cards[i])
      init_card(d->cards + i, i + 1, j + 1);
    }
  }
  return d;
}

when you free it

void freeDeck( deck *d )
{
  if ( d != NULL )
  {
    free( d->cards );
  }
  free( d );
}
AndersK
  • 35,813
  • 6
  • 60
  • 86
1

To create a deck, first allocate memory for the deck structure, and then (assuming that you want an array of pointers to cards) allocate memory for the pointer array. Here's an example that creates a standard deck of 52 cards.

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

typedef struct _card {
    int suit;
    int value;
} card;

typedef struct _deck {
    int num_cards;
    card **cards;
} deck;

card *make_card(int suit, int value)
{
    card *newCard = malloc(sizeof(card));
    newCard->suit = suit;
    newCard->value = value;

    return newCard;
}

deck *make_standard_deck( void )
{
    deck *newDeck = malloc( sizeof(deck) );

    newDeck->num_cards = 52;
    newDeck->cards = malloc( 52 * sizeof(card *) );

    int index = 0;
    for ( int suit = 0; suit < 4; suit++ )
        for ( int value = 1; value <= 13; value++ )
            newDeck->cards[index++] = make_card( suit, value );

    return newDeck;
}

int main( void )
{
    int i;

    deck *stdDeck = make_standard_deck();

    for ( i = 0; i < stdDeck->num_cards; i++ )
        printf( "suit=%d value=%2d\n", stdDeck->cards[i]->suit, stdDeck->cards[i]->value );

    /* free the deck when we're done with it */
    for ( i = 0; i < stdDeck->num_cards; i++ )
        free( stdDeck->cards[i] );
    free( stdDeck->cards );
    free( stdDeck );
}
user3386109
  • 34,287
  • 7
  • 49
  • 68
  • You forget to free `newDeck->cards`. It would be better to put those freeing routines in separate functions. – user694733 Apr 11 '14 at 06:48
  • @user694733 thanks, I added the `free` code as an afterthought. You're right that it belongs in its own function. – user3386109 Apr 11 '14 at 06:51
0

If you know before hand the number of cards in the deck (say 52) then you can do it this way:

deck deck_cards[4][13];

for (int i = 0; i < 4; i++)
    {
            for (int j = 0; j < 13; j++)
            {
               deck_cards[i][j].cards = make_card(suit, value);
            }
     }
0xF1
  • 6,046
  • 2
  • 27
  • 50
  • I don't think this makes sense. Now you have 52 decks with one card on each. – user694733 Apr 11 '14 at 06:30
  • Well, in that case, OP's structure needs to be changed or he should make a linked list of cards with start at `deck.card` – 0xF1 Apr 11 '14 at 06:36
0

I'd do something like this

struct Card
{
    int suit;
    int value;
};

struct Deck
{
    int num_cards;
    Card *cards;
};

//instead of returning a pointer simply return a Card struct
Card make_card(int suit, int value)
{
    Card newCard;
    newCard.suit = suit;
    newCard.value = value;

    return newCard;
}

Deck *deck = (Deck*) malloc(sizeof(Deck));
//So here's the part you're struggling with? Simply malloc num_cards of Card structs.
deck->cards = (Card*) malloc(sizeof(Card) * deck->num_cards);

//Now iterate through each Card struct in the deck
for(int i etc......)
    deck->cards[i] = make_card(suit, value); //make_card returns Card struct

So the deck holds a pointer to an array of cards based off of the decks num_cards value. Of course make sure to actually set num_cards beforehand unlike this example.

TerraOrbis
  • 91
  • 4
  • Casting return value of `malloc` should **not** be done in C. And you are missing `typedef` on `Deck` and `Card`: this will not compile. – user694733 Apr 11 '14 at 06:34
  • In `Card make_card(int suit, int value) { Card newCard; newCard.suit = suit; newCard.value = value; return newCard; }` the `newCard` is local variable you should not return it. – 0xF1 Apr 11 '14 at 06:39
  • @MadHatter It is OK to pass-by-value. – user694733 Apr 11 '14 at 06:40
  • @user694733 This is C++ not C. No need to typedef a struct. And why should the casting not be done? I can't even compile this without the cast. – TerraOrbis Apr 11 '14 at 18:02
  • @user694733 I didn't realize this question was actually tagged C but still it's kind of a small issue. Now in C sure casting isn't needed but why should it **not** be done? – TerraOrbis Apr 11 '14 at 18:09
  • @TerraOrbis [This answer](http://stackoverflow.com/a/605858/694733) explains it better than I could. – user694733 Apr 14 '14 at 06:11
  • @user694733 Ah ok I've been doing C++ too long I guess. Forgot some of my C roots. – TerraOrbis Apr 14 '14 at 22:56