• Log InLog In
  • Register
Liquid`
Team Liquid Liquipedia
EST 09:05
CET 15:05
KST 23:05
  • Home
  • Forum
  • Calendar
  • Streams
  • Liquipedia
  • Features
  • Store
  • EPT
  • TL+
  • StarCraft 2
  • Brood War
  • Smash
  • Heroes
  • Counter-Strike
  • Overwatch
  • Liquibet
  • Fantasy StarCraft
  • TLPD
  • StarCraft 2
  • Brood War
  • Blogs
Forum Sidebar
Events/Features
News
Featured News
RSL Revival - 2025 Season Finals Preview8RSL Season 3 - Playoffs Preview0RSL Season 3 - RO16 Groups C & D Preview0RSL Season 3 - RO16 Groups A & B Preview2TL.net Map Contest #21: Winners12
Community News
ComeBackTV's documentary on Byun's Career !1Weekly Cups (Dec 8-14): MaxPax, Clem, Cure win1Weekly Cups (Dec 1-7): Clem doubles, Solar gets over the hump1Weekly Cups (Nov 24-30): MaxPax, Clem, herO win2BGE Stara Zagora 2026 announced15
StarCraft 2
General
ComeBackTV's documentary on Byun's Career ! Weekly Cups (Dec 8-14): MaxPax, Clem, Cure win Did they add GM to 2v2? RSL Revival - 2025 Season Finals Preview Weekly Cups (Dec 1-7): Clem doubles, Solar gets over the hump
Tourneys
Sparkling Tuna Cup - Weekly Open Tournament $5,000+ WardiTV 2025 Championship StarCraft2.fi 15th Anniversary Cup RSL Offline Finals Info - Dec 13 and 14! Tenacious Turtle Tussle
Strategy
Custom Maps
Map Editor closed ?
External Content
Mutation # 504 Retribution Mutation # 503 Fowl Play Mutation # 502 Negative Reinforcement Mutation # 501 Price of Progress
Brood War
General
FlaSh on: Biggest Problem With SnOw's Playstyle How Rain Became ProGamer in Just 3 Months [BSL21] RO8 Bracket & Prediction Contest BGH Auto Balance -> http://bghmmr.eu/ BW General Discussion
Tourneys
[Megathread] Daily Proleagues [BSL21] RO8 - Day 2 - Sunday 21:00 CET [ASL20] Grand Finals [BSL21] RO8 - Day 1 - Saturday 21:00 CET
Strategy
Current Meta Simple Questions, Simple Answers Game Theory for Starcraft Fighting Spirit mining rates
Other Games
General Games
Stormgate/Frost Giant Megathread Path of Exile Dawn of War IV ZeroSpace Megathread The 2048 Game
Dota 2
Official 'what is Dota anymore' discussion
League of Legends
Heroes of the Storm
Simple Questions, Simple Answers Heroes of the Storm 2.0
Hearthstone
Deck construction bug Heroes of StarCraft mini-set
TL Mafia
Mafia Game Mode Feedback/Ideas Survivor II: The Amazon Sengoku Mafia TL Mafia Community Thread
Community
General
US Politics Mega-thread Russo-Ukrainian War Thread Things Aren’t Peaceful in Palestine YouTube Thread European Politico-economics QA Mega-thread
Fan Clubs
White-Ra Fan Club
Media & Entertainment
Anime Discussion Thread [Manga] One Piece Movie Discussion!
Sports
2024 - 2026 Football Thread Formula 1 Discussion
World Cup 2022
Tech Support
Employee Retention in Behavioral Health: Building Computer Build, Upgrade & Buying Resource Thread
TL Community
TL+ Announced Where to ask questions and add stream?
Blogs
How Sleep Deprivation Affect…
TrAiDoS
I decided to write a webnov…
DjKniteX
James Bond movies ranking - pa…
Topin
Thanks for the RSL
Hildegard
Customize Sidebar...

Website Feedback

Closed Threads



Active: 779 users

FreeCell written in C

Blogs > Zephirdd
Post a Reply
Barbiero
Profile Blog Joined September 2010
Brazil5259 Posts
April 21 2013 01:05 GMT
#1
Hi, I am Zephirdd and I am a Computer Science graduate.

I received an assignment to create the game FreeCell in either C or Pascal. We are not allowed to use any graphical interface other than the console, and we MUST use pointer stacks to organize our cards. These are the conditions of our assignment.

And I had a week to do it.


Now, a little background. I had some experience in programming with C when I was very young, but ever since I got into the university, all I could use was Pascal. And I HATE Pascal.
Furthermore, I haven't programmed in forever. And I had a week to write the whole freaking game. Well fuck, I thought.


Turns out three half-nights were enough. Who'd tell, FreeCell is a fairly simple game!
When I searched the interwebs for this specific project - FreeCell in C - in order to blatantly stealresearch the method, I couldn't find any satisfactory one. I found a guy who spammed every single programming forum asking for it though lol.

So, for the programming enthusiasts, I decided to post this. If you are a beginner, this is a fairly simple project which you can look on. If you are an advanced programmer, well... this is useless for you, but you can get some good laughter.

Because I need to send the source code to my professor, all of the comments are in Portuguese, but I believe the functions are enough

The project was made via Code::Blocks, compiled with the mingw that comes with it. It's a great IDE for beginners IMO.

Without further ado, here you go!

main.c
+ Show Spoiler +
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <math.h>
#include <time.h>
#include "main.h"

/////////////////////////////////
// Cartas são enumeradas de 0 a 51
// 0 = A Copas
// 51 = K Espadas
// 0-12 = copas
// 13-25 = ouros
// 26-38 = paus
// 39-51 = espadas

// (valor+1)/13 = categoria(copas/espadas/ouros/paus); 0=C 1=O 2=P 3=E
// (valor+1)%13 = número(A,2,3,4,5,6,7,8,9,10,J,Q,K)
/////////////////////////////////

// void cardToStr(Item *card, char *c)
// transforma *c na carta
void cardToStr(Item *card, char *c)
{
if(card == NULL)
{
strcpy(c, " ");
return;
}

int category = getCardNipe(card);
int value = getCardNumber(card);
c[0] = ' '; c[1] = ' '; c[2] = ' ';
switch(value)
{
case 0: c[1] = 'A'; break; //A
case 9: c[0] = '1'; c[1] = '0'; break; //10
case 10: c[1] = 'J'; break; //J
case 11: c[1] = 'Q'; break; //Q
case 12: c[1] = 'K'; break; //K
default: c[1] = '1'+value; break; //Isto só é possível pois os casos para números > 9 já foram cobertos acima

}

switch(category)
{
case 0: c[2] = '\3'; break;
case 1: c[2] = '\4'; break;
case 2: c[2] = '\5'; break;
case 3: c[2] = '\6'; break;
default: c[2] = ' '; break;
}
}

void shuffleArray(int *arr, size_t n)
{
if(n>1)
{
size_t i, j;
for(i = 0; i < n-1; i++)
{
j = i + (rand() / (RAND_MAX / (n - i) + 1));
int t = arr[j];
arr[j] = arr[i];
arr[i] = t;
}
}
}

void initializeCards()
{
srand(time(NULL)); //modifica a base do gerador aleatório para não sair a mesma combinação para toda execução
int ar[52];
size_t i;
//Baralho padrão, não embaralhado
for(i=0; i<52; i++)
{
ar[i] = i;
}

shuffleArray(ar, 52); // Embaralhado


for(i=0; i<=3; i++)
{
top_slots[i] = createPile();
base_slots[i] = createPile();
mid_slots[i] = createPile();
mid_slots[i+4] = createPile(); //Não precisa de 2 loops
}

//Colocar as cartas nos mid_slots
for(i=0; i<52; i++){
addNewItemPile(mid_slots[i%8], ar[i]);
}

//Inicializar status do jogo
gameStatus = GAME_STATUS_START;
}

void writeCards()
{
if(!mid_slots[0])
return;

int i;
Item* item;
char *c = malloc(sizeof(char[3]));

for(i=0; i<8; i++)
{
if(mid_slots[i])
{
item = mid_slots[i]->start;
while(item->next != NULL)
{
cardToStr(item, c);
printf("%s ", c);
item = item->next;
}
printf("\n");
}
}
free(c);
}

//int moveCardToPile(Pile* from, Pile* to)
//Move a carta do topo da pilha from para a pilha to
//retorna -1 se nao conseguir, 0 se conseguir
int moveCardToPile(Pile* from, Pile* to)
{
if(from == NULL || to == NULL)
return -1;

Item *prev = removeTopItemPile(from);
if(prev == NULL)
return -1;

return addItemPile(to, prev);
}

int moveCardToBase(Pile *from)
{
if(from == NULL)
return -1;

Item *prev = removeTopItemPile(from);
if(prev == NULL)
return -1;

return addItemPile(base_slots[getCardNipe(prev)], prev);
}


//int getCardNipe
//retorna 0 para copas, 1 para ouros, 2 para paus, 3 para espadas, -1 para erro
int getCardNipe(Item* card)
{
if(card != NULL)
return (int)(card->value / 13);
return -1;
}

//int getCardNumber
//retorna o número da carta, de 0 a 12
//0=A, 1=2, 2=3, etc...
int getCardNumber(Item* card)
{
if(card != NULL)
return (int)(card->value % 13);
return -1;
}

//int canMove(Pile *from, Pile *to)
//retorna 1 se é possível mexer a carta do topo de from para to
//retorna 0 se não
//Toma como base apenas as regras do jogo para as pilhas do meio
//Não leva em consideração as pilhas do topo direito, que têm funcionamento diferente.
int canMove(Pile *from, Pile *to)
{
if(from == NULL || to == NULL)
return 0;

if(from->start == NULL)
return 0;

Item *toMove = from->start;
Item *toReceive = to->start;
if(toReceive == NULL)
return 1; //Sem carta = pode mecher qualquer carta

//verificar se o número é válido
if(getCardNumber(toMove) != getCardNumber(toReceive)-1)
return 0; //só pode mexer uma carta 1 numero menor do que a carta alvo, ex 2 para 3

//verificar se o nipe é válido
//0 não pode combinar com 1, 2 não pode combinar com 3.
//A XOR C, pois se o bit da esquerda é diferente, torna o movimento válido
if((getCardNipe(toMove) ^ getCardNipe(toReceive)) > 1) //>1 significa 10 ou 11 vs 00 ou 01
return 1;

return 0;
}

//int canMoveToBase(Pile *from)
//retorna 1 de a carta pode ser posta em uma pilha base
//retorna 0 se não
int canMoveToBase(Pile *from)
{
if(from == NULL || base_slots[0] == NULL)
return -1;

Item *toMove = from->start;
if(toMove == NULL)
return -1;


//Verifica na pilha do nipe da carta
Item *toReceive = base_slots[getCardNipe(toMove)]->start;
if(toReceive != NULL)
{
if(getCardNumber(toReceive) == getCardNumber(toMove)-1)
return 1;
}
else if(getCardNumber(toMove) == 0)
return 1;

//Verifica se a carta na pilha é antecessora a esta


return 0;
}

// Função main() executa o programa.
int main()
{
initializeCards();
drawBoard();
//writeCards();
return 0;
}

main.h
+ Show Spoiler +


#ifndef MAIN_H_INCLUDED
#define MAIN_H_INCLUDED

#include "pilha.h"

//Slot é a casa onde as cartas são postas
//Em FreeCell, você tem 8 slots vazios na primeira linha(sendo 4 "bases") e 8 slots com cartas

Pile *top_slots[4]; //Slots da esquerda de cima, inicialmente vazios
Pile *base_slots[4]; //Slots base, para onde as cartas vão. Talvez não precise utilizar Pile aqui?
Pile *mid_slots[8]; //Slots do meio. No inicio do jogo, têm as cartas distribuídas neles


//Funções de main.c
void cardToStr(Item *card, char *c);
void shuffleArray(int *arr, size_t n);
void initializeCards();
int moveCardToPile(Pile *from, Pile *to);
int moveCardToBase(Pile *from);
int getCardNipe(Item *card);
int getCardNumber(Item *card);
int canMove(Pile *from, Pile *to);
int canMoveToBase(Pile *from);



#define NOMINMAX 1
//Usarei minha própria função max
#define max(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; })


void drawCard(Item *card);
void drawBoard();
void drawMiddle();
void drawRequestHandle();
void receiveUserInput();
void checkGameStatus();


int gameStatus; //estado do jogo
#define GAME_STATUS_START 0
#define GAME_STATUS_CHOSECARD 1
#define GAME_STATUS_CHOSETARGET 2
#define GAME_STATUS_DEFEAT 3
#define GAME_STATUS_VICTORY 4

Pile *selectedSlot; //pilha selecionada para mover

#endif // MAIN_H_INCLUDED


pilha.c
+ Show Spoiler +
#include "pilha.h"

// Pile* createPile();
// Retorna uma NOVA pilha inicializada
// Retorna NULL caso não consiga criar uma nova pilha
Pile* createPile()
{
Pile* newPile = (Pile*)malloc(sizeof(Pile));
if(newPile == NULL) //se não puder achar memória no sistema
return NULL;

newPile->start = NULL;
newPile->length = 0;
return newPile;
}


// int addItemPile(Pile* pile, int value)
// Cria e adiciona um novo item à pilha, com valor value
// Retorna -1 se não for bem sucedido, 0 se for bem sucedido
int addNewItemPile(Pile* pile, int value)
{
Item* newItem;
if(pile == NULL)
return -1;

newItem = (Item*)malloc(sizeof(Item));
if(newItem == NULL)
return -1;

newItem->value = value;
newItem->next = pile->start;
pile->start = newItem;
pile->length++;
return 0;
}

int addItemPile(Pile* pile, Item* item)
{
if(item == NULL)
return -1;

if(item->next != NULL) //se o next != NULL, ele está em alguma pilha
return -1;

item->next = pile->start;
pile->start = item;
pile->length++;
return 0;
}

// Item* removeTopItemPile(Pile* pile)
// remove o primeiro item da pilha
// retorna NULL se houver algum erro, ou o item removido para uso futuro
// O "next" do item removido vira NULL, pois ele é removido da pilha.
// Nota: o item NÃO É DELETADO DA MEMÓRIA.
Item* removeTopItemPile(Pile* pile)
{
Item* removedItem;
if(pile == NULL || pile->length <= 0)
return NULL;

removedItem = pile->start;
pile->start = removedItem->next;
pile->length--;
removedItem->next = NULL;
return removedItem;
}

// int deleteItem(Item* item)
// deleta e remove o item da memória
// retorna -1 se o next não for NULL, pois siginifica que ainda está em uma pilha
// retorna 0 se for bem sucedido
int deleteItem(Item* item)
{
if(item == NULL || item->next != NULL)
return -1;

free(item);
return 0;
}

// int deletePile(Pile* pile)
// deleta a pilha e remove da memória
// remove e deleta qualquer item que esteja na pilha
// retorna -1 se a pilha não existir
int deletePile(Pile* pile)
{
Item* item;
if(pile == NULL)
return -1;

while(pile->length > 0)
{
item = removeTopItemPile(pile); //reduz o valor da pilha automaticamente
if(item != NULL)
deleteItem(item);
}

free(pile);
return 0;
}

//Item* getPreviousItemOnPile(Item *item, Pile *pile)
// retorna o item anterior ao item requerido na pilha
// retorna o próprio item se ele for o topo da pilha
// retorna NULL se não for possível, ou se o item não estiver na pilha
Item* getPreviousItemOnPile(Item *item, Pile *pile)
{
if(item == NULL || pile == NULL)
return NULL;

Item* Q = pile->start;
if(Q == NULL) return NULL;
if(Q == item) return item;

while(Q->next != NULL)
{
if(Q->next == item) return Q;

Q = Q->next;
}

return NULL;
}


pilha.h
+ Show Spoiler +
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//////////////////////////Funcoes de Pilha(stack)//////////////////////
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////


#ifndef PILHA_H_INCLUDED
#define PILHA_H_INCLUDED

#include <stdlib.h>

// Definir Pilha(Pile) e suas funções para o uso no jogo
// Usar nomes genéricos para usos futuros

typedef struct ItemList
{
int value; //No futuro, achar um método de transformar este tipo em algo mais dinâmico
struct ItemList *next;
}Item;

typedef struct PileStructure
{
Item *start;
int length; // length ao inves de size, pois size ja é definido para outras coisas
}Pile;


// Pile* createPile();
// Retorna uma NOVA pilha inicializada
// Retorna NULL caso não consiga criar uma nova pilha
Pile* createPile();


// int addItemPile(Pile* pile, int value)
// Cria e adiciona um novo item à pilha, com valor value
// Retorna -1 se não for bem sucedido, 0 se for bem sucedido
int addNewItemPile(Pile* pile, int value);
int addItemPile(Pile* pile, Item* item);

// Item* removeTopItemPile(Pile* pile)
// remove o primeiro item da pilha
// retorna NULL se houver algum erro, ou o item removido para uso futuro
// O "next" do item removido vira NULL, pois ele é removido da pilha.
// Nota: o item NÃO É DELETADO DA MEMÓRIA.
Item* removeTopItemPile(Pile* pile);

// int deleteItem(Item* item)
// deleta e remove o item da memória
// retorna -1 se o next não for NULL, pois siginifica que ainda está em uma pilha
// retorna 0 se for bem sucedido
int deleteItem(Item* item);

// int deletePile(Pile* pile)
// deleta a pilha e remove da memória
// remove e deleta qualquer item que esteja na pilha
// retorna -1 se a pilha não existir
int deletePile(Pile* pile);

//Item* getPreviousItemOnPile(Item *item, Pile *pile)
// retorna o item anterior ao item requerido na pilha
// retorna o próprio item se ele for o topo da pilha
// retorna NULL se não for possível, ou se o item não estiver na pilha
Item* getPreviousItemOnPile(Item *item, Pile *pile);

#endif // PILHA_H_INCLUDED

ui.c
+ Show Spoiler +
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include "main.h"
#include "pilha.h"

void drawCard(Item *card)
{
if(card != NULL)
{
char *c = malloc(sizeof(char[3]));
cardToStr(card, c);
printf("{%s} ", c);
free(c);
}
else
printf("{ } ");
}


void drawBoard()
{
system("cls");
int i;

if(top_slots[0] == NULL)
return;
/*

#1 #2 #3 #4 C O P E
{ } { } { } { } | { } { } { } { }
-------------------------------------------------
{ } { } { } { } { } { } { } { }
{ } { } { } { } { } { } { } { }
{ } { } { } { } { } { } { } { }
{ } { } { } { } { } { } { } { }
{ } { } { } { } { } { } { } { }
{ } { } { } { } { } { } { } { }
{ } { } { } { } { } { } { } { }
{ } { } { } { } { } { } { } { }
{ } { } { } { } { } { } { } { }
{ } { } { } { } { } { } { } { }
a b c d e f g h

In which column is the card you want to take? _

(depois de selecionar a carta)
To where you want to send this card?
Valid options: 1,2,3,4,a,b,c,d,e,f,g,h,BASE
Enter with the target: _


// NOTA: opções possíveis também são o, out, base, nipe


*/

printf(" #1 #2 #3 #4 \3 \4 \5 \6 \n");
for(i=0;i<4;i++)
drawCard(top_slots[i]->start);

printf("| ");

for(i=0;i<4;i++)
drawCard(base_slots[i]->start);
//base e topo escritas

printf("\n");
printf("------------------------------------------------- \n");

//escrever o meio
drawMiddle();

printf("\n\n");
//Perguntas
drawRequestHandle();

//Solicitar o usuário a executar um comando
if(gameStatus != GAME_STATUS_DEFEAT && gameStatus != GAME_STATUS_VICTORY)
receiveUserInput();
}



void drawMiddle()
{
//Função separada para organizar
//Para o jogo, é mais fácil manter pilhas de baixo para cima(pelo display)
//Porém para escrever, é mais fácil utilizar pilhas de cima para baixo

//Então vou criar novas pilhas temporárias que são cópias das globais
//E utilizar estas para imprimir
if(mid_slots[0] == NULL)
return;

Pile *tempPile[8];
Item *tempItem;
Item *tmpVector[8];
int i, j, max_length;
max_length = -1; //Inicialização necessária para garantir o uso

for(i=0;i<8;i++)
{
//Terei de criar NOVAS cartas, pois as originais precisam manter seus atributos
//Lembrar de deletar tudo ao fim da função
tempPile[i] = createPile();
tempItem = mid_slots[i]->start;
while(tempItem != NULL)
{
addNewItemPile(tempPile[i], tempItem->value);
tempItem = tempItem->next;
}

max_length = max(max_length, tempPile[i]->length); //será usado mais tarde

}

//Desenhar
for(i = 0; i < max_length; i++)
{
for(j = 0; j < 8; j++)
{
if(i == 0)
tmpVector[j] = tempPile[j]->start;
else if(tmpVector[j] != NULL){
tmpVector[j] = tmpVector[j]->next;
}

drawCard(tmpVector[j]);
if(j == 3)
printf(" "); //Alinhar as cartas
}
printf("\n");
}


printf(" a b c d e f g h \n");

//deletar pilas temporárias
for(i= 0; i < 8; i++)
deletePile(tempPile[i]);
//funçoes em pile.h já lidam com os items criados
}

void drawRequestHandle()
{
//Função para escrever as perguntas
switch(gameStatus)
{
case GAME_STATUS_START:
printf("Welcome to FreeCell! Above you will see your cards!\n");
case GAME_STATUS_CHOSECARD:
printf("Please chose which card you want to move!\n");
printf("Valid options: a, b, c, d, e, f, g, h, 1, 2, 3, 4\n");
break;
case GAME_STATUS_CHOSETARGET:
printf("Please chose to where you want to move ");
drawCard(selectedSlot->start);
printf("\nValid options: a, b, c, d, e, f, g, h, 1, 2, 3, 4, base\n");
break;
case GAME_STATUS_DEFEAT:
printf("No more possible moves. Game over!");
break;
case GAME_STATUS_VICTORY:
printf("Congratulations, you won!");
break;
}
}

void receiveUserInput()
{
char *c = malloc(sizeof(char[5]));
int i;
scanf("%5s", c);
//verificar estado do jogo
if(gameStatus == GAME_STATUS_START || gameStatus == GAME_STATUS_CHOSECARD)
{
//if(c[0] == 'a') i = 0;
//if
if(c[0] >= 'a' && c[0] <= 'h')
{
i = (int)(c[0] - 'a'); //a=0, b=1, c=2, d=3, e=4, f=5, g=6, h=7
selectedSlot = mid_slots[i];
}
else if(c[0] >= '1' && c[0] <= '4')
{
i = (int)(c[0] - '1');
selectedSlot = top_slots[i];
}
else{
printf("Invalid selection! \nValid options are a,b,c,d,e,f,g,h,1,2,3,4!\n");
free(c);
receiveUserInput();
return;
}


if(selectedSlot->start == NULL)
{
printf("This pile has no cards! Please select another slot.\n");
free(c);
receiveUserInput();
return;
}

gameStatus = GAME_STATUS_CHOSETARGET;
}
else if(gameStatus == GAME_STATUS_CHOSETARGET)
{
Pile *targetSlot;
if(strcasecmp(c, "base") == 0)
{
strcpy(c, " ");
free(c);
if(canMoveToBase(selectedSlot) == 1)
{
moveCardToBase(selectedSlot);
checkGameStatus();
selectedSlot = NULL;
drawBoard();
return;
}
else
{
selectedSlot = NULL;
printf("Invalid move! Please select another card.\n");
gameStatus = GAME_STATUS_CHOSECARD;
receiveUserInput();
return;
}

}
else if(c[0] >= 'a' && c[0] <= 'h')
{
i = (int)(c[0] - 'a'); //a=0, b=1, c=2, d=3, e=4, f=5, g=6, h=7
targetSlot = mid_slots[i];
}
else if(c[0] >= '1' && c[0] <= '4')
{
i = (int)(c[0] - '1');
targetSlot = top_slots[i];
//top_slots may only receive one card at a time
if(targetSlot->length > 0)
{
printf("Invalid move! Please select another card to move.\n");
free(c);
selectedSlot = NULL;
gameStatus = GAME_STATUS_CHOSECARD;
receiveUserInput();
return;
}
}
else{
printf("Invalid selection! \nValid options are a,b,c,d,e,f,g,h,1,2,3,4,base!");
free(c);
receiveUserInput();
return;
}

if(canMove(selectedSlot, targetSlot) == 1)
{
moveCardToPile(selectedSlot, targetSlot);
checkGameStatus();
}
else{
printf("Invalid move! Please select another card to move.\n");
free(c);
selectedSlot = NULL;
gameStatus = GAME_STATUS_CHOSECARD;
receiveUserInput();
return;
}
}

free(c);
drawBoard();
}

void checkGameStatus()
{
//Ler os slots e verificar se o jogo acabou, e determinar o status do jogo

//se o length dos top_slots for 13, eles estão cheios e o jogo acabou em vitória
if(top_slots[0]->length == 13 && top_slots[1]->length == 13 && top_slots[2]->length == 13 && top_slots[4]->length == 13){
gameStatus = GAME_STATUS_VICTORY;
return;
}

//Se nenhum movimento for possível, o jogo resulta em derrota
Pile *a, *b;
int j;
int isDefeat = 1; //Assume que é derrota inicialmente; se achar um movimento válido, vira vitória

a = mid_slots[0];
for(j=0; j<8; j++)
{
b = mid_slots[j];
if(canMove(a, b) == 1 || canMove(b, a) == 1){
isDefeat = 0;
break; //Já foi determinado que não é derrota
}
if(j<4)
{
b = top_slots[j];
if(top_slots[j]->length == 0)
{
isDefeat = 0;
break;
}
}
}

if(isDefeat == 1)
gameStatus = GAME_STATUS_DEFEAT;
else
gameStatus = GAME_STATUS_CHOSECARD;

}



This was the very first full project I've done by myself. I feel proud :3

One thing I wanted to make was an actual cursor to select the cards and move them, but I figured it would be far too much work for something like this. From what I've researched, cursors are actually really complicated o-o'

Also you may notice that I never created an "exit" function and deleted the piles and items created in this. Ctrl+C seems to do the work fine, and I'm lazy lol.

I could upload the built .exe file, but it would look shady. So you can compile the above code instead :D

Thanks for reading~

*****
♥ The world needs more hearts! ♥
Birdie
Profile Blog Joined August 2007
New Zealand4438 Posts
April 21 2013 03:34 GMT
#2
Congratz, I'm a year 1 computer science student so I'll check out the code later this week if I remember and see what I can learn. I've been lazy and haven't learned pointers yet so maybe I'll use this as an example of how they can be used
Red classic | A butterfly dreamed he was Zhuangzi | 4.5k, heading to 5k as support!
docvoc
Profile Blog Joined July 2011
United States5491 Posts
April 21 2013 03:44 GMT
#3
I don't get this at all, but it looks very impressive O.o, this is awesome dude, how do I run this code?
User was warned for too many mimes.
rabidch
Profile Joined January 2010
United States20289 Posts
April 21 2013 03:54 GMT
#4
On April 21 2013 12:44 docvoc wrote:
I don't get this at all, but it looks very impressive O.o, this is awesome dude, how do I run this code?

compile the program with a C compiler and then run it
LiquidDota StaffOnly a true king can play the King.
IMlemon
Profile Blog Joined May 2008
Lithuania296 Posts
April 21 2013 10:25 GMT
#5
Please dont ever write source code in a non-english language if you want someone to understand it.
My future's so bright, I gotta wear shades.
LML
Profile Blog Joined March 2007
Germany1774 Posts
Last Edited: 2013-04-21 14:42:28
April 21 2013 14:41 GMT
#6
what's the problem with english comments just because you study in a non-english speaking country?
I use english comments in my programs for university, most professors even post their stuff with english comments, it's really not that uncommon

on a different note, why did you keep all the functions in the main.c instead of like a functions.h?
Wouldn't that be way cleaner to look at, when looking at the main?
LML
Barbiero
Profile Blog Joined September 2010
Brazil5259 Posts
April 21 2013 17:19 GMT
#7
On April 21 2013 23:41 LML wrote:
what's the problem with english comments just because you study in a non-english speaking country?
I use english comments in my programs for university, most professors even post their stuff with english comments, it's really not that uncommon

on a different note, why did you keep all the functions in the main.c instead of like a functions.h?
Wouldn't that be way cleaner to look at, when looking at the main?


My professor reads the code, and he doesnt like english

If you mean the main.h having all the functions, I dont really see an issue as its only a naming thing. But yeah, for consistency renaming it to functions.h would be better I guess

If you mean main.c, I decided to keep game rules and game interpreting functions on main.c and user related dunctions(draw/read) on ui.c . Leaving main.c empty just with the main function would look silly lol
♥ The world needs more hearts! ♥
Riccardo
Profile Joined May 2020
Italy1 Post
May 19 2020 10:48 GMT
#8
Hi, I have received an assignment similar to yours at my university. I tried to use your code initially to understand how it worked but unfortunately after building and starting it, the output is this in image.

Could you help me understand?
Thank you very much.

[image loading]
catplanetcatplanet
Profile Blog Joined March 2012
3830 Posts
Last Edited: 2020-05-20 03:22:53
May 20 2020 03:22 GMT
#9
Hi Riccardo. I'm afraid the guy you necro'd hasn't been active here for more than 4 years. Speaking from experience, copying an entire codebase you find online and then asking why it doesn't run out of the box (without even googling your error to see if there's a very simple solution) doesn't tend to be the most productive approach. Try solving the assignment on your own, see what you get hung up on, and consult with your peers and professors. That's how learning at university works!
I think it's finally time to admit it might not be the year of Pet
Urth
Profile Blog Joined November 2007
United States1250 Posts
May 29 2020 16:14 GMT
#10
Lol nice necro
BY.HERO FIGHTING!!!!
decembre
Profile Joined January 2024
1 Post
January 11 2024 15:21 GMT
#11
hi I read your code and I want tothank you but I have a problem that I didn't understand it
jacksmith1221
Profile Joined January 2024
1 Post
January 12 2024 10:19 GMT
#12
QuickBooks Error H505 is a common issue that occurs when a user tries to access a company file that is located on another computer, and QuickBooks cannot establish a connection with the server. This error is part of the H series errors in QuickBooks, which are related to hosting issues.
Here is a step-by-step solution to fix QuickBooks Error H505:
Step 1: Check Hosting Settings
Open QuickBooks on all computers.
Go to the 'File' menu and select 'Utilities.'
Verify that the host computer is set as the host in multi-user mode.
If not, choose 'Host Multi-User Access.'
Step 2: Update QuickBooks
Ensure you are using the latest version of QuickBooks.
Go to the 'Help' menu and select 'Update QuickBooks Desktop.'
Choose the 'Update Now' tab and click 'Get Updates.'
Restart QuickBooks after the update is complete.
Please log in or register to reply.
Live Events Refresh
WardiTV 2025
12:00
Playoffs
Spirit vs RogueLIVE!
Scarlett vs Reynor
TBD vs Clem
uThermal vs Shameless
WardiTV990
ComeBackTV 488
TaKeTV 244
IndyStarCraft 129
Rex129
LiquipediaDiscussion
Sparkling Tuna Cup
10:00
Weekly #115
Percival vs KrystianerLIVE!
CranKy Ducklings104
LiquipediaDiscussion
[ Submit Event ]
Live Streams
Refresh
StarCraft 2
Lowko346
Rex 129
IndyStarCraft 129
BRAT_OK 82
ProTech11
StarCraft: Brood War
Sea 3828
Rain 3286
Bisu 1625
Jaedong 960
Larva 953
GuemChi 628
Soma 618
BeSt 396
actioN 379
Mini 353
[ Show more ]
Hyuk 338
EffOrt 306
Stork 290
Light 263
firebathero 187
Snow 163
Rush 155
hero 132
Hyun 95
Sea.KH 70
Killer 60
JYJ 56
sorry 38
Aegong 32
Terrorterran 29
yabsab 25
Mind 25
scan(afreeca) 23
Mong 18
GoRush 14
Movie 11
Bale 9
Oya187 6
Dota 2
Gorgc3584
qojqva2133
BananaSlamJamma409
420jenkins303
XcaliburYe196
capcasts62
syndereN38
Counter-Strike
olofmeister2089
x6flipin642
byalli362
allub259
markeloff68
Other Games
B2W.Neo1915
Pyrionflax318
Fuzer 311
hiko278
Hui .264
RotterdaM124
ArmadaUGS59
QueenE55
Trikslyr31
Chillindude23
Organizations
StarCraft: Brood War
UltimateBattle 1511
lovetv 6
StarCraft 2
Blizzard YouTube
StarCraft: Brood War
BSLTrovo
sctven
[ Show 14 non-featured ]
StarCraft 2
• AfreecaTV YouTube
• intothetv
• Kozan
• IndyKCrew
• LaughNgamezSOOP
• Migwel
• sooper7s
StarCraft: Brood War
• HerbMon 20
• BSLYoutube
• STPLYoutube
• ZZZeroYoutube
Dota 2
• WagamamaTV721
League of Legends
• Jankos2824
• TFBlade554
Upcoming Events
PiGosaur Cup
10h 55m
WardiTV 2025
21h 55m
MaNa vs Gerald
TBD vs MaxPax
ByuN vs TBD
TBD vs ShoWTimE
OSC
1d
YoungYakov vs Mixu
ForJumy vs TBD
Percival vs TBD
Shameless vs TBD
The PondCast
1d 19h
WardiTV 2025
1d 22h
Cure vs Creator
TBD vs Solar
WardiTV 2025
2 days
OSC
2 days
CranKy Ducklings
3 days
SC Evo League
3 days
Ladder Legends
4 days
[ Show More ]
BSL 21
4 days
Sparkling Tuna Cup
4 days
Ladder Legends
5 days
BSL 21
5 days
Replay Cast
5 days
Monday Night Weeklies
6 days
Liquipedia Results

Completed

Acropolis #4 - TS3
RSL Offline Finals
Kuram Kup

Ongoing

C-Race Season 1
IPSL Winter 2025-26
KCM Race Survival 2025 Season 4
YSL S2
BSL Season 21
Slon Tour Season 2
WardiTV 2025
META Madness #9
SL Budapest Major 2025
ESL Impact League Season 8
BLAST Rivals Fall 2025
IEM Chengdu 2025
PGL Masters Bucharest 2025
Thunderpick World Champ.
CS Asia Championships 2025
ESL Pro League S22

Upcoming

CSL 2025 WINTER (S19)
BSL 21 Non-Korean Championship
Acropolis #4
IPSL Spring 2026
Bellum Gens Elite Stara Zagora 2026
HSC XXVIII
Big Gabe Cup #3
ESL Pro League Season 23
PGL Cluj-Napoca 2026
IEM Kraków 2026
BLAST Bounty Winter 2026
BLAST Bounty Winter Qual
eXTREMESLAND 2025
TLPD

1. ByuN
2. TY
3. Dark
4. Solar
5. Stats
6. Nerchio
7. sOs
8. soO
9. INnoVation
10. Elazer
1. Rain
2. Flash
3. EffOrt
4. Last
5. Bisu
6. Soulkey
7. Mini
8. Sharp
Sidebar Settings...

Advertising | Privacy Policy | Terms Of Use | Contact Us

Original banner artwork: Jim Warren
The contents of this webpage are copyright © 2025 TLnet. All Rights Reserved.