📋 Instructions: Implementing a Card Game in C

This document describes the requirements for creating a card game management system in C, including data structure definitions and function implementations.

General Grading Rule:
0.5 points will be deducted for each function that is implemented but not tested in the main function.


Part 1: Type Definitions (cards.h File)

1.1 Project Context

We want to define types to handle playing cards. Our playing cards are either cards with a numeric value (from 1 to 10) and a suit (spades, hearts, diamonds, or clubs), or named cards (e.g., "joker").

1.2 Type Specifications

1.3 Grading Criteria (Types)


Part 2: Function Implementation (cards.c File)

You must implement the following functions (prototyped in cards.h) respecting the grading criteria below.

2.1 Card Creation Functions (4 points)

card* createclassiccard(int value, color col);
card* createnamedcard(const char* name);
card* createclassiccard(int value, color col){
    if (value < 1 || value > 10 || col > CLUBS)
    {
        fprintf(stderr, "wrong arguments for creating a card\n");
        exit(EXIT_FAILURE);
    }
    card* res = mallocandcheck(sizeof(card));
    res->is_named = false;
    res->data.numeric.col=col;
    res->data.numeric.value=value;
    return res;
}

card* createnamedcard(const char* name){
    if (name == NULL)
    {
        fprintf(stderr, "wrong arguments for creating a card\n");
        exit(EXIT_FAILURE);
    }
    card* res = mallocandcheck(sizeof(card));
    res->is_named = true;
    int length = 0;
    while(name[length] != '\0'){
        length++;
    }
    res->data.name = mallocandcheck(length+1);
    int i = 0;
    while(i < length+1){
        res->data.name[i] = name[i];
        i++;
    }
    return res;
}

2.2 Deck Creation (2 points)

deck* createonecarddeck(card* c);
deck* createonecarddeck(card* c){
    deck* res = mallocandcheck(sizeof(deck));
    res->nb_cards=1;
    res->start = mallocandcheck(sizeof(clist));
    res->start->content = c;
    res->start->next = NULL;
    res->start->previous = NULL;
    res->start->ptr_deck = res;
    return res;
}

2.3 Adding a Card (4 points)

void addcardbefore(clist* l, card* newcard);
void addcardbefore(clist* l, card* newcard){
    clist* newclist = mallocandcheck(sizeof(clist));
    clist* tmp = l->previous;
    l->previous = newclist;
    l->ptr_deck->nb_cards++;
    newclist->content = newcard;
    newclist->next = l;
    newclist->previous = tmp;
    if(tmp == NULL)
    {
        newclist->ptr_deck = l->ptr_deck;
        l->ptr_deck->start = newclist;
    }
    else
    {
        newclist->ptr_deck = tmp->ptr_deck;
        tmp->next = newclist;
    }
}

2.4 Freeing Memory (3 points)

void freedeck(deck* d);
void freedeck(deck* d){
    if(d != NULL)
    {
        clist* l = d->start;
        while(l!= NULL)
        {
            clist* temp = l->next;
            if(l->content != NULL)
                if(l->content->is_named)
                    free(l->content->data.name);
            free(l->content);
            free(l);
            l = temp;
        }
        free(d);   
    }
}

2.5 Removing a Card (3 points)

card* removecard(clist* l);
card* removecard(clist* l){
    deck* d = l->ptr_deck;
    if(d->nb_cards < 2)
    {
        fprintf(stderr, "wrong argument for card removal\n");
        exit(EXIT_FAILURE);
    }
    d->nb_cards--;
    clist* next = l->next;
    if(l->previous == NULL)
    {
        d->start = next;
        next->previous = NULL;
    }
    else
    {
        clist* prev = l->previous;
        prev->next = next;
        next->previous = prev;
    }
    card* res = l->content;
    free(l);
    return res;
}
        
    

2.6 Printing the Deck (3 points)

void fprintdeck (const char* filename, deck* d);
void fprintdeck (const char* filename, deck* d){
    FILE* f = fopen(filename, "w");
    if(f == NULL)
    {
        fprintf(stderr, "could not open file\n");
        exit(EXIT_FAILURE);
    }
    clist* l = d->start;
    while(l!=NULL)
    {
        if(l->content->is_named)
            fprintf(f, "%s\n", l->content->data.name);
        else
            fprintf(f, "%d %d\n",l->content->data.numeric.value, l->content->data.numeric.col);
        l = l->next;
    }
    fclose(f);
}

2.7 Dealing (Bonus)

clist** distribute(int nbplayers, deck* d);

Part 3: Tests (main Function)

The main function must be used to test all implemented functions (except distribute, which is a bonus).

Reminder: 0.5 points will be deducted for each untested function.

Example of test main provided in cards.c:

int main(void){
    card* c1 = createclassiccard(6,HEARTS);
    card* c2 = createclassiccard(2,SPADES);
    card* c3 = createclassiccard(3,CLUBS);
    card* c4 = createnamedcard("jocker");
    card* c5 = createnamedcard("rulescard");
    deck* d = createonecarddeck(c1);
    addcardbefore(d->start, c2);
    addcardbefore(d->start, c3);
    addcardbefore(d->start->next, c4);
    addcardbefore(d->start, c5);
    removecard(d->start);
    fprintdeck("foo1.txt",d);
    free(distribute(2,d));
    fprintdeck("foo2.txt",d);
    freedeck(d);


    return EXIT_SUCCESS;
}