This repository was archived by the owner on May 6, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
250 lines (214 loc) · 7.06 KB
/
Copy pathmain.cpp
File metadata and controls
250 lines (214 loc) · 7.06 KB
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
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <time.h>
#include "game_state.h"
#include "card.h"
using namespace std;
using Deck = vector<Card*>;
/**
* Function to clear the terminal by inserting many new line characters.
*/
void clearTerminal();
/**
* Function to populate the deck with cards.
*
* @param deck A vector reference of Card pointers representing the deck
*/
void buildDeck(Deck& deck);
/**
* Function to shuffle the deck.
*
* @param deck A vector reference of Card pointers representing the deck
*/
void shuffleDeck(Deck&);
/**
* Function to draw a card from the deck to either the hand or discard pile.
*
* @param deck A vector reference of Card pointers representing the deck
* @param target A vector representing the structure that the card being drawn
* from the deck is being drawn to. This can be either a hand or the discard
* pile
*/
void drawCards(Deck& deck, Deck& target, Deck& discard, int);
/**
* Function to draw 7 cards to each player's hand at the beginning of the game.
*
* @param deck A vector reference of Card pointers representing the deck.
* @param hands A vector of vector of Card pointers representing each player
* and their hands. The indicies of the first vector represents a player, and
* the indicies of the vector at that index is each individual card within the
* player's hand.
*/
void populateHands(Deck& deck, vector<Deck>& hands, Deck& discard);
/**
* Renders the cards in he hand vector passed.
*
* @param hand A vector containing Card pointers
*/
void renderHand(Deck hand);
/**
* Renders the top card of the passed discard vector.
*
* @param hand A vector containing Card pointers
*/
void renderDiscard(Deck);
/**
* Passed references to the deck, hand, and discard vectors and a reference to
* the game state. This function will resolve the turn for the current player
* (whose index is stored in the game state). TakeTurn will query the user for
* input, draw cards if the previous card was a draw 2 card, or skip the current
* players turn (see numCardsToPlay in GameState).
*
* @param deck A vector reference of Card pointers representing the deck
* @param hand A vector reference of Card pointers representing a single player's hand
* @param discard A vector reference of Card pointers representing the discard pile
* @param gameState A reference of the game state object
* @return The index of the player who has won (negative value if no one has won)
*/
int takeTurn(Deck& deck, Deck& hand, Deck& discard, GameState& gameState);
int main(){
srand(time(0));
int num_players = 0;
int winner = -1;
do {
cout << "Enter the number of players (2-16): ";
cin >> num_players;
} while(num_players < 2 || num_players > 16);
GameState gameState(num_players);
Deck deck;
Deck discard;
vector<Deck> hands(num_players);
buildDeck(deck);
shuffleDeck(deck);
populateHands(deck, hands, discard);
drawCards(deck, discard, discard, 1);
while(winner == -1){
winner = takeTurn(deck, hands.at(gameState.currentPlayerIndex), discard, gameState);
}
cout << "Player " << winner << " wins!" << endl;
return 0;
}
void clearTerminal(){
for(int i = 0; i < 100; i++){
cout << endl;
}
}
void buildDeck(Deck &deck){
// Create Number Cards
for(int c = RED; c < NUM_COLORS; c++){
for(int n = 0; n < 10; n++){
Card* temp = new NumberCard((Color)c, n);
deck.push_back(temp);
deck.push_back(temp);
}
deck.push_back(new ReverseCard((Color)c));
deck.push_back(new ReverseCard((Color)c));
deck.push_back(new SkipCard((Color)c));
deck.push_back(new Draw2Card((Color)c));
deck.push_back(new Draw2Card((Color)c));
}
for(int i = 0; i < 18; ++i) {
deck.push_back(new WildCard());
deck.push_back(new Draw4Card());
}
}
void shuffleDeck(Deck &deck){
for(int i = 0; i < 1000; i++){
int idx1 = rand() % deck.size();
int idx2 = rand() % deck.size();
Card* temp = deck.at(idx1);
deck.at(idx1) = deck.at(idx2);
deck.at(idx2) = temp;
}
}
void drawCards(Deck &deck, Deck &target, Deck &discard, int numToDraw){
for(int i = 0; i < numToDraw; i++){
if(deck.size() == 0 && discard.size() > 1){
Card* top = discard.back();
discard.pop_back();
shuffleDeck(discard);
deck = discard;
discard.clear();
discard.push_back(top);
}
if(deck.size() > 0) {
target.push_back(deck.at(deck.size() - 1));
deck.pop_back();
}
}
}
void populateHands(Deck &deck, vector<Deck> &hands, Deck &discard){
for(int i = 0; i < hands.size(); i++){
drawCards(deck, hands.at(i), discard, 7);
}
}
void renderHand(Deck hand){
if(hand.size() > 0){
for(int i = 0; i <= 7; i++){
for(int j = 0; j < hand.size(); j++){
cout << hand.at(j)->render(i) << " ";
}
cout << endl;
}
} else {
for(int i = 0; i <= 7; i++)
cout << endl;
}
}
void renderDiscard(Deck discard){
for(int i = 0; i <= 7; i++){
cout << discard.at(discard.size() - 1)->render(i) << endl;
}
}
int takeTurn(Deck &deck, Deck &hand, Deck &discard, GameState &gameState){
clearTerminal();
renderDiscard(discard);
cout << "Player " << gameState.currentPlayerIndex + 1 << "'s turn." << endl;
drawCards(deck, hand, discard, gameState.numCardsToDraw);
gameState.numCardsToDraw = 0; // reset cards to draw back to 0
renderHand(hand);
// loop for number of cards to play (0 if previously played card was a "skip" or "draw 2")
//for(int j = 0; j < gameState.numCardsToPlay; j++){
if(!gameState.skipTurn){
// Collect user input
cout << "Discard Pile: " << discard.size() << " Cards in deck: " << deck.size() << endl << endl;
cout << "What would you like to do?" << endl;
int i;
for(i = 0; i < hand.size(); i++){
cout << i << ": Play Card" << endl;
}
cout << i << ": Draw a Card" << endl;
int input;
cin >> input;
do {
if (input > i)
{
cout << "This is an invalid input, please enter a valid input." << endl;
cin >> input;
}
else
break;
}while (input > i);
// Evaluate user input
if(hand.at(input)->play(discard.at(discard.size()-1), gameState)){
Card* temp;
temp = hand.at(input);
discard.push_back(temp);
hand.erase(hand.begin() + input); // Remove card in hand at position "input"
}
if(input == i){
drawCards(deck, hand, discard, 1);
}
}
else{
gameState.skipTurn = false;
}
if(hand.size() == 0){
return gameState.currentPlayerIndex;
} else{
// update variables for next turn
gameState.nextTurn();
return -1;
}
}