-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdeck.c
214 lines (183 loc) · 4.59 KB
/
deck.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
/**
* This game is provided as an example of good use of the C programming
* language for beginners. We assume you are familiar with simple
* programming constructs like for loops and pointers. Complicated
* functions are well documented. This game was originally written
* by Riccardo Mutschlechner <[email protected]> and Nik Ingrassia,
* but was rewritten from scratch.
*
* Author: John Detter <[email protected]>
*
*/
#include <stdio.h> /** Needed for printf */
#include <string.h> /** Needed for memmove */
#include <stdlib.h> /** Needed for malloc and rand */
#include "gofish.h"
/**
* Fill a deck with the 52 game cards. Takes the deck, d, as
* the parameter.
*/
void deck_populate(struct deck* d)
{
d->top = -1;
rank_t r;
suit_t s;
/* Loop through all of the ranks */
for(r = R2; r <= RANK_MAX; r++)
{
/* For each rank, add one card of each suit */
for(s = CLUBS; s <= SUIT_MAX; s++)
{
/* the card we are adding to the deck */
struct card c;
c.r = r; /* Assign rank */
c.s = s; /* Assign suit */
/* Add the card to the deck */
if(deck_put(d, &c))
{
printf("gofish: deck full!\n");
exit(1);
}
}
}
}
/**
* Shuffle the given deck, d.
*/
void deck_shuffle(struct deck* d)
{
/* Just to a limited swapping randomization */
int x;
for(x = 0;x < 10000;x++)
{
/* Pick 2 indexes */
int index_1 = rand() % (d->top + 1);
int index_2 = rand() % (d->top + 1);
/* Swap the two values at the given indexes */
struct card tmp;
/* Save index_1 in tmp */
memmove(&tmp, d->cards + index_1, sizeof(struct card));
/* index_1 = index_2*/
memmove(d->cards + index_1, d->cards + index_2, sizeof(struct card));
/* index_2 = tmp */
memmove(d->cards + index_2, &tmp, sizeof(struct card));
}
}
/**
* Puts the given card, c, in the given deck, d. Returns 0 on
* success, nonzero otherwise.
*/
int deck_put(struct deck* d, struct card* c)
{
/* Is this deck full? */
if(d->top == DECK_SIZE - 1)
{
/* Can't add to a full deck */
printf("go fish: tried to add card to full deck!\n");
exit(1);
}
/* Increment the top index */
d->top++;
/* Put the card at the top index */
memmove(d->cards + d->top, c, sizeof(struct card));
return 0; /* Return success */
}
/**
* Draw a card from the given deck, d. Returns a pointer to
* a card on success (there were card(s) in the deck). Returns
* NULL on failure (the deck was empty).
*/
struct card* deck_draw(struct deck* d)
{
/* Is this deck empty? */
if(d->top < 0)
{
/* Return failure. */
return NULL;
}
/* Create a new card */
struct card* c = malloc(sizeof(struct card));
/* Copy the card in the deck */
memmove(c, d->cards + d->top, sizeof(struct card));
/* Delete the card from the deck */
memset(d->cards + d->top, 0, sizeof(struct card));
/* Adjust the top index */
d->top--;
return c;
}
/**
* Check to see if a deck, d, contains any cards of rank, r.
* If there exists such a card in the deck, it is removed
* from the deck and returned. Returns NULL if there is no
* such card in the deck.
*/
struct card* deck_contains(struct deck* d, rank_t r)
{
int x;
/* Loop through the cards in the deck */
for(x = 0;x <= d->top;x++)
{
if(d->cards[x].r == r)
{
/* Found a card with a matching rank! */
struct card* c = malloc(sizeof(struct card));
/* Copy the card from the deck */
memmove(c, d->cards + x, sizeof(struct card));
/* Fix the deck so there isn't an empty space */
for(;x <= d->top - 1;x++)
{
/* Move the next card to the current spot */
memmove(d->cards + x, d->cards + x + 1,
sizeof(struct card));
}
/* Adjust top of deck */
d->top--;
/* Return the card we found */
return c;
}
}
return NULL;
}
/**
* Check to see if the deck contains a completed set of cards.
* Return the rank of the card that has a complete set, and
* removes all of those cards from the deck. Returns -1 if
* no set was found.
*/
rank_t deck_get_set(struct deck* d)
{
/* Keep track of the cards we have */
char card_counts[RANK_MAX + 1];
memset(card_counts, 0, RANK_MAX + 1);
int x;
for(x = 0;x <= d->top;x++)
{
/* Increment card counts for this card rank */
card_counts[d->cards[x].r]++;
}
/* Did we find any sets? */
for(x = R2;x <= RANK_MAX;x++)
{
if(card_counts[x] >= 4)
{
/** We found a set! */
/* Remove all of these cards */
struct card* c = NULL;
do
{
/* Find and remove a card */
c = deck_contains(d, x);
/* Did we get a card? */
if(c)
{
/* Free the card*/
free(c);
}
} while(c != NULL);
/* Return this rank */
return x;
}
}
/* We found no complete sets */
return -1;
}