/* =====================================================================================================================
* File - main.c
* ---------------------------------------------------------------------------------------------------------------------
* <https://forums.macrumors.com/threads/1072156/>
*
* Assumes C99
* Formatted for 120 characters screen width
* Uses 'tab' characters set as 4 space per 'tab'
*
* WARNING: Thrown togeether in about 45 minutes, including testing, and likely contains a few bugs!
*/
/* =====================================================================================================================
* ---------------------------------------------------------------------------------------------------------------------
* MARK: HEADERS
*/
//#define NDEBUG
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
/* =====================================================================================================================
* ---------------------------------------------------------------------------------------------------------------------
* MARK: -
* MARK: DEFINES
*/
#define kSUITES 4
#define kCARDS_PER_SUITE 13
#define kCARDS_PER_DECK ((kSUITES) * (kCARDS_PER_SUITE))
/* =====================================================================================================================
* ---------------------------------------------------------------------------------------------------------------------
* MARK: -
* MARK: TYPESDEFS
*/
typedef unsigned char card_t;
typedef card_t* card_ptr;
struct collection_t
{
card_t _v[kCARDS_PER_DECK];
card_ptr _end;
};
typedef struct collection_t collection_t;
typedef collection_t* collection_ptr;
/* =====================================================================================================================
* ---------------------------------------------------------------------------------------------------------------------
* MARK: -
* MARK: GLOBALS
*/
const char* szSuiteNames[kSUITES] =
{
"Clubs", "Diamonds", "Hearts", "Spades"
};
const char* szValueNames[kCARDS_PER_SUITE] =
{
"Ace", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King"
};
/* =====================================================================================================================
* ---------------------------------------------------------------------------------------------------------------------
* MARK: -
* MARK: CARD ROUTINES
*/
const char* suite_name(card_t card) { return szSuiteNames[card / kCARDS_PER_SUITE]; }
const char* value_name(card_t card) { return szValueNames[card % kCARDS_PER_SUITE]; }
/* =====================================================================================================================
* ---------------------------------------------------------------------------------------------------------------------
* MARK: -
* MARK: COLLECTION ROUTINES
*/
void collection_constructor(collection_ptr p)
{
assert(p);
(*p)._end = (*p)._v;
}
/* =====================================================================================================================
* ---------------------------------------------------------------------------------------------------------------------
*/
int collection_count(collection_ptr p)
{
assert(p);
return ((*p)._end - (*p)._v);
}
/* =====================================================================================================================
* ---------------------------------------------------------------------------------------------------------------------
*/
void collection_push(collection_ptr p, card_t card)
{
assert(p);
assert(((*p)._end - (*p)._v) < kCARDS_PER_DECK);
*((*p)._end++) = card;
}
/* =====================================================================================================================
* ---------------------------------------------------------------------------------------------------------------------
*/
card_t collection_pull(collection_ptr p)
{
assert(p);
assert((*p)._end != (*p)._v);
return *(--(*p)._end);
}
/* =====================================================================================================================
* ---------------------------------------------------------------------------------------------------------------------
*/
card_t collection_peek(collection_ptr p, int index)
{
assert(p);
assert((*p)._end != (*p)._v);
assert(index >= 0);
assert(index < ((*p)._end - (*p)._v));
return (*p)._v[index];
}
/* =====================================================================================================================
* ---------------------------------------------------------------------------------------------------------------------
*/
void collection_swap(collection_ptr p, int indexSrc, int indexDst)
{
assert(p);
assert((*p)._end != (*p)._v);
assert(indexSrc >= 0);
assert(indexDst >= 0);
assert(indexSrc < ((*p)._end - (*p)._v));
assert(indexDst < ((*p)._end - (*p)._v));
card_t card;
card = (*p)._v[indexSrc];
(*p)._v[indexSrc] = (*p)._v[indexDst];
(*p)._v[indexDst] = card;
}
#ifndef NDEBUG
/* =====================================================================================================================
* ---------------------------------------------------------------------------------------------------------------------
*/
void collection_display_card(card_t card)
{
printf("\n\t[%.2d] %s of %s", card, value_name(card), suite_name(card));
}
/* =====================================================================================================================
* ---------------------------------------------------------------------------------------------------------------------
*/
void collection_display(collection_ptr p)
{
for ( int i = 0; i < collection_count(p); i++ )
{
collection_display_card(collection_peek(p, i));
}
}
#else
#define collection_display_card(x)
#define collection_display(x)
#endif
// TODO: perhaps a 'collection_shuffle(collection_ptr)' would be useful?
/* =====================================================================================================================
* ---------------------------------------------------------------------------------------------------------------------
* MARK: -
*/
int main(int argc, const char* argv[])
{
collection_t deck;
collection_constructor(&deck);
// add cards to collection 'deck' ...
for ( int i = 0; i < kCARDS_PER_DECK; i++ )
{
collection_push(&deck, i);
}
// ... display collection 'deck' ...
printf("\n\nInitial deck ...");
collection_display(&deck);
// ... shuffle the collection 'deck' ...
for ( int i = 0; i < collection_count(&deck); i++ )
{
collection_swap(&deck, i, (rand() % kCARDS_PER_DECK));
}
// ... display shuffled collection 'deck' ...
printf("\n\nShuffled deck ...");
collection_display(&deck);
// ... draw cards from the collection 'deck' and add to the collections 'hand1' and 'hand2' ...
collection_t hand1;
collection_constructor(&hand1);
collection_t hand2;
collection_constructor(&hand2);
while ( collection_count(&deck) )
{
collection_push(&hand1, collection_pull(&deck));
collection_push(&hand2, collection_pull(&deck));
}
// ... draw cards from the collection 'hand1' till collection is empty ...
// ... display the card ...
printf("\n\nHand1 ...");
while ( collection_count(&hand1) )
{
collection_display_card(collection_pull(&hand1));
}
// ... draw cards from the collection 'hand2' till collection is empty ...
// ... display the card ...
printf("\n\nHand2 ...");
while ( collection_count(&hand2) )
{
collection_display_card(collection_pull(&hand2));
}
return EXIT_SUCCESS;
}