Example #1
0
 /**
  * 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));
       }
     }
   }
 }
Example #2
0
  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();
  }