/**
 * A maze set on a rectangular grid. 
 *
 */
public class Maze {
  private Room[][] rooms;
  private int rows, cols;
  private int size;
  private Room start;
  /**
   * Create a new maze from the given map. The maze has a room for
   * each position in the map with a positive value. A room has
   * symmetric exits to adjacent rooms, that is, rooms whose row or
   * column differs by one from the rooms row and column, but not
   * both.
   *
   * @param map matrix of zeros (no room) and ones (room)
   * @param startRow row of the starting room
   * @param startCol column of the starting room
   */
  public Maze(int [][] map, int startRow, int startCol) {
    rows = map.length;
    if (rows > 0)
      cols = map[0].length;
    if (startRow < 0 || startCol < 0 ||
        startRow >= rows || startCol >= cols ||
        map[startRow][startCol] == 0)
      throw new IllegalArgumentException("No room at that location");   
    rooms = new Room[rows][cols];
    for (int r = 0; r < rows; r++)
      for (int c = 0; c < cols; c++)
        if (map[r][c] > 0) {
          rooms[r][c] = new Room("(" + r + "," + c +")");
          size++;
          //Check if there's a room above. If so, link to this room
          if (r > 0 && map[r-1][c] > 0)
            rooms[r][c].linkRooms(rooms[r-1][c], Direction.NORTH);
          //Check if there's a room on its left. If so, link to this room
          if (c > 0 && map[r][c-1] > 0)
            rooms[r][c].linkRooms(rooms[r][c-1], Direction.WEST);
        }
    start = rooms[startRow][startCol];
  }
  /**
   * Get the room at the specified row and column. If there is no room
   * at that position, return <code>null</code>.
   *
   * @param r row
   * @param c column
   * @return the room at that row and column
   */
  public Room getRoomAt(int r, int c) {
    return rooms[r][c];
  }
  /**
   * How many actual rooms in this maze.
   *
   * @return the number of rooms in the maze
   */
  public int numberOfRooms() {
    return size;
  }
  /**
   * Get the starting room for the maze.
   *
   * @return the starting room
   */
  public Room getStartingRoom() {
    return start;
  }
}
