You don't have to delete anything.
Shuffle your deck
array (using a Fisher-Yates shuffle or similar algorithm). Deal each card from the "top" of the deck:
int top = 0;
card1 = deck[top++];
card2 = deck[top++];
card3 = deck[top++];
...
etc. The top
variable is the index of the next available card in the deck.
The general outline of your code will be something like
#define DECKSIZE 52
#define HANDSIZE 5
int main( void )
{
int deck[DECKSIZE] = { ... }; // initial deck;
size_t top = 0; // points to next available card
shuffle( deck, DECKSIZE );
int hero[HANDSIZE] = {0}; // 0 means no card has been drawn for
int villan[HANDSIZE] = {0}; // that element.
if ( deal( hero, HANDSIZE, deck, DECKSIZE, &top ) &&
deal( villan, HANDSIZE, deck, DECKSIZE, &top ) )
{
/**
* do stuff with hero and villan hands
*/
}
else
{
/**
* Not enough cards available in deck for two hands.
*/
}
};
Your deal
function would look something like
int deal( int *hand, size_t handsize, int *deck, size_t decksize, size_t *top )
{
size_t i;
for ( i = 0; i < handsize && *top < decksize; i++ )
hand[i] = deck[(*top)++];
return i == handsize;
}
This function will return 0
if we run out of cards in deck
before we've dealt the hand, in which case you'll need to do...something. Good luck!
If you want to deal a partial hand (such as to replace 3 cards), you'd do something like
if ( deal( &hero[2], 3, deck, DECKSIZE, &top) )
...
This call will overwrite hero[2]
through hero[4]
with three new cards drawn from deck
. With each call to deal
, top
will be advanced to point to the next available card in the deck.
You can write a discard
function that returns cards to the deck. It means keeping a separate bottom
variable and updating that:
int discard( int card, int *deck, size_t decksize, size_t *top, size_t *bottom )
{
int result = *bottom < *top && *bottom < decksize;
if ( result )
deck[(*bottom)++] = card;
return result;
}
Obviously, bottom
should be strictly less than the deck size and strictly less than top
on a discard; otherwise, we haven't managed our deck or hands properly. With a little work, you could make your array "circular", such that top
and bottom
"wrap around" as necessary. If you exhaust the deck, you can reshuffle (minus the cards in hand, which will be the deck
entries between bottom
and top
) and reset top
and bottom
as necessary.
Play with this on paper for a little while, and it should become obvious.
EDIT
Addressing questions here:
At which point do you assign deck[5] to a card, for instance
That happens in the deal
function, in the for
loop. The first time we call deal
, we tell it to deal to the hero
hand:
deal( hero, HANDSIZE, deck, DECKSIZE, &top )
At this point, top
is 0. Assuming we're dealing 5 cards at a time, the first call to deal
effectively does this:
Loop iteration 0: hero[0] = deck[0]
Loop iteration 1: hero[1] = deck[1]
Loop iteration 2: hero[2] = deck[2]
Loop iteration 3: hero[3] = deck[3]
Loop iteration 4: hero[4] = deck[4]
When the function returns, the top
variable has been updated to 5. The next time we call deal
, we tell it to deal to the villain
hand:
deal( villain, HANDSIZE, deck, DECKSIZE, &top )
Again, assuming we're dealing 5 cards at a time, the loop effectively does this:
Loop iteration 0: villain[0] = deck[5];
Loop iteration 1: villain[1] = deck[6];
Loop iteration 2: villain[2] = deck[7];
Loop iteration 3: villain[3] = deck[8];
Loop iteration 4: villain[4] = deck[9];
After the second call to deal
, top
has been updated to 10.
Each time you call deal
with the top
variable, it will start dealing from deck
at the position specified by top
, and each time through the loop it will add 1 to top
. The loop will exit if one of two conditions is true:
i == handsize
- we've dealt all the cards necessary for this hand
*top == decksize
- we've reached the end of the array, nor more cards may be dealt.
So, suppose you've dealt a number of hands, and there are only 3 cards left in the deck - if you try to deal 5 more cards, the loop will exit before you've dealt all 5 cards, and we'll return a 0 to indicate that no more cards are left in the deck.
at which point is the desk shuffled randomly?
You would call a shuffle
function to do that before the first call to deal
:
int deck[DECKSIZE] = { ... };
...
shuffle( deck, DECKSIZE );
...
if ( deal( hero, HANDSIZE, deck, DECKSIZE, &top ) &&
deal( villain, HANDSIZE, deck, DECKSIZE, &top ) )
{
...
}
A simplistic (and not terribly good) implementation of the shuffle
function would be:
void shuffle( int *deck, size_t decksize )
{
for ( size_t i = 0; i < decksize; i++ )
{
int r = rand() % (decksize - i)
int tmp = deck[i+r];
deck[i+r] = deck[i];
deck[i] = tmp;
}
}
Basically, what this does is swap each deck[i]
with a randomly chosen element from deck[i]
through deck[decksize-1]
(meaning the element may remain in place). Assume we have 5 cards. The first time through the loop, i
points to the first card. We pick an offset from i
at random and call it r
:
i --> 1
2
3
4 <-- r
5
We then swap the contents of deck[i]
and deck[i+r]
, and then advance i
:
4
i --> 2
3
1
5
We pick another r
at random from the remaining elements:
4
i --> 2
3
1
5 <-- r
and do another swap and advance i
:
4
5
i --> 3
1
2
Lather, rinse, repeat - by the end of the loop, the array is more-or-less randomly shuffled.