loc.displayCostToEachNeighbor();
The goals of this assignment are to:
The Neighbor class outline is provided for you (see Neighbor.java). The Neighbor class has the following constructor and methods, which you need to implement:
Constructor | Description |
---|---|
Neighbor(int cost, GraphNode neighbor) | Constructs a Neighbor with cost of the link and the neighbor at the other end. |
Method | Description |
int getCost() | Returns the cost of travelling this edge to get to the Neighbor at the other end of this edge. |
GraphNode getNeighborNode() | Returns the Neighbor (node) that is at the other end of "this" node's edge. |
int compareTo(Neighbor otherNode) | Return the results of comparing this node's neighbor name to the other node's neighbor name. Allows List of Neighbors to be sorted. Hint: Read the java docs for String class carefully. |
String toString() | Returns a String representation of this Neighbor. The String that is returned shows an arrow (with the cost in the middle) and then the Neighbor node's name. Example: " --1--> b" indicates a cost of 1 to get to node b Note: Quotes are given here for clarification, do not print the quotes. |
You may not add any public methods to the Neighbor class, but you may add private helper methods.
A GraphNode class outline is also provided for you (see GraphNode.java). The GraphNode class has the following constructor and methods, which you need to implement:
Constructor | Description |
---|---|
GraphNode(String name) | Constructs a GraphNode with the vertex name and empty neighbors list. |
Method | Description |
String getNodeName() | Returns the name of the vertex. |
List<Neighbor> getNeighbors() | Returns the neigbors of this vertex. |
void setVisited(boolean flagVal) | Sets the visited flag of this vertex. |
boolean getVisited() | Gets the visited flag of this vertex. |
int compareTo(GraphNode otherNode) | Return the results of comparing this node's name to the other node's name. Return negative value or 0 or positive value |
void addNeighbor(GraphNode neighbor, int cost) | Adds a new neighbor and maintains sorted order of neighbors by neighbor name. You can sort any List which stores object instances from a class that implements Comparable<T> interface, simply by calling <List_instance_variable>.sort(null); You need not implement your own sort functionality, but can use the built-in sort function. |
void displayCostToEachNeighbor() | Prints a list of neighbors of this GraphNode and the cost of the edge to them. Example: "1 b" "4 c" Note: Quotes are given here for clarification, do not print the quotes. |
int getCostTo(String neighborName) | Returns cost to reach the neighbor. Throws NotNeighborException if neighborName is not a neighbor. |
GraphNode getNeighbor(String neighborName) | Returns the GraphNode associated with name that is a neighbor of the current node. Throws NotNeighborException if neighborName is not a neighbor. |
Iterator<String> getNeighborNames() | Returns an iterator that can be used to find neighbor names of this GraphNode. Hint: You need yo construct a new List here. |
void setSpycam(boolean cam) | Sets/unsets spycam at this node. |
boolean getSpycam() | Returns information about spycam presense in this node. |
boolean isNeighbor(String neighborName) | Returns true if this node name is a neighbor of current node. Retrue if the node is an adjacent neighbor or false otherwise. |
String toString() | Returns the name of this node. |
You may not add any public methods to the GraphNode class, but you may add private helper methods.
A Player class outline is also provided for you (see Player.java). The Player class has the following constructor and methods, which you need to implement:
Constructor | Description |
---|---|
Player(String name, int budget, int spycams, GraphNode startnode) | Constructs an instance of Player to track location and other information for the player. |
Method | Description |
void decreaseBudget(int dec) | Subtract the decrease amount from the budget. |
boolean dropSpycam() | If there are no remaining spy cams to drop, display "Not enough spycams" and return false. Otherwise: If there is not a spy cam at the player's current location:
|
int getBudget() | Return the amount remaining in this player's budget. |
GraphNode getLocation() | Returns the node where the player is currently located. |
String getLocationName() | Returns the name of the node where the player is currently located. |
String getName() | Return the name of the player. |
void getSpycamBack(boolean pickupSpyCam) | If pickupSpyCam is true, increment the number of spy cams remaining. Note: Make sure to unset the spycam on the GraphNode as well. |
int getSpycams() | Returns the number of spy cams available to drop. |
boolean move(String name) |
Change the location of the player to the specified node. Moves to nodes with a cost of one are not counted. (ie. it is "free" to "walk" to a node). If attempt to move to a node that is not a neighbor (node with name nn) is made, displays the message: "nn is not a neighbor of your current location" and returns false. If there is no sufficient budget, then display "Not enough money cost is <COST> budget is <BUDGET>" Example: "Not enough money cost is 20 budget is 15" Note:Quotes are given here for clarification, do not print the quotes. Note: Write a try-catch block for NotNeighborException, but you should do necessary checks such that this exception will never be thrown from the GraphNode functions that you are invoking. Hint: Carefully consider which function to call first to ensure that an exception will never be thrown. |
boolean pickupSpycam(GraphNode node) | Check the node to see if there is a spy cam. If there is a spy cam at that node, remove the spy cam from that node. Also, remove the spy cam name from the Player's list of spy cam names. Otherwise, return false. Note: Make sure to unset the spycam on the GraphNode as well. Increment the number of spy cams remaining. |
void printSpyCamLocations() | Display the names of the locations where Spy Cams were dropped (and are still there).
If there are spy cams at nodes named a, f, and g, the display would show: "Spy cam at a" "Spy cam at f" "Spy cam at g" Note: Quotes are given here for clarification, do not print the quotes. |
You may not add any public methods to the Player class, but you may add private helper methods.
A SpyGraph class outline is also provided for you (see SpyGraph.java). The SpyGraph class has the following constructor and methods. Implement the TODO's and any missing public method implementations in this class.
Constructor | Description |
---|---|
SpyGraph() | Initializes an empty list of GraphNode objects |
Method | Description |
void addGraphNode(String name) | Add a vertex with this label to the list of vertexes. No duplicate vertex names are allowed. |
void addEdge(String v1name, String v2name, int cost) | Adds v2 as a neighbor of v1 and adds v1 as a neighbor of v2. Also sets the cost for each neighbor pair. |
Iterator<GraphNode> iterator() | Return an iterator through all nodes in the SpyGraph |
List<Neighbor> BFS(String start, String end) | Identify path between the start node and end node by performing BFS traversal. Hint: Write your BFS helper companion function recursively. You will need to use multiple Queue data structures as parameters [You may use a List instead of a Queue if that makes the processing easier]. Apart from using a data structure to track neighbors during every level of recursion, you will also need to use another data structure to track the parent node association from the previous level of recursion. Note: This is not the only possible approach to solve this problem. You might be able to achieve an iterative solution using HashMap instead. Apart from these solutions, there still could be an alternate solution to this problem. As long as you follow the BFS order for generating the path, any solution will be accepted. To enable testing of your program with a partial implementation, make sure to return an empty list instead of a null to prevent your program from crashing. |
List<Neighbor> DFS(String start, String end) | Identify path between the start node and end node by performing DFS traversal. While you are storing the DFS traversal result in the List<Neighbor>, if you found that you completed the traversal of a particular path without finding the end node, then you need to remove the predecessor node from the List<Neighbor> before proceeding with trying out the rest of the paths. Hint: Make your companion / helper function's return variable to boolean and set it to true / false when you found the end node. When you write the recursive call, process the returned boolean value appropriately to either keep the found path as such in List<Neighbor> or to delete the last node from List<Neighbor>. To enable testing of your program with a partial implementation, make sure to return an empty list instead of a null to prevent your program from crashing. |
GraphNode getNodeFromName(String name) | Return the GraphNode instance which corresponds to the given vertex name. |
List<Neighbor> Dijkstra(String start, String end) | OPTIONAL: Implements Dijkstra's shortest path list of nodes on path. To enable testing of your program with a partial implementation, make sure to return an empty list instead of a null to prevent your program from crashing. |
GraphNode getRandomNode() | Returns a random node from the Graph. Implementation of this method is provided to you - Do not edit this method. |
You may not add any public methods to the SpyGraph class, but you may add private helper methods.
We have coded the Game
class for you and this will handle much of the game play once you implement the missing classes. At the start of the program, the input files are read and the game parameters and SpyGraph
are initialized. Next, the player is asked for their name and a brief help instruction is provided.
java -cp . Game config1.txt area1.txt Enter the name of your player: Bucky Badger Your random starting location is a Type 'h' at any time for a list of commands. Enter command:
Various areas in Madison are modelled as a graph. Each location represents a vertex or node in the graph and the road connecting between the two locations represent the edge between the nodes. In addition, each road has a toll fee (weight) that should be spent in order to use the road. The player and spy start out at a random spots in the city. As a player, enter your name, and then choose your action to wisely to catch the spy before time expires. At each instant of time, the player has the following set of actions to choose from:
All commands can be activated with the first character. 'budget' prints the money you have remaining to use on moves. 'clock' returns the number of moves remaining. 'drop' places a spycam at your current location if there is one available. 'get NODE' retrieves a spycam from NODE if NODE has a spycam 'location' prints your location 'move NODE' moves you to NODE if possible. 'neighbors' prints all neighbors of your location and the cost to get there. 'onspy' tells you if you are at the same location as the spy and decreases your budget by a prespecified amount 'path NODE' prints three possible paths from your location to NODE using DFS, BFS, and Dijkstra's 'quit' ends the game 'spycams' prints the nubmer of spycams remaining and the locations of placed spycams.
The spy will periodically reveal their location and this will help you to make a better decision when choosing the next course of action to catch the spy.
If you catch the spy, you'll see the win message:
GAME OVER, spy is surrounded. Bucky Badger wins! Spy is at node e Player is at node f
If you don't catch the spy, you'll see this message:
GAME OVER, you did not find the spy, spy wins Spy is at node red_gym Player is at node gordon_commons
To configure different game play, the program requires two input data files entered as command-line arguments. The names of these two files must be included as command-line arguments in your build process. The
A text only file that contains the area information (the graph information), that is, the locations(nodes) and paths(edges). The contents of the area file will follow this form. The NODES section lists the node names and the EDGES section lists the edges between nodes that exist. The Game
class will parse these files for you, but you must have the SpyGraph
complete before this can by completed correctly. Each line following the line "NODES" represent a node in the graph. Each line following "EDGES" specifies an edge between the two nodes
NODES a b EDGES a b 1
The graph described by this area file has two nodes, "a" and "b" and one edge, between "a" and "b" with a cost or weight of 1. That means it will cost 1 unit of your budget to move from a to b or b to a. The graph is undirected and constructed from GraphNode
instances that are linked together according to the edge list.
The config.txt
file gives information about the parameters required for the gameplay.
REVEALSPY 2 MOVES 10 BUDGET 15 SPYCAMS 3 UNIT pound COST 2
To help you understand the game play, we have created several sample runs for you to review.
After you have read this program page and given thought to the problem we suggest the following steps: