Last active
July 9, 2024 05:19
-
-
Save assyrianic/60a5be1259d811a4b1676a3999b3527a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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