Table of Contents

cgf2

doubly linked stack

Stack Struct

The following is a simple struct for a stack. It includes a pointer to a deck class, a pointer to the top card in a stack, and the size of a stack.

struct stack {
    deck* deckPtr;   // Pointer to the deck structure
    cardnode* top;   // Pointer to the top card in the stack
    int size;        // Size of the stack
};

Function to Create Stack

After Making your struct stack you can choose to make a function that you can call every time you make a new stack. You'll want to do this considering how many stacks you need for creating FreeCell.

//Creates a stack when called
stack* createStack(deck* d) {
    stack* newStack = (stack*)malloc(sizeof(stack));
    newStack->deckPtr = d;
    newStack->top = NULL;
    newStack->size = 0;
    return newStack;
}

LIFO/FILO

LIFO stands for last in, first out. In a LIFO system, the last item added to the structure is the first one to be removed. It's similar to a stack data structure, where you can think of items being stacked on top of each other, and the most recently added item is the first to be taken off the stack. FILO stands for first in, last out. In the FILO structure, the first item to get added to a list is the last one to get taken out. You can think of this as a queue where the item that has been in queue the longest is the one that gets taken out next.

size: bounded vs unbounded

top

push

The following is a function that grabs a card from the deck list and pushes it onto the specified stack.

void push(stack* s, cardnode* card) {
    card->next = s->top;  // Link the new card to the previous top
    s->top = card;        // Set the new card as the top
    s->size++;            // Increase the size of the stack
}

stack overflow

pop

This is an example of what your pop function might look like.

void pop(stack* s, Cardnode* card) {
    s->top = card->prev;
    card->next->prev = card->prev;
    card->prev->next = card->next;
    if(s->size!=0){
      s->size--;
    }
}

stack underflow

peek

card game: freecell

foundations

The foundations in Freecell are 4 piles of cards in the upper-right. You're only able to place cards in foundations in a specific order, and you cannot take them back out. The order in which cards are placed in foundations goes from Ace to King, and each foundation represents one of the four suits.

At the start of the game, all the foundations are empty. To win Freecell, all four foundations must be filled up with the entire deck of cards.

Foundation logic

To accomplish this functionality you can create the following bool function:

// Funtion for checking a valid placment of a card in the final destination
bool isMoveValid(stack* upperStack, cardnode* card)
{
     // If the stack is empty, only Ace can be placed
    if (upperStack->size == 0)
    {
        return card->value == 1;
    }
 
    cardnode* topCard = upperStack->top;
 
    // Checks if suits are the same and the card being added is one higher than the current card
    return (topCard->suit == card->suit) && (topCard->value + 1 == card->value);
}

This function checks if the current card in your hand can be placed onto one of the final stacks (NOTE: This also takes into account that the current card you have matches the suit you are trying to place it on)

Here is a possible example of calling the function:

// Checks if the card can be dropped with the isMoveValid funtion and drops if so
if (isMoveValid(currentStack, Hand->top))
{
    cardnode* topCard = pop(Hand);
    push(currentStack, topCard);
}

Note: hand→top Refers to the card you are moving.

storage

There are four Storage piles in the top-left of the board. Unlike the foundations, the each storage slot can only hold one card at a time.

Like the foundations, these start empty at the start of the game. The player may choose to take a card from any tableau and place it within a storage slot, and they can take it back at any time. If all the storage slots are filled, no more cards can be placed into the Storage piles.

tableau

The tableaus are the eight piles of cards below the storage piles and foundation piles.

At the start of the game, the tableaus are filled up with all 52 cards in a shuffled manner (It can be purely random, or placed strategically, it doesn't matter. The tableaus don't need to be a specific size.) The player is only able to interact with the top-most card of the tableau. The player has the option to move that card from one tableau into another tableau. However, a card can only be placed onto a tableau if:

  1. The card being placed has a value of exactly one less than the card it's being placed onto.
  2. The card being placed has a color opposite than the card it's being placed onto.

The strategy for the player is to try to line up tableaus into positions going from King to Ace. This makes it much easier to place the cards into the foundations.

Note: When coding the tableaus, a max size for each stack may be desirable so that cards do not go off-screen.

pile