From a79e1eefe33b202d368a7ae339b8abe35117057d Mon Sep 17 00:00:00 2001 From: Andrin Fassbind Date: Sun, 5 Dec 2021 13:53:36 +0100 Subject: [PATCH] Implemented longest Road logic in SiedlerGame -adjusted Road and Settlement to return position --- src/ch/zhaw/catan/City.java | 6 +- src/ch/zhaw/catan/Dummy.java | 4 +- src/ch/zhaw/catan/Road.java | 17 ++- src/ch/zhaw/catan/Settlement.java | 11 +- src/ch/zhaw/catan/SiedlerGame.java | 158 ++++++++++++++++++++++-- test/ch/zhaw/catan/SiedlerGameTest.java | 33 +++++ 6 files changed, 212 insertions(+), 17 deletions(-) diff --git a/src/ch/zhaw/catan/City.java b/src/ch/zhaw/catan/City.java index 499bf87..a976267 100644 --- a/src/ch/zhaw/catan/City.java +++ b/src/ch/zhaw/catan/City.java @@ -1,9 +1,11 @@ package ch.zhaw.catan; +import java.awt.*; + public class City extends Settlement { - public City(Config.Faction faction) { - super(faction); + public City(Config.Faction faction, Point position) { + super(faction,position); } public String toString() { diff --git a/src/ch/zhaw/catan/Dummy.java b/src/ch/zhaw/catan/Dummy.java index ca1bbe2..bf94f5f 100644 --- a/src/ch/zhaw/catan/Dummy.java +++ b/src/ch/zhaw/catan/Dummy.java @@ -20,8 +20,8 @@ public class Dummy { TextTerminal textTerminal = textIO.getTextTerminal(); SiedlerBoard board = new SiedlerBoard(); board.addField(new Point(2, 2), Land.FOREST); - board.setCorner(new Point(3, 3), new Settlement(Config.Faction.RED)); - board.setEdge(new Point(2, 0), new Point(3, 1), new Road(Config.Faction.BLUE)); + board.setCorner(new Point(3, 3), new Settlement(Config.Faction.RED,new Point(3, 3))); + board.setEdge(new Point(2, 0), new Point(3, 1), new Road(Config.Faction.BLUE,new Point(2, 0),new Point(2, 0))); board.addFieldAnnotation(new Point(2, 2), new Point(3, 1), "AA"); Map lowerFieldLabel = new HashMap<>(); diff --git a/src/ch/zhaw/catan/Road.java b/src/ch/zhaw/catan/Road.java index 5131770..1bc37a5 100644 --- a/src/ch/zhaw/catan/Road.java +++ b/src/ch/zhaw/catan/Road.java @@ -1,8 +1,23 @@ package ch.zhaw.catan; +import java.awt.*; + public class Road extends Structure { - public Road(Config.Faction faction) { + private Point start,end; + + + public Road(Config.Faction faction,Point start,Point end) { super(faction); + this.start = start; + this.end = end; + } + + public Point getStart() { + return start; + } + + public Point getEnd() { + return end; } } diff --git a/src/ch/zhaw/catan/Settlement.java b/src/ch/zhaw/catan/Settlement.java index c70734c..b10595d 100644 --- a/src/ch/zhaw/catan/Settlement.java +++ b/src/ch/zhaw/catan/Settlement.java @@ -1,8 +1,17 @@ package ch.zhaw.catan; +import java.awt.*; + public class Settlement extends Structure { - public Settlement(Config.Faction faction) { + private Point position; + + public Settlement(Config.Faction faction,Point position) { super(faction); + this.position = position; + } + + public Point getPosition() { + return position; } } diff --git a/src/ch/zhaw/catan/SiedlerGame.java b/src/ch/zhaw/catan/SiedlerGame.java index ba34a58..207bf94 100644 --- a/src/ch/zhaw/catan/SiedlerGame.java +++ b/src/ch/zhaw/catan/SiedlerGame.java @@ -4,10 +4,8 @@ import ch.zhaw.catan.Config.Faction; import ch.zhaw.catan.Config.Resource; import java.awt.*; -import java.util.ArrayList; -import java.util.HashMap; +import java.util.*; import java.util.List; -import java.util.Map; /** @@ -151,7 +149,7 @@ public class SiedlerGame { if(!validPositionForSettlement(position)){ return false; } - board.setCorner(position, new Settlement(allPlayers.get(activePlayer).getFaction())); + board.setCorner(position, new Settlement(allPlayers.get(activePlayer).getFaction(),position)); if(payout) { List lands = board.getLandsForCorner(position); for (Config.Land land : lands) { @@ -176,7 +174,7 @@ public class SiedlerGame { if (!validPositionForRoad(roadStart, roadEnd)){ return false; } - board.setEdge(roadStart, roadEnd, new Road(allPlayers.get(activePlayer).getFaction())); + board.setEdge(roadStart, roadEnd, new Road(allPlayers.get(activePlayer).getFaction(),roadStart,roadEnd)); return true; } @@ -254,7 +252,7 @@ public class SiedlerGame { return false; } //4. Insert Settlement to map - board.setCorner(position, new Settlement(allPlayers.get(activePlayer).getFaction())); + board.setCorner(position, new Settlement(allPlayers.get(activePlayer).getFaction(),position)); return true; } @@ -279,7 +277,7 @@ public class SiedlerGame { } //2. Check if Settlement has already been built Settlement atCurrentPosition = board.getCorner(position); //todo prüfen ob Siedlung von richtiger Faction und nicht Stadt - if (atCurrentPosition == null){ + if (atCurrentPosition == null || atCurrentPosition.getFaction() != allPlayers.get(activePlayer).getFaction()){ return false; } //3. Can player build a City. @@ -287,7 +285,7 @@ public class SiedlerGame { return false; } //4.Insert City into the map. - board.setCorner(position,new City(allPlayers.get(activePlayer).getFaction())); + board.setCorner(position,new City(allPlayers.get(activePlayer).getFaction(),position)); return true; } @@ -317,7 +315,7 @@ public class SiedlerGame { return false; } //3. Insert Road to map - board.setEdge(roadStart, roadEnd, new Road(allPlayers.get(activePlayer).getFaction())); + board.setEdge(roadStart, roadEnd, new Road(allPlayers.get(activePlayer).getFaction(),roadStart,roadEnd)); return true; } @@ -466,10 +464,148 @@ public class SiedlerGame { return winPoints; } - private Faction getLongestRoadFaction() { - return null; //todo implement + + /** + * This method returns the faction of the player with the longest road longer than 5. + * @return null if there is no player with a road longer than 5 otherwise it returns the faction of the specific player + */ + private Faction getLongestRoadFaction() { + List corners = board.getCorners(); + List factionList = getPlayerFactions(); + HashMap players = new HashMap<>(); + int highest = 0; + Config.Faction longestRoad = null; + for(Config.Faction faction : factionList) { + int count = 0; + players.put(faction,count); + for(Settlement settlement : corners){ + HashSet roads = new HashSet<>(); + roads = countRoad(faction,settlement.getPosition(),roads,true); + count = roads.size(); + int currentCount = players.get(faction); + if(count > currentCount) { + players.put(faction,count); + } + } + } + for(Config.Faction faction : players.keySet()) { + if(players.get(faction) >= 5 && players.get(faction)>highest) { + highest = players.get(faction); + longestRoad = faction; + } + } + return longestRoad; } + /** + * This method is recursive and adds all roads which belongs to a specific players and stringing together to a HashSet. + * The length of the HashSet represents the length of the longest Road the player has. + * @param faction the faction of the player to check on + * @param position there has to be a starting point to start counting. In this case it's a corner where a settlement belonging to the players faction is build on. + * @param roads is the hashset with all roads belong to the player which are stringing together + * @param add if true branches needs to be count together. (for example if it is the starting point(first time of counting)) otherwise the longest branch is beeing added to roads. + * @return HashSet with all roads from a specific player which are string together. + */ + private HashSet countRoad(Config.Faction faction,Point position,HashSet roads,boolean add) { + List roadslist = board.getAdjacentEdges(position); + + Iterator it2 = roads.iterator(); + while(it2.hasNext()) { + Road roadsroad = (Road) it2.next(); + Iterator it3 = roadslist.iterator(); + while (it3.hasNext()){ + Road roadslistRoad = (Road) it3.next(); + if(roadslistRoad == roadsroad || roadslistRoad.getFaction() != faction) { + it3.remove(); + } + } + } + + + if(roadslist.size() == 1) { + roads.add(roadslist.get(0)); + position = getNextPoint(roadslist.get(0),position); + roads = countRoad(faction,position,roads,false); + } + + else if(roadslist.size() == 2) { + HashSet listOne = (HashSet) roads.clone(); + HashSet listTwo = (HashSet) roads.clone(); + listOne.add(roadslist.get(0)); + Point positionOne = getNextPoint(roadslist.get(0),position); + listTwo.add(roadslist.get(1)); + Point positionTwo = getNextPoint(roadslist.get(1),position); + listOne = countRoad(faction,positionOne,listOne,false); + listTwo = countRoad(faction,positionTwo,listTwo,false); + if(add) { + for (Road road : listOne) { + listTwo.add(road); + } + roads = listTwo; + }else { + HashSet tallest; + if(listOne.size()>= listTwo.size()) { + tallest = listOne; + }else{ + tallest = listTwo; + } + for (Road road : tallest) { + roads.add(road); + } + } + + } + + else if(roadslist.size() == 3) { + HashSet listOne = (HashSet) roads.clone(); + HashSet listTwo = (HashSet) roads.clone(); + HashSet listThree = (HashSet) roads.clone(); + listOne.add(roadslist.get(0)); + Point positionOne = getNextPoint(roadslist.get(0),position); + listTwo.add(roadslist.get(1)); + Point positionTwo = getNextPoint(roadslist.get(1),position); + listThree.add(roadslist.get(2)); + Point positionThree = getNextPoint(roadslist.get(2),position); + listOne = countRoad(faction,positionOne,listOne,false); + listTwo = countRoad(faction,positionTwo,listTwo,false); + listThree = countRoad(faction,positionThree,listThree,false); + + HashSet tallest; + HashSet secondtallest; + + if(listOne.size()>=listTwo.size()) { + tallest = listOne; + secondtallest = listTwo; + }else { + tallest = listTwo; + secondtallest = listOne; + }if(listThree.size() >= secondtallest.size()) { + secondtallest = listThree; + } + for(Road road : secondtallest) { + tallest.add(road); + } + roads = tallest; + } + return roads; + } + + /** + * This method is beeing used to evaluate the next starting position to get the adjacent Roads from it. + * @param road the next road to check on + * @param position the current starting point + * @return return the oposite point of the current point. + */ + private Point getNextPoint(Road road,Point position) { + Point start = road.getStart(); + Point end = road.getEnd(); + if(position.equals(start)) { + position = end; + }else { + position = start; + } + return position; + } /** * Places the thief on the specified field and steals a random resource card (if diff --git a/test/ch/zhaw/catan/SiedlerGameTest.java b/test/ch/zhaw/catan/SiedlerGameTest.java index 2b3d4d6..2d68560 100644 --- a/test/ch/zhaw/catan/SiedlerGameTest.java +++ b/test/ch/zhaw/catan/SiedlerGameTest.java @@ -1,8 +1,14 @@ package ch.zhaw.catan; import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.beryx.textio.TextIO; +import org.beryx.textio.TextIoFactory; +import org.beryx.textio.TextTerminal; import org.junit.jupiter.api.Test; +import java.awt.*; + /*** * TODO Write your own tests in this class. @@ -18,4 +24,31 @@ public class SiedlerGameTest { assertTrue(false); } + /** + * To Test getLongestRoad in SiedlerGame isolatet do: + * 1. make SiedlerGame.getLongestRoadFaction, Siedlergame.countRoad && Siedlergame.getNextPoint static + * 2. make SiedlerGame.getLongestRoadFaction public + * 3. add Parameter Board to SiedlerGame.getLongestRoadFaction and SiedlerGame.countRoad. + * 4. add Parameter faction to SiedlerGame.getLongestRoadFaction + * 5. Create Board in testLongestRoad() and Hashmap with faction + * Tipp: Logic Equivalent classes are: start counting at settlements with 0 or 1 or 2 or 3 own roads attached to it + * Make branches in between the road with diffrent lengths. + * + */ + @Test + public void testLongestRoad() { + SiedlerBoard board = new SiedlerBoard(); + board.createFixGamefield(); + board.setEdge(new Point(6, 6), new Point(5, 7), new Road(Config.Faction.BLUE,new Point(6, 6),new Point(5, 7))); + board.setEdge(new Point(4, 6), new Point(5, 7), new Road(Config.Faction.BLUE,new Point(4, 6),new Point(5, 7))); + board.setEdge(new Point(4, 6), new Point(4, 4), new Road(Config.Faction.BLUE,new Point(4, 6),new Point(4, 4))); + board.setEdge(new Point(4, 6), new Point(3, 7), new Road(Config.Faction.BLUE,new Point(4, 6),new Point(3, 7))); + board.setEdge(new Point(3, 7), new Point(3, 9), new Road(Config.Faction.BLUE,new Point(3, 7),new Point(3, 9))); + board.setEdge(new Point(3, 9), new Point(4, 10), new Road(Config.Faction.BLUE,new Point(3, 9),new Point(4, 10))); + board.setEdge(new Point(4, 10), new Point(5, 9), new Road(Config.Faction.BLUE,new Point(4, 10),new Point(5, 9))); + board.setCorner(new Point(3,7),new Settlement(Config.Faction.BLUE,new Point(3,7))); + //SiedlerGame.getLongestRoadFaction(board,faction); + + } + } \ No newline at end of file