Skip to content

Commit 799bd0b

Browse files
committed
Finished tests and implementation of longest road
1 parent e942559 commit 799bd0b

File tree

8 files changed

+371
-31
lines changed

8 files changed

+371
-31
lines changed

include/GameBoard.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ class GameBoard {
3030

3131
int constructBoardFromFile(std::ifstream &file);
3232
int constructFileFromBoard(std::ofstream &file);
33+
34+
void freeRoads();
35+
void removeRoadEnd(Road * startRoad);
36+
int FindLongestRoad_FromPoint(Coordinate curr, Player & owner, std::map<Coordinate, bool>& marked, int length);
37+
3338
public:
3439
GameBoard();
3540
GameBoard(GameBoard&) = delete;
@@ -39,8 +44,10 @@ class GameBoard {
3944
int save_Board(std::string filename);
4045
int load_Board(std::string filename);
4146
const std::map<Coordinate, std::unique_ptr<GamePiece>>& getResources() const;
42-
const Road& getRoad(int start, int end);
47+
Road * getRoad(Coordinate start, Coordinate end);
4348

49+
int FindLongestRoad(Player & owner);
50+
4451
std::vector<Settlement*> GetNeighboringSettlements(Coordinate location);
4552

4653
void PlaceSettlement(Coordinate location, Player& Owner);

include/Player.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ class Player {
4545

4646
int getDevCardsInHand();
4747

48+
std::string getName();
49+
4850
void buyCard(DevelopmentCard* card);
4951
void playCard(DevelopmentCard* card);
5052

include/Road.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,26 @@
99
class Road {
1010
private:
1111
bool checkRoad();
12+
Coordinate start;
13+
Coordinate end;
1214

15+
bool marker;
1316
public:
1417
Road(Coordinate start, Coordinate end, Player& Owner);
1518
Road(Road&) = delete;
1619
~Road();
1720
Road& operator=(Road&) = delete;
1821

19-
//Made these public because I couldn't get getters to work, maybe someone else knows how. Paul
20-
Coordinate start;
21-
Coordinate end;
22+
Coordinate getStart() const;
23+
Coordinate getEnd() const;
2224

2325
bool equals(const Road& otherRoad);
2426
bool equals(const Coordinate& otherStart, const Coordinate& otherEnd);
2527

28+
bool isMarked();
29+
void mark();
30+
void unmark();
31+
2632
Player* owner;
2733

2834

src/GameBoard.cpp

Lines changed: 156 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,46 @@ GameBoard::GameBoard() {
2121
}
2222

2323
GameBoard::~GameBoard() {
24+
freeRoads();
25+
}
26+
27+
/*
28+
* Frees the roads data structure to prevent memory leaks
29+
*/
2430

31+
void GameBoard::freeRoads(){
32+
//Iterate over all the points in the roads map
33+
for (auto roadVector = roads.begin(); roadVector != roads.end(); ++roadVector)
34+
{
35+
//Iterate all the roads at a given point
36+
for (std::vector<Road*>::iterator road = roadVector->second.begin(); road != roadVector->second.end(); ++road) {
37+
Road * roadPtr = *road;
38+
39+
//If this is the start of the road we want to remove it, but we must first erase it the list at the other end of the road
40+
//If we don't then we may try to access a road which has already been freed
41+
if(roadPtr != NULL && roadPtr->getStart() == roadVector->first){
42+
removeRoadEnd(roadPtr);
43+
roadVector->second.erase(road);
44+
//Need to decrement the iterator to account for the lost item
45+
road--;
46+
delete roadPtr;
47+
}
48+
}
49+
}
50+
}
51+
52+
/**
53+
* Find and remove the road that matches startRoad
54+
*/
55+
void GameBoard::removeRoadEnd(Road * startRoad){
56+
std::vector<Road*> endRoadVector = roads[startRoad->getEnd()];
57+
for(std::vector<Road*>::iterator endRoad = endRoadVector.begin(); endRoad != endRoadVector.end(); ++endRoad){
58+
if((*endRoad) == startRoad){
59+
endRoadVector.erase(endRoad);
60+
//Need to decrement the iterator to account for the lost item
61+
endRoad--;
62+
}
63+
}
2564
}
2665

2766
int GameBoard::save_Board(std::string filename) {
@@ -142,51 +181,57 @@ bool GameBoard::outOfBounds(const Coordinate& coord) {
142181
/**
143182
* This code is embarrassing, but I couldn't really figure out how to easily check for out of bounds
144183
* I'm sure there is a simple algebraic function that does it, but I went for the hacky way.
184+
*
185+
* Discussed that we can just do a find in the map, and if it's not found then it's out of bounds
145186
*/
187+
146188
switch (coord.second) {
147189
case 0:
148-
return (coord.first >= 0 && coord.first <= 4);
190+
return !(coord.first >= 0 && coord.first <= 4);
149191
break;
150192
case 1:
151-
return (coord.first >= -2 && coord.first <= 5);
193+
return !(coord.first >= -2 && coord.first <= 5);
152194
break;
153195
case 2:
154-
return (coord.first >= -3 && coord.first <= 5);
196+
return !(coord.first >= -3 && coord.first <= 5);
155197
break;
156198
case 3:
157-
return (coord.first >= -3 && coord.first <= 4);
199+
return !(coord.first >= -3 && coord.first <= 4);
158200
break;
159201
case 4:
160-
return (coord.first >= -4 && coord.first <= 4);
202+
return !(coord.first >= -4 && coord.first <= 4);
161203
break;
162204
case 5:
163-
return (coord.first >= -4 && coord.first <= 3);
205+
return !(coord.first >= -4 && coord.first <= 3);
164206
break;
165207
case 6:
166-
return (coord.first >= -5 && coord.first <= 3);
208+
return !(coord.first >= -5 && coord.first <= 3);
167209
break;
168210
case 7:
169-
return (coord.first >= -5 && coord.first <= 2);
211+
return !(coord.first >= -5 && coord.first <= 2);
170212
break;
171213
case 8:
172-
return (coord.first >= -4 && coord.first <= 0);
214+
return !(coord.first >= -4 && coord.first <= 0);
173215
break;
174216
default:
175217
break;
176218
}
177-
return false;
219+
return true;
178220
}
179221

222+
/**
223+
* Checks to make sure the road doesn't already exist. If it does, then we don't want to add it again
224+
*/
180225
bool GameBoard::roadExists(Coordinate start, Coordinate end) {
181-
std::vector<Road*> roadVector = roads[start];
182-
for (std::vector<Road*>::iterator road = roadVector.begin();
183-
road != roadVector.end(); ++road) {
184-
if ((*road)->equals(start, end))
185-
return true;
186-
}
187-
return false;
226+
Road * isRoad = getRoad(start, end);
227+
if (isRoad == NULL)
228+
return false;
229+
return true;
188230
}
189231

232+
/**
233+
* Checks to make sure the road being placed at a valid point according to the rules
234+
*/
190235
bool GameBoard::isRoadConnectionPoint(Coordinate start, Coordinate end, Player& Owner){
191236
/** Need to figure out the CornerPiece/GamePiece predicament
192237
CornerPiece * corner = corners[start];
@@ -199,6 +244,9 @@ bool GameBoard::isRoadConnectionPoint(Coordinate start, Coordinate end, Player&
199244
return true;
200245
}
201246

247+
/**
248+
* Runs a series of checks to make sure the road can be placed
249+
*/
202250
bool GameBoard::verifyRoadPlacement(Coordinate start, Coordinate end, Player& Owner) {
203251
if (outOfBounds(start) || outOfBounds(end))
204252
return false;
@@ -208,23 +256,112 @@ bool GameBoard::verifyRoadPlacement(Coordinate start, Coordinate end, Player& Ow
208256

209257
if (!isRoadConnectionPoint(start, end, Owner))
210258
return false;
259+
211260
return true;
212261
}
213262

263+
/**
264+
* Places a road at the specified coordinates that will be owned by the given player
265+
*/
214266
void GameBoard::PlaceRoad(Coordinate start, Coordinate end, Player& Owner) {
215-
verifyRoadPlacement(start, end, Owner);
267+
if (!verifyRoadPlacement(start, end, Owner))
268+
return;
269+
216270
Road * newRoad;
217271
try {
218272
newRoad = new Road(start, end, Owner);
219273
} catch (int n) {
220274
//Coordinates did not meet the criteria for a valid road
221275
return;
222276
}
223-
224277
std::vector<Road*> roadVector = roads[start];
225278
roadVector.push_back(newRoad);
279+
roads[start] = roadVector;
226280

227281
roadVector = roads[end];
228282
roadVector.push_back(newRoad);
283+
roads[end] = roadVector;
284+
}
285+
286+
/**
287+
* returns a pointer to the road located at the specified coordinates. Will return NULL if the road is not found
288+
*/
289+
Road * GameBoard::getRoad(Coordinate start, Coordinate end){
290+
std::vector<Road*> roadVector = roads[start];
291+
for (std::vector<Road*>::iterator road = roadVector.begin(); road != roadVector.end(); ++road) {
292+
if ((*road)->equals(start, end))
293+
return *road;
294+
}
295+
return NULL;
296+
}
297+
298+
/**
299+
* Parent function for the find longest road traversal. Note that longest path is NP-Hard, so there is no simple algorithm for this.
300+
*/
301+
int GameBoard::FindLongestRoad(Player & owner){
302+
int longest_path = 0;
303+
//for each road vertex v on the board
304+
for (auto roadVector = roads.begin(); roadVector != roads.end(); ++roadVector){
305+
//find the longest path from v
306+
std::map<Coordinate, bool> marked;
307+
Coordinate start = roadVector->first;
308+
int temp_longest_path = FindLongestRoad_FromPoint(start, owner, marked, 0);
309+
310+
std::cout << "LONGEST PATH: " << start.first << ", " << start.second << ": " << temp_longest_path << "\n";
311+
312+
//if that path is longer than the current longest, set to the longest
313+
if (temp_longest_path > longest_path)
314+
longest_path = temp_longest_path;
315+
}
316+
317+
return longest_path;
318+
}
319+
320+
321+
int GameBoard::FindLongestRoad_FromPoint(Coordinate curr, Player & owner, std::map<Coordinate, bool>& marked, int length){
322+
323+
std::cout << " " << curr.first << ", " << curr.second << ": " << length << "\n";
324+
325+
marked[curr] = true;
326+
int longest_path = length;
327+
//traverse all the surrounding edges and vertices
328+
std::vector<Road*> roadVector = roads[curr];
329+
for (std::vector<Road*>::iterator road = roadVector.begin(); road != roadVector.end(); ++road) {
330+
331+
int temp_longest_path = length;
332+
333+
//if the owner is correct and the road is unmarked
334+
if ( !(*road)->isMarked() && (*road)->owner->getName().compare(owner.getName()) == 0){
335+
336+
temp_longest_path++;
337+
(*road)->mark();
338+
//Check if you can traverse to the next vertex and make that step if you can
339+
if(curr != (*road)->getStart() && !marked[(*road)->getStart()]){
340+
temp_longest_path = FindLongestRoad_FromPoint((*road)->getStart(), owner, marked, temp_longest_path);
341+
}else if (curr != (*road)->getEnd() && !marked[(*road)->getEnd()]){
342+
temp_longest_path = FindLongestRoad_FromPoint((*road)->getEnd(), owner, marked, temp_longest_path);
343+
}
344+
(*road)->unmark();
345+
}
346+
347+
if(temp_longest_path > longest_path)
348+
longest_path = temp_longest_path;
349+
}
350+
marked[curr] = false;
351+
return longest_path;
229352
}
230353

354+
355+
356+
357+
358+
359+
360+
361+
362+
363+
364+
365+
366+
367+

src/Player.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ void Player::playCard(DevelopmentCard *card)
6161

6262
}
6363

64+
std::string Player::getName(){
65+
return name;
66+
}
6467

6568

6669
int Player::getWood()

src/Road.cpp

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,32 +10,41 @@ Road::Road(Coordinate start, Coordinate end, Player& Owner) {
1010
}
1111
owner = &Owner;
1212

13+
marker = false;
14+
1315
//If the input is bad, throw an exception so bad roads won't be built
14-
if(!checkRoad())
16+
if(!checkRoad()){
1517
throw -1;
18+
}
19+
1620

1721
}
1822

1923
/**
2024
* Valid roads must start in one point and end in another point a distance of 1 away.
2125
*/
2226
bool Road::checkRoad(){
27+
if (start == end)
28+
return false;
2329

24-
int dist = std::abs(start.first - end.first) + std::abs(start.second - end.second);
25-
return dist == 1;
30+
int dist = std::abs((start.first - end.first) + (start.second - end.second));
31+
return (dist <= 1);
2632
}
2733

2834
Road::~Road() {
2935

3036
}
3137

32-
Coordinate Road::getStart(){
38+
Coordinate Road::getStart() const{
3339
return start;
3440
}
41+
Coordinate Road::getEnd() const{
42+
return end;
43+
}
3544

3645
bool Road::equals(const Road& otherRoad){
37-
Coordinate otherstart = otherRoad.start;
38-
Coordinate otherend = otherRoad.end;
46+
Coordinate otherstart = otherRoad.getStart();
47+
Coordinate otherend = otherRoad.getEnd();
3948
return equals(otherstart, otherend);
4049
}
4150

@@ -45,3 +54,19 @@ bool Road::equals(const Coordinate& otherStart, const Coordinate& otherEnd){
4554
return false;
4655
}
4756

57+
58+
59+
bool Road::isMarked(){
60+
return marker;
61+
}
62+
63+
void Road::mark(){
64+
marker = true;
65+
}
66+
67+
void Road::unmark(){
68+
marker = false;
69+
}
70+
71+
72+

0 commit comments

Comments
 (0)