-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGame.cpp
More file actions
309 lines (275 loc) · 7.77 KB
/
Game.cpp
File metadata and controls
309 lines (275 loc) · 7.77 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
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
// Project Card Game
// by Pierre
// and Samuel
#include <vector>
#include "Game.h"
#include "Player.h"
#include "Card.h"
#include <algorithm>
#include <fstream>
#include <string>
#include <sstream>
#include <numeric>
using namespace std;
// Empty constructor
Game::Game()
{
_reserve = {};
_player1;
_player2;
}
// Constructor
Game::Game(const vector<Card> &reserve, Player &player1, Player &player2)
{
_reserve = reserve;
_player1 = player1;
_player2 = player2;
}
// Know if the game is finished and give the winner
bool Game::ended(Player &winner) const
{
bool finish = this->IsGameFinished();
if (finish)
{
if (_player1.GetPrestige() > _player2.GetPrestige())
{
winner = _player1;
}
else
{
if (_player1.GetPrestige() < _player2.GetPrestige())
{
winner = _player2;
}
}
}
return finish;
}
// Plays one round of the game
void Game::playsARound()
{
_player1.playsACard(_player2, _reserve);
}
// plays one round of the game
void Game::operator++()
{
this->playsARound();
}
// return true if the game is finished
bool Game::IsGameFinished() const
{
return !(_player1.enoughCards() && _player1.enoughPrestige() && _player2.enoughCards() &&
_player2.enoughPrestige());
}
// Return the winner with an integer
int Game::winner()
{
Player winner;
if (this->ended(winner))
{
if (winner == _player1)
{
return 1;
}
if (winner == _player2)
{
return -1;
}
}
return 0;
}
// Get the vector of ranks from a vector of Card with a chosen sort criteria
vector<int> vectorOfRanks(const vector<Card> &reserve, Tri sortCriteria)
{
unsigned int size = reserve.size();
// Create the vector of card index
vector<int> index(size);
// fill the vector with 0 to reserve.size()
iota(index.begin(), index.end(), 0);
// Sort the vector with the expected criteria
sortVectorOfCard(index, sortCriteria, reserve);
// Create the vector of ranks
vector<int> ranks(size);
for (unsigned int i = 0; i < size; i++)
{
ranks[index[i]] = i;
}
return ranks;
}
// Merge vectors into one vector
void mergeCard(vector<int> &deck, int start1, int end1, int end2, Tri sortCriteria, const vector<Card> &reserve)
{
// create a temporary vector to hold the elements of the first half of the input vector
vector<int> deck1(deck.size());
// calculate the starting index of the second half of the input vector
int start2 = end1 + 1;
// initialize indices for the two halves of the input vector
int cpt1 = start1;
int cpt2 = start2;
int i;
// copy the elements of the first half of the input vector into the temporary vector
for (i = start1; i <= end1; i++)
{
deck1[i - start1] = deck[i];
}
// iterate through the input vector from start to end
for (i = start1; i <= end2; i++)
{
// if all elements of the first half have been used, break
if (cpt1 == start2)
{
break; // all elements have been sorted
}
// if all elements of the second half have been used, add the remaining elements from the first half
else if (cpt2 == (end2 + 1))
{
deck[i] = deck1[cpt1 - start1];
cpt1++;
}
// if the element from the first half is greater than or equal to the element from the second half, add it to the input vector
else if (reserve[deck1[cpt1 - start1]].compareCard(reserve[deck[cpt2]], sortCriteria))
{
deck[i] = deck1[cpt1 - start1];
cpt1++;
}
// otherwise, add the element from the second half to the input vector
else
{
deck[i] = deck[cpt2];
cpt2++;
}
}
}
// recursive function to sort the input vector in descending order using merge sort
void mergeSortBisCard(vector<int> &deck, int start, int end, Tri sortCriteria, const vector<Card> &reserve)
{
// if the start index is not the same as the end index, the list is not fully sorted
if (start != end)
{
// calculate the midpoint of the list
int mid = (end + start) / 2;
// sort the first half of the list
mergeSortBisCard(deck, start, mid, sortCriteria, reserve);
// sort the second half of the list
mergeSortBisCard(deck, mid + 1, end, sortCriteria, reserve);
// merge the two sorted halves
mergeCard(deck, start, mid, end, sortCriteria, reserve);
}
}
// wrapper function to start the descending merge sort process on the input vector
void mergeSortCard(vector<int> &deck, int length, Tri sortCriteria, const vector<Card> &reserve)
{
// if the input vector has at least one element, begin the sorting process
if (length > 0)
{
// sort the entire input vector
mergeSortBisCard(deck, 0, length - 1, sortCriteria, reserve);
}
}
// Sort a vector of card
void sortVectorOfCard(vector<int> &deck, Tri sortCriteria, const vector<Card> &reserve)
{
// Here we use the merge sort with a vector of card
mergeSortCard(deck, deck.size(), sortCriteria, reserve);
}
// sort the reserve of the game
void sortReserve(vector<Card> &reserve)
{
sort(reserve.begin(), reserve.end(),
[](const Card &c1, const Card &c2)
{
return c1.getName() < c2.getName();
});
}
// Fill the reserve with the file
void Game::fillReserve(const string &filename)
{
ifstream file(filename);
if (!file.is_open())
{
throw out_of_range("Error while opening the file");
}
string actual_line, name;
int numLines = 0;
while (!file.eof())
{
//while (i<_reserve.size()) {
getline(file, actual_line);
Card c;
c.fill(actual_line);
_reserve.push_back(c);
numLines++;
}
if (numLines < 20)
{
throw out_of_range("We don't have enough data to start the game");
}
sortReserve(_reserve);
file.close();
}
// The following methods are not in the instructions, but we had them because they are useful many times
// compare game
bool Game::compareGame(const Game &game)
{
return this->compareReserve(game._reserve) &&
((_player1 == game._player1 && _player2 == game._player2) ||
(_player1 == game._player2 && _player2 == game._player1));
}
// Modify the prestige of the player two
void Game::modifyPlayerTwoPrestige(int num)
{
_player2.modifyPrestige(num);
}
// Modify the prestige of the player two
void Game::modifyPlayerOnePrestige(int num)
{
_player1.modifyPrestige(num);
}
// Clear the deck of the player Two
void Game::clearPlayerTwoDeck()
{
_player2.clearDeck();
}
// Compare the reserve of card
bool Game::compareReserve(const vector<Card> &vector) const
{
bool ok = true;
int size = _reserve.size();
if (vector.size() != size)
{
ok = false;
}
if (ok)
{
int i = 0;
while (ok && i < size)
{
if (!(_reserve[i] == vector[i]))
{
ok = false;
}
i++;
}
}
return ok;
}
// Get the player 1
Player Game::GetPlayerOne()
{
return _player1;
}
// Get the player 2
Player Game::GetPlayerTwo()
{
return _player2;
}
// Get the reserve of the game
vector<Card> Game::getReserve()
{
return _reserve;
}
// Get the size of the reserve
int Game::getSizeReserve()
{
return _reserve.size();
}