Skip to content

Instantly share code, notes, and snippets.

@assyrianic
Last active July 9, 2024 05:19
Show Gist options
  • Save assyrianic/60a5be1259d811a4b1676a3999b3527a to your computer and use it in GitHub Desktop.
Save assyrianic/60a5be1259d811a4b1676a3999b3527a to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <inttypes.h>
#include <time.h>
#include <stdbool.h>
#include <stdlib.h>
enum CardSuit {
SUIT_HEART,
SUIT_DIAMOND,
SUIT_SPADE,
SUIT_CLUB,
MAX_SUITS,
};
enum CardFace {
ACE, TWO, THREE,
FOUR, FIVE, SIX, SEVEN,
EIGHT, NINE, TEN,
JACK, QUEEN, KING,
MAX_FACES,
};
/// Valid cards only use up 6 bits.
enum { NULL_CARD = 0xFF };
uint8_t
make_card(enum CardSuit const suit, enum CardFace const face) {
return suit | (face << 2);
}
void
print_card(uint8_t const card) {
char const *suit_str = NULL;
switch( card & 3 ) {
case SUIT_HEART: suit_str = "heart"; break;
case SUIT_DIAMOND: suit_str = "diamond"; break;
case SUIT_SPADE: suit_str = "spade"; break;
case SUIT_CLUB: suit_str = "club"; break;
}
char const *face_str = NULL;
switch( card >> 2 ) {
case ACE: face_str = "A"; break;
case TWO: face_str = "2"; break;
case THREE: face_str = "3"; break;
case FOUR: face_str = "4"; break;
case FIVE: face_str = "5"; break;
case SIX: face_str = "6"; break;
case SEVEN: face_str = "7"; break;
case EIGHT: face_str = "8"; break;
case NINE: face_str = "9"; break;
case TEN: face_str = "10"; break;
case JACK: face_str = "J"; break;
case QUEEN: face_str = "Q"; break;
case KING: face_str = "K"; break;
}
printf("card is: %s - %s\n", suit_str, face_str);
}
void
print_cards(size_t const len, uint8_t const card[const static len]) {
for( size_t i=0; i < len; i++ ) {
print_card(card[i]);
}
}
void
init_deck(uint8_t (*const deck)[MAX_SUITS * MAX_FACES]) {
for( enum CardSuit suit = SUIT_HEART; suit < MAX_SUITS; suit++ ) {
for( enum CardFace face = ACE; face < MAX_FACES; face++ ) {
(*deck)[(suit * MAX_FACES) + face] = (suit | (face << 2));
}
}
}
void
print_deck(uint8_t const (*const deck)[MAX_SUITS * MAX_FACES]) {
for( enum CardSuit suit = SUIT_HEART; suit < MAX_SUITS; suit++ ) {
for( enum CardFace face = ACE; face < MAX_FACES; face++ ) {
print_card((*deck)[(suit * MAX_FACES) + face]);
}
}
}
struct CardDeck {
uint8_t cards[MAX_SUITS * MAX_FACES];
uint64_t removed; /// what card[s] were removed from deck.
};
struct CardDeck
card_deck_make(void) {
struct CardDeck deck;
init_deck(&deck.cards);
deck.removed = 0;
return deck;
}
void
card_deck_print(struct CardDeck const deck) {
print_deck(&deck.cards);
}
uint_fast8_t
card_deck_draw_by_index(struct CardDeck *const deck, size_t const index) {
if( index >= sizeof deck->cards ) {
return NULL_CARD;
}
size_t const bitflag = 1LU << index;
if( deck->removed & bitflag ) {
return NULL_CARD;
}
uint_fast8_t const card = deck->cards[index];
deck->removed |= bitflag;
return card;
}
uint_fast8_t
card_deck_draw_random(struct CardDeck *const deck) {
size_t index = ( size_t )(rand() % (MAX_SUITS * MAX_FACES));
uint_fast8_t card = card_deck_draw_by_index(deck, index);
if( card==NULL_CARD && deck->removed != (uint64_t)(-1LLU) ) {
while( card==NULL_CARD ) {
index = ( size_t )(rand() % (MAX_SUITS * MAX_FACES));
card = card_deck_draw_by_index(deck, index);
}
}
return card;
}
void
card_deck_draw_random_to_hands(struct CardDeck *const restrict deck, size_t const hand_len, uint8_t hand[const restrict static hand_len]) {
for( size_t i=0; i < hand_len; i++ ) {
hand[i] = card_deck_draw_random(deck);
}
}
int main(int const argc, char *argv[const static argc]) {
srand(time(NULL));
struct CardDeck cards = card_deck_make();
card_deck_print(cards);
puts("");
enum{ HAND_SIZE = 5 };
uint8_t hand[HAND_SIZE];
card_deck_draw_random_to_hands(&cards, HAND_SIZE, hand);
print_cards(HAND_SIZE, hand);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment