/** * Cache the {@link Line2D} objects making up the maze. * * @param x Initial x coordinate. * @param y Initial y coordinate. * @param width Width of a cell. * @param height Height of a cell. */ private void buildWalls(double x, double y, double width, double height) { Point p = maze.getSize(); wallList = new ArrayList(p.getX() * p.getY()); for (int i = 0; i < p.getY(); i++) { for (int j = 0; j < p.getX(); j++) { Cell cell = maze.getCell(new Point(j, i)); if (cell.isWall(Direction.North)) { wallList.add( new Line2D.Double( x + j * width, y + (i + 1) * height, x + (j + 1) * width, y + (i + 1) * height)); } if (cell.isWall(Direction.East)) { wallList.add( new Line2D.Double( x + (j + 1) * width, y + i * height, x + (j + 1) * width, y + (i + 1) * height)); } } } }
public void paintComponent(Graphics g) { super.paintComponent(g); // paint background Graphics2D g2 = (Graphics2D) g; // Turn on antialiasing Map m = new HashMap(); m.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.addRenderingHints(m); // Figure out how large the maze is Point p = maze.getSize(); double llx = 0.0, lly = 0.0, width = 0.0, height = 0.0, cellwidth = 0.0, cellheight = 0.0; // Do we need to update our cache? if ((panelSize == null) || (panelSize != getSize())) { panelSize = getSize(); llx = (double) panelSize.width * 0.025; lly = (double) panelSize.height * 0.025; width = (double) panelSize.width - (double) panelSize.width * 0.05; height = (double) panelSize.height - (double) panelSize.height * 0.05; cellwidth = width / (double) p.getX(); cellheight = height / (double) p.getY(); buildWalls(llx, lly, cellwidth, cellheight); double diameter = java.lang.Math.min(cellwidth, cellheight) * 0.75; player = new Arc2D.Double( new Rectangle2D.Double(-diameter / 2.0, -diameter / 2.0, diameter, diameter), 30.0, 300.0, Arc2D.PIE); diameter = java.lang.Math.min(cellwidth, cellheight) * 0.30; projectile = new Arc2D.Double( new Rectangle2D.Double(-diameter / 2.0, -diameter / 2.0, diameter, diameter), 0.0, 360.0, Arc2D.PIE); } // Flip coordinate system g2.translate(0.0, (double) panelSize.height); g2.scale(1.0, -1.0); // Draw the maze walls g2.setStroke(new BasicStroke(2.0f)); g2.setColor(Color.black); g2.draw(new Rectangle2D.Double(llx, lly, width, height)); Iterator it = wallList.iterator(); while (it.hasNext()) { Object o = it.next(); if (o instanceof Shape) { g2.draw((Shape) o); } else { throw new Error(); } } Font font = new Font("Arial", Font.PLAIN, 9); FontRenderContext frc = g2.getFontRenderContext(); // Obtain the location of the distinguished client Point cp = maze.getClientPoint(client); for (int i = 0; i < p.getY(); i++) { for (int j = 0; j < p.getX(); j++) { boolean cellVisible = true; Line2D visLine = new Line2D.Double( llx + (cp.getX() + 0.5) * cellwidth, lly + (cp.getY() + 0.5) * cellheight, llx + (j + 0.5) * cellwidth, lly + (i + 0.5) * cellheight); /* Visibility testing */ /* Iterator visIt = wallList.iterator(); while(visIt.hasNext()) { Object o = visIt.next(); if(o instanceof Line2D) { Line2D l = (Line2D)o; if(l.intersectsLine(visLine)) { cellVisible = false; } } else { throw new Error(); } } */ if (cellVisible) { Cell cell = maze.getCell(new Point(j, i)); Object o = cell.getContents(); if (o != null) { if (o instanceof Client) { Client c = (Client) o; if (c instanceof GUIClient) { g2.setColor(Color.green); } else if (c instanceof RobotClient) { g2.setColor(Color.red); } else if (c instanceof RemoteClient) { g2.setColor(Color.magenta); } double xoffset = llx + j * cellwidth + (cellwidth / 2.0); double yoffset = lly + i * cellheight + (cellheight / 2.0); Direction orient = c.getOrientation(); g2.translate(xoffset, yoffset); double rotation = 0.0; if (orient.equals(Direction.South)) { rotation = -java.lang.Math.PI / 2.0; } else if (orient.equals(Direction.North)) { rotation = java.lang.Math.PI / 2.0; } else if (orient.equals(Direction.West)) { rotation = java.lang.Math.PI; } g2.rotate(rotation); g2.fill(player); g2.rotate(-rotation); GlyphVector name = font.createGlyphVector(frc, c.getName()); g2.scale(1.0, -1.0); g2.setColor(Color.black); g2.drawGlyphVector(name, 0.0f, 0.0f); g2.scale(1.0, -1.0); g2.translate(-xoffset, -yoffset); } else { if (o instanceof Projectile) { g2.setColor(Color.yellow); double xoffset = llx + j * cellwidth + (cellwidth / 2.0); double yoffset = lly + i * cellheight + (cellheight / 2.0); g2.translate(xoffset, yoffset); g2.fill(projectile); g2.translate(-xoffset, -yoffset); } } } } } } }
/** * Implements a Depth First Search on a Maze Object * * @param myMaze * @return */ public static char[] depthFirstSearch(Maze myMaze) { // For breadth-first search Stack<MazeCell> frontier = new Stack<MazeCell>(); // Add the Starting State frontier.add(myMaze.getCell(myMaze.getStartX(), myMaze.getStartY())); while (!frontier.isEmpty()) { // Get the Top Node MazeCell currentNode = frontier.pop(); if (currentNode.getVisited() == true) { continue; } // Mark the current node as visited currentNode.setVisited(); nodesExpanded += 1; int currentX = currentNode.getX(); int currentY = currentNode.getY(); // Reached the Goal State if ((currentX == myMaze.getGoalX()) && (currentY == myMaze.getGoalY())) { return myMaze.getCell(currentX, currentY).getPath().toCharArray(); } // Go Rightwards (0) if ((!myMaze.getCell(currentX, currentY + 1).isWall()) && (!myMaze.getCell(currentX, currentY + 1).getVisited())) { // Add to the Frontier frontier.add(myMaze.getCell(currentX, currentY + 1)); // Adjust it's Path myMaze .getCell(currentX, currentY + 1) .appendPath(myMaze.getCell(currentX, currentY).getPath() + "0"); } // Go Downwards (1) if ((!myMaze.getCell(currentX + 1, currentY).isWall()) && (!myMaze.getCell(currentX + 1, currentY).getVisited())) { // Add to the Frontier frontier.add(myMaze.getCell(currentX + 1, currentY)); // Adjust it's Path myMaze .getCell(currentX + 1, currentY) .appendPath(myMaze.getCell(currentX, currentY).getPath() + "1"); } // Go Leftwards (2) if ((!myMaze.getCell(currentX, currentY - 1).isWall()) && (!myMaze.getCell(currentX, currentY - 1).getVisited())) { // Add to the Frontier frontier.add(myMaze.getCell(currentX, currentY - 1)); // Adjust it's Path myMaze .getCell(currentX, currentY - 1) .appendPath(myMaze.getCell(currentX, currentY).getPath() + "2"); } // Go Upwards (3) if ((!myMaze.getCell(currentX - 1, currentY).isWall()) && (!myMaze.getCell(currentX - 1, currentY).getVisited())) { // Add to the Frontier frontier.add(myMaze.getCell(currentX - 1, currentY)); // Adjust it's Path myMaze .getCell(currentX - 1, currentY) .appendPath(myMaze.getCell(currentX, currentY).getPath() + "3"); } } return null; }
/** * Implements an A-Star Search on a Maze Object * * @param myMaze * @return */ public static char[] aStarSearch(Maze myMaze) { // For Greedy Best First Search List<MazeCell> frontier = new LinkedList<MazeCell>(); // Add the Starting State frontier.add(myMaze.getCell(myMaze.getStartX(), myMaze.getStartY())); // Store the current Coordinates int currentX = 0, currentY = 0; while (!frontier.isEmpty()) { // Remove the best node based on heuristic path cost and current path cost int currentNodeIndex = getIndexWithSmallestCurrentPath(frontier); MazeCell currentNode = frontier.remove(currentNodeIndex); // Check if this node has been visited if (currentNode.getVisited() == true) { continue; } // Move the Ghost // myMaze.scaryGhost.move(); // Mark the current node as visited currentNode.setVisited(); // Obtain the current coordinates currentX = currentNode.getX(); currentY = currentNode.getY(); // myMaze.getCell(myMaze.scaryGhost.getGhostX(), myMaze.scaryGhost.getGhostY()).setWall(true); // The ghost is in the same place if ((currentX == myMaze.scaryGhost.getGhostX()) && (currentY == myMaze.scaryGhost.getGhostY())) { continue; } // Reached the Goal State if ((currentX == myMaze.getGoalX()) && (currentY == myMaze.getGoalY())) { return myMaze.getCell(myMaze.getGoalX(), myMaze.getGoalY()).getPath().toCharArray(); } // Increase the number of Expanded Nodes nodesExpanded += 1; // Initial values of heuristics int heuristicRight = Integer.MAX_VALUE, heuristicLeft = Integer.MAX_VALUE, heuristicUp = Integer.MAX_VALUE, heuristicDown = Integer.MAX_VALUE; // Go Rightwards (0) if ((!myMaze.getCell(currentX, currentY + 1).isWall()) && (!myMaze.getCell(currentX, currentY + 1).getVisited())) { // Obtain the heuristic // heuristicRight = manhattan(myMaze.getGoalX(), myMaze.getGoalY(), currentX, currentY+1); heuristicRight = estimatedManhattan( myMaze.getCell(currentX, currentY + 1), myMaze.getGoalX(), myMaze.getGoalY()); // Adjust the Path myMaze .getCell(currentX, currentY + 1) .appendPath(myMaze.getCell(currentX, currentY).getPath() + "0"); // Set the Heuristic myMaze.getCell(currentX, currentY + 1).setHeuristicDistance(heuristicRight); // Find the current path cost int currentDistanceCost = pathCost(myMaze.getCell(currentX, currentY + 1).getPath().toCharArray()); // Set the Current Path Distance myMaze.getCell(currentX, currentY + 1).setCurrentDistanceCost(currentDistanceCost); } // Go Downwards (1) if ((!myMaze.getCell(currentX + 1, currentY).isWall()) && (!myMaze.getCell(currentX + 1, currentY).getVisited())) { // Obtain the Heuristic // heuristicDown = manhattan(myMaze.getGoalX(), myMaze.getGoalY(), currentX+1, currentY); heuristicDown = estimatedManhattan( myMaze.getCell(currentX + 1, currentY), myMaze.getGoalX(), myMaze.getGoalY()); // Adjust the Path myMaze .getCell(currentX + 1, currentY) .appendPath(myMaze.getCell(currentX, currentY).getPath() + "1"); // Set the Heuristic myMaze.getCell(currentX + 1, currentY).setHeuristicDistance(heuristicDown); // Find the current path cost int currentDistanceCost = pathCost(myMaze.getCell(currentX + 1, currentY).getPath().toCharArray()); // Set the Current Path Distance myMaze.getCell(currentX + 1, currentY).setCurrentDistanceCost(currentDistanceCost); } // Go Leftwards (2) if ((!myMaze.getCell(currentX, currentY - 1).isWall()) && (!myMaze.getCell(currentX, currentY - 1).getVisited())) { // Obtain the Heuristic // heuristicLeft = manhattan(myMaze.getGoalX(), myMaze.getGoalY(), currentX, currentY-1); heuristicLeft = estimatedManhattan( myMaze.getCell(currentX, currentY - 1), myMaze.getGoalX(), myMaze.getGoalY()); // Adjust the Path myMaze .getCell(currentX, currentY - 1) .appendPath(myMaze.getCell(currentX, currentY).getPath() + "2"); // Set the Heuristic myMaze.getCell(currentX, currentY - 1).setHeuristicDistance(heuristicLeft); // Find the current path cost int currentDistanceCost = pathCost(myMaze.getCell(currentX, currentY - 1).getPath().toCharArray()); // Set the Current Path Distance myMaze.getCell(currentX, currentY - 1).setCurrentDistanceCost(currentDistanceCost); } // Go Upwards (3) if ((!myMaze.getCell(currentX - 1, currentY).isWall()) && (!myMaze.getCell(currentX - 1, currentY).getVisited())) { // Obtain the Heuristic // heuristicUp = manhattan(myMaze.getGoalX(), myMaze.getGoalY(), currentX-1, currentY); heuristicUp = estimatedManhattan( myMaze.getCell(currentX - 1, currentY), myMaze.getGoalX(), myMaze.getGoalY()); // Adjust the Path myMaze .getCell(currentX - 1, currentY) .appendPath(myMaze.getCell(currentX, currentY).getPath() + "3"); // Set the Heuristic myMaze.getCell(currentX - 1, currentY).setHeuristicDistance(heuristicUp); // Find the current path cost int currentDistanceCost = pathCost(myMaze.getCell(currentX - 1, currentY).getPath().toCharArray()); // Set the Current Path Distance myMaze.getCell(currentX - 1, currentY).setCurrentDistanceCost(currentDistanceCost); } // Add the Neighbors to the frontier if (heuristicRight != Integer.MAX_VALUE) { frontier.add(myMaze.getCell(currentX, currentY + 1)); } if (heuristicDown != Integer.MAX_VALUE) { frontier.add(myMaze.getCell(currentX + 1, currentY)); } if (heuristicLeft != Integer.MAX_VALUE) { frontier.add(myMaze.getCell(currentX, currentY - 1)); } if (heuristicUp != Integer.MAX_VALUE) { frontier.add(myMaze.getCell(currentX - 1, currentY)); } // myMaze.getCell(myMaze.scaryGhost.getGhostX(), // myMaze.scaryGhost.getGhostY()).setWall(false); } return myMaze.getCell(myMaze.getGoalX(), myMaze.getGoalY()).getPath().toCharArray(); }
/** * Implements a Greedy Best First Search on a Maze Object * * @param myMaze * @return */ public static char[] greedyBestFirstSearch(Maze myMaze) { // For Greedy Best First Search Stack<MazeCell> frontier = new Stack<MazeCell>(); // Add the Starting State frontier.add(myMaze.getCell(myMaze.getStartX(), myMaze.getStartY())); // Store the current Co-ordinates int currentX = 0, currentY = 0; while (!frontier.isEmpty()) { // Get the Top Node MazeCell currentNode = frontier.pop(); // Check if this node has been visited if (currentNode.getVisited() == true) { continue; } // Mark the current node as visited currentNode.setVisited(); // Obtain the current cordinates currentX = currentNode.getX(); currentY = currentNode.getY(); // Reached the Goal State if ((currentX == myMaze.getGoalX()) && (currentY == myMaze.getGoalY())) { return myMaze.getCell(myMaze.getGoalX(), myMaze.getGoalY()).getPath().toCharArray(); } // Increase the number of Expanded Nodes nodesExpanded += 1; // Check that you're not out of Bounds if (currentX <= 0 || currentY <= 0 || currentX >= myMaze.getHeight() - 1 || currentY >= myMaze.getWidth() - 1) { continue; } // Initial values of heuristics int heuristicRight = Integer.MAX_VALUE, heuristicLeft = Integer.MAX_VALUE, heuristicUp = Integer.MAX_VALUE, heuristicDown = Integer.MAX_VALUE; // Go Rightwards (0) if ((!myMaze.getCell(currentX, currentY + 1).isWall()) && (!myMaze.getCell(currentX, currentY + 1).getVisited())) { // Obtain the heuristic heuristicRight = manhattan(myMaze.getGoalX(), myMaze.getGoalY(), currentX, currentY + 1); // Adjust the Path myMaze .getCell(currentX, currentY + 1) .appendPath(myMaze.getCell(currentX, currentY).getPath() + "0"); // Set the Heuristic myMaze.getCell(currentX, currentY + 1).setHeuristicDistance(heuristicRight); } // Go Downwards (1) if ((!myMaze.getCell(currentX + 1, currentY).isWall()) && (!myMaze.getCell(currentX + 1, currentY).getVisited())) { heuristicDown = manhattan(myMaze.getGoalX(), myMaze.getGoalY(), currentX + 1, currentY); myMaze .getCell(currentX + 1, currentY) .appendPath(myMaze.getCell(currentX, currentY).getPath() + "1"); myMaze.getCell(currentX + 1, currentY).setHeuristicDistance(heuristicDown); } // Go Leftwards (2) if ((!myMaze.getCell(currentX, currentY - 1).isWall()) && (!myMaze.getCell(currentX, currentY - 1).getVisited())) { heuristicLeft = manhattan(myMaze.getGoalX(), myMaze.getGoalY(), currentX, currentY - 1); myMaze .getCell(currentX, currentY - 1) .appendPath(myMaze.getCell(currentX, currentY).getPath() + "2"); myMaze.getCell(currentX, currentY - 1).setHeuristicDistance(heuristicLeft); } // Go Upwards (3) if ((!myMaze.getCell(currentX - 1, currentY).isWall()) && (!myMaze.getCell(currentX - 1, currentY).getVisited())) { heuristicUp = manhattan(myMaze.getGoalX(), myMaze.getGoalY(), currentX - 1, currentY); myMaze .getCell(currentX - 1, currentY) .appendPath(myMaze.getCell(currentX, currentY).getPath() + "3"); myMaze.getCell(currentX - 1, currentY).setHeuristicDistance(heuristicUp); } // Used to Sort the Values ArrayList<MazeCell> myNeighbors = new ArrayList<MazeCell>(); if (heuristicRight != Integer.MAX_VALUE) { myNeighbors.add(myMaze.getCell(currentX, currentY + 1)); } if (heuristicDown != Integer.MAX_VALUE) { myNeighbors.add(myMaze.getCell(currentX + 1, currentY)); } if (heuristicLeft != Integer.MAX_VALUE) { myNeighbors.add(myMaze.getCell(currentX, currentY - 1)); } if (heuristicUp != Integer.MAX_VALUE) { myNeighbors.add(myMaze.getCell(currentX - 1, currentY)); } // Sort the Cells based on Heuristic Values myNeighbors = sortNeighbors(myNeighbors); // Add the Cells to the Frontier in the Sorted Order for (MazeCell temp : myNeighbors) { if (temp.getHeuristicDistance() != Integer.MAX_VALUE) { frontier.add(temp); } } } return myMaze.getCell(myMaze.getGoalX(), myMaze.getGoalY()).getPath().toCharArray(); }