Random Cards from Decks

Wrote some code to pick random cards from an expanding number of decks. Only "opening" a new deck when needed. If you ask for 13 random diamonds and 13 random spades then it will only use one deck. But if you request 14 random diamonds or 5 random kings then it will start using a second deck.

int MAX_DECKS = 10;  
int16_t get_from_decks(bool *decks, int search_rank, int search_suit)  
{
    int start_rank = search_rank == -1 ? rand()%13 : search_rank;
    int start_suit = search_suit == -1 ? rand()%4 : search_suit;
    int rank, suit;
    int deck = 0;
    bool found = false;

    while(deck < MAX_DECKS && !found) {
        for(int rank_offset=0;
                rank_offset < (search_rank == -1 ? 13 : 1) && !found;
                rank_offset++) {
            for(int suit_offset=0;
                    suit_offset < (search_suit == -1 ? 4 : 1) && !found;
                    suit_offset++) {

                rank = (start_rank + rank_offset) % 13;
                suit = (start_suit + suit_offset) % 4;
                int idx = rank + suit * 13 + deck * 52;

                if(decks[idx]) {
                    decks[idx] = false;
                    found = true;
                }
            }
        }

        deck++;
    }

    return rank + suit * 13;
}

The algorithm will always try to empty the previous decks even if new ones have been opened. So if the first deck has 1 remaining club, the second deck has 10 clubs and you request a random club then it will always return the last club from deck 1.

If you go past MAX_DECKS then the code returns cards that match the search criteria but without taking into account decks (so five random hearts could come up 5 aces).

The code isn't high performance. It just does a brute force search for a free card matching the criteria. A search three and/or meta data about remaining cards in the deck would make it faster but I only need it to process a limited set of cards (and only once during a file load).

Demo of function:

int most_copies(int *array) {  
    int copies = 0;
    for(int i=0; array[i] != -1; i++) {
        int count = 1;
        for(int a=i+1; array[a] != -1; a++) {
            if(array[i] == array[a]) {
                count++;
            }
        }
        copies = count > copies ? count : copies;
    }
    return copies;
}

int main (int argc, char const *argv[])  
{
    bool* decks = (bool*)malloc(sizeof(bool)*52*MAX_DECKS);
    memset(decks, 1, sizeof(bool)*52*MAX_DECKS);

    int *created_cards = (int*)malloc(sizeof(int)*100);
    memset(created_cards, -1, sizeof(int)*100);

    // Get 52 random cards (full deck)
    for(int i=0; i<52; i++) {
        created_cards[i] = get_from_decks(decks, -1, -1);
    }
    printf("Decks for 52 cards: %d\n", most_copies(created_cards));

    // Get 60 random cards (full deck + 8 cards)
    memset(decks, 1, sizeof(bool)*52*MAX_DECKS);
    memset(created_cards, -1, sizeof(int)*100);
    for(int i=0; i<60; i++) {
        created_cards[i] = get_from_decks(decks, -1, -1);
    }
    printf("Decks for 60 cards: %d\n", most_copies(created_cards));

    // Get 5 aces (2 decks):
    memset(decks, 1, sizeof(bool)*52*MAX_DECKS);
    memset(created_cards, -1, sizeof(int)*100);
    for(int i=0; i<5; i++) {
        created_cards[i] = get_from_decks(decks, 0, -1);
    }
    printf("Decks for 5 aces: %d\n", most_copies(created_cards));   

    // Get 27 diamonds (3 decks):
    memset(decks, 1, sizeof(bool)*52*MAX_DECKS);
    memset(created_cards, -1, sizeof(int)*100);
    for(int i=0; i<27; i++) {
        created_cards[i] = get_from_decks(decks, -1, 0);
    }
    printf("Decks for 27 diamonds: %d\n", most_copies(created_cards));  

    return 0;
}

Output:

Decks for 52 cards: 1
Decks for 60 cards: 2
Decks for 5 aces: 2
Decks for 27 diamonds: 3
Older posts

Early Engine Demo

A couple of quick demos of a C / OpenGL project with platform layers for iPhone and Mac. Mac with gamepad input: iPhone with touch input: The goal is to have an simple way to work on our upcoming game project without having to rebuild/deploy to the a mobile device…

Swift JSON Performance

I'm currently working on my first real Swift project. A from-scratch update of one of ZenRockers old apps to make it fit better with iOS8 in terms of look and features. Swift performance has been close to Objective C for the most part. But there are times when Swift suddenly…

Swift & SpriteKit

I've been playing around with Swift this weekend. It's an interesting language. Not just because Apple has announced it as the future of iOS and Mac development. It feels a lot more concise and flexible than Objective C. E.g. optionals that replace nil testing so that: if(shop.lastOrder…

Windows Development

Finally got around to making my snake game run on Windows (download). Requires Windows 8 and the 32bit / x86 Visual C++ 2013 Runtime. Converting the game was straight forward. I spent a few hours trying to embed resources in the .exe but gave up and just included them in the…

Ghost: Feature Latest Post

I recently updated my Ghost blog setup to always show the full content of the latest post. By default ghost only shows excerpts of all posts. This is a quick guide to setting it up. Start by adding a partials folder to the theme if not already present. Then add…