0

I'm trying to deal 5 cards to 4 different hands, however while the first card is distributed to each Hand, the next 4 cards are the copy of the first card (respective to the player). AFAIK the inner for loop distributes successive cards to each Hand the first time, but doesn't seem to work for the rest of the 4 cards. What is the error in my for loop?

main.c

#include "functions.h"
#include <stdlib.h>
#include <stdio.h>
#include  <crtdbg.h> 

int main(int argc, char ** argv)
{
    const int SuitSize = 13; //const int of 13 faces for the double for loop
    int i,j,k; //iterating variables


    Vector Deck; //create a vector Deck (with size, capacity, and ptr to card array)

    VectorInit(&Deck, 52); //initialize deck with 10, will grow later

    Card cardArray[52]; //create a Card type array of 52, fill with unshuffled Deck of Cards in for loop(s) below

    //outer loop is for Suits
    for (k = Clubs; k <= Spades; k++)
    {
        //inner for loop is for face
        for (j = Deuce; j <= Ace; j++)
        {
            cardArray[j - Deuce + k * SuitSize].suit = k; //j-Deuce is 2 - face pos plus k * 13 k
            cardArray[j - Deuce + k * SuitSize].face = j;

        }
    }

    //copy cardArray into Deck using AddToTail for the correct order
    for (i = 0; i < 52; ++i)
    {
        AddToTail(cardArray[i], &Deck);
        Deck.Items[i];
    }

    //array of vectors, each with ptr to an array of cards
    Vector Hands[4];

    for (int v = 0; v < 4; ++v)
    {
        VectorInit(&Hands[v], 5);
    }



    for (int c = 0; c < 5; ++c)
    {
        for (int h = 0; h < 4; ++h)
        {
            AddToTail(Deck.Items[h], &Hands[h]);

        }
    }



    system("pause");

}

functions.c

#include "functions.h"

    void VectorInit(Vector * vect, int capacity)
{
    vect->size = 0;             //initialize the size to 0 (no elements)
    vect->capacity = capacity;  //initialize capacity to 10, can grow later
    vect->Items = malloc(sizeof(Card) * capacity);
}

void Grow(Vector * vect)
{
    int i;

    if (vect->capacity < 0) //if the capacity ever reaches 0 or below, reset it to 10
        vect->capacity = 10;
    else
        vect->capacity *= 2; // 'grow' the capacity by doubling it

    Card *newStore;
    newStore = (Card*)malloc(vect->Items, (vect->capacity * sizeof(Card)));
    vect->Items = newStore;

    free(vect->Items);


}
void Add(Card card, int pos, Vector * vect)
{
    int i;
    if (vect->size == vect->capacity) //if the num of elements = capacity, the array is full - Grow it
        Grow(vect);

    //for (i = vect->size; i > pos; --i) //copy everything over by 1 to make an empty spot at pos
    //{
    //  vect->Items[i] = vect->Items[i - 1];
    //}
    vect->Items[pos] = card;        //add a provided index and value for insertion in Items array
    ++(vect->size);

}

void AddToTail(Card value, Vector * vect)
{
    Add(value, vect->size, vect);
}

functions.h

    #pragma once

typedef enum {Clubs,Diamonds,Hearts,Spades} Suits;
typedef enum{Deuce = 2,Three,Four,Five,Six,Seven,Eight,Nine,Ten,Jack,Queen,King,Ace} Face;

typedef struct card
{
    Suits suit;
    Face face;

} Card;

typedef struct vector
{
    Card * Items; //pointer to array of cards
    int size; //current num of elements
    int capacity; //max num of elements

}Vector;


void VectorInit(Vector * vect, int capacity);
void Grow(Vector * vect);
void Add(Card card, int pos, Vector * vect);
void AddToTail(Card value, Vector * vect);
V.M
  • 71
  • 1
  • 9
  • OT: regarding: `int main(int argc, char ** argv)` When the parameters to `main()` are not used, then to avoid two compiler warnings about unused parameters, use the signature: `int main( void )` – user3629249 Dec 15 '18 at 02:28
  • The posted code does not compile. Amongst other problems, it is missing the needed `#include` statements for the needed header files. Are you expecting us to guess as to which header files you actually included? – user3629249 Dec 15 '18 at 02:29
  • this statement: `Deck.Items[i];` has no effect. When compiling, always enable the warnings, then fix those warnings. ( for `gcc`, at a minimum use: `-Wall -Wextra -Wconversion -pedantic -std=gnu11` ) Note: other compilers use different options to do the same thing – user3629249 Dec 15 '18 at 02:32
  • @user3629249 that is just so I can manually see that each card is added through the debugger – V.M Dec 15 '18 at 02:36
  • regarding: `newStore = (Card*)malloc(vect->Items, (vect->capacity * sizeof(Card)));` 1) the function: `malloc()` only takes a single parameter. Maybe you were thinking of `calloc()` 2) in C, the returned type from any of the heap allocation functions: `malloc` `calloc` `realloc` is `void*` which can be assigned to any pointer. Casting just clutters the code, making it more difficult to understand, debug, etc – user3629249 Dec 15 '18 at 02:38
  • Shouldn't `Add` check if `pos < capacity`? – Barmar Dec 15 '18 at 02:39
  • in the function: `Grow()` MUCH better to use `realloc()` rather than calling `malloc()` and having to copy all the current data – user3629249 Dec 15 '18 at 02:39
  • @user3629249 He did that in his earlier question, I don't know why he removed it: https://stackoverflow.com/questions/53788067/accessing-writing-violation-in-c-vectors Maybe he misunderstood my comment saying that the malloc+copy was redundant. – Barmar Dec 15 '18 at 02:41
  • regarding the code sequence: `newStore = (Card*)malloc(vect->Items, (vect->capacity * sizeof(Card))); vect->Items = newStore; free(vect->Items);` That call to `free()` completely undid the call to `malloc()` Suggest re-thinking about what the posted code is trying to do. – user3629249 Dec 15 '18 at 02:41
  • regarding: `Deck.Items[i];` in the debugger (like `gdb`) use a statement like: `p Deck.Items[i]` – user3629249 Dec 15 '18 at 02:44
  • OT: when calling any of the heap allocation functions: `calloc` `malloc` `realloc`, always check (!=NULL) the returned value to assure the operation was successful. If == NULL, then call `perror( "your error message" );` so that both your error message AND text reason the system thinks the error occurred are output to `stderr` – user3629249 Dec 15 '18 at 02:48
  • The posted code calls `malloc()` several times, (however every call is causing the compiler to output a warning message or an error message. Due to wrong number of parameters (should only be 1 parameter) or due to passing `malloc()` a parameter that is not of type `size_t`. As if that wasn't a big enough problem, the result is a massive memory leak because all those calls to `malloc()` do not have a matching call to `free()` True, the OS will clean up when the program exits, but letting the OS perform the clean up is a very poor programming practice – user3629249 Dec 15 '18 at 02:56

1 Answers1

1

Other people have commented about code compiling and warnings, so I'll skip that. In the line:

AddToTail(Deck.Items[h], &Hands[h]);

Take note of which index into the Deck you're using. Each time the loop executes, it's using the same values for h. Think about how to change this so it does not use the same index into the deck (you want new cards each time, but that's not possible with the same index like this).

Chuck
  • 21
  • 2
  • 5