I'm working on a program to find a way out of a series of underground tunnels. The LinearStructure Interface and the Location Class were written for me and I wrote the LinearStack and LinearQueue Classes, and they are working fine (as far as I can tell). My problem comes in when I run the getOutOfTunnel method. I get a null pointer method the first time the isExit(Location) method is ran, and I can't figure out why. I've included what I think are the important classes below. Let me know if I should post something else. The nullPointerException is thrown at line 134 of Map.java, which is a call to the method at line 55. Why is there a null pointer? Thanks in advance.
Map.java:
import java.io.*;
import java.util.*;
public class Map {
private int width, height;
private Position[][] map;
private boolean foundExit;
private LinearStructure<Location> steps = null;
public Map (File f) throws IOException {
String line;
StringTokenizer tok;
char temp;
BufferedReader fin = new BufferedReader(new FileReader(f));
tok = new StringTokenizer(fin.readLine());
height = Integer.parseInt(tok.nextToken());
width = Integer.parseInt(tok.nextToken());
map = new Position[getHeight()][getWidth()];
try {
for (int row = 0; row < getHeight(); row++) {
line = fin.readLine();
for (int col = 0; col < getWidth(); col++) {
temp = line.charAt(col);
if (temp == 'D' || temp == 'S' || temp == 'E' || temp == 'T') {
map[row][col] = new Position(temp);
}
else {
throw new InvalidMapException();
}
}
}
fin.close();
}
catch (InvalidMapException ime) {
System.out.println("'" + f + "' Contains An Invalid Character.");
System.out.println("Please Check '" + f + "' And Try Again.");
}
catch (IndexOutOfBoundsException ioobe) {
System.out.println("'" + f + "' Contains A Ragged Map.");
System.out.println("Please Check '" + f + "' And Try Again.");
}
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public boolean isExit(Location pt) {
return (map[pt.getRow()][pt.getColumn()].getType() == 'E');
}
public boolean isStart(Location pt) {
return (map[pt.getRow()][pt.getColumn()].getType() == 'S');
}
public boolean isTraversable(Location pt) {
return (map[pt.getRow()][pt.getColumn()].getType() == 'T');
}
public List<Location> getExits() {
ArrayList<Location> exits = new ArrayList<Location>();
int capacity = 10;
for (int row = 0; row < getHeight(); row++) {
for (int col = 0; col < getWidth(); row++) {
if (exits.size() == capacity) {
exits.ensureCapacity(capacity + 10);
capacity += 10;
}
if (map[row][col].getType() == 'E') {
exits.add(new Location(row, col, null));
}
}
}
exits.trimToSize();
return exits;
}
public Location getStart() {
Location start = null;
int count = 0;
try {
for (int row = 0; row < getHeight(); row++) {
for (int col = 0; col < getWidth(); col++) {
if (map[row][col].getType() == 'S') {
start = new Location(row, col, null);
count++;
}
if (count > 1) {
throw new InvalidMapException();
}
}
}
return start;
}
catch (InvalidMapException ime) {
System.out.println("Map Contained More Than One Start.");
System.out.println("Please Check Data And Try Again.");
return null;
}
}
public boolean hasBeenVisited(Location pt) {
return map[pt.getRow()][pt.getColumn()].beenVisited();
}
public void visit(Location pt) {
map[pt.getRow()][pt.getColumn()].visit();
}
public List<Location> getOutOfTunnel(boolean useStack) {
ArrayList<Location> path = new ArrayList<Location>();
Location start = getStart(), current;
LinearStructure<Location> steps;
int capacity = 10;
if (useStack) {
steps = new LinearStack<Location>();
}
else {
steps = new LinearQueue<Location>();
}
steps.add(getStart());
while (!steps.isEmpty()) {
current = steps.remove();
if (isExit(current)) {
while (current != null) {
if (path.size() == capacity) {
path.ensureCapacity(capacity + 10);
capacity += 10;
}
path.add(0, current);
current = current.getFrom();
}
path.trimToSize();
return path;
}
else if (isTraversable(current) && !hasBeenVisited(current)) {
visit(current);
steps.add(current.getLocation(current, Direction.EAST));
steps.add(current.getLocation(current, Direction.SOUTH));
steps.add(current.getLocation(current, Direction.WEST));
steps.add(current.getLocation(current, Direction.NORTH));
}
}
return path;
}
}
Location.java:
public class Location {
private int row, col;
private Location from;
public Location(int row, int col, Location from) {
this.row = row;
this.col = col;
this.from = from;
}
public String toString() {
return "(" + col + "," + row + ")";
}
public Location getLocation(Location from, Direction d) {
switch(d) {
case EAST: return new Location(row, col+1, from);
case SOUTH: return new Location(row+1, col, from);
case WEST: return new Location(row, col-1, from);
case NORTH: return new Location(row-1, col, from);
default: return null;
}
}
public int getColumn() {
return col;
}
public boolean equals(Object other) {
if(other instanceof Location ){
Location loc = (Location)other;
return loc.row == row && loc.col == col;
}
return false;
}
public Location getFrom() {
return from;
}
public int getRow() {
return row;
}
}
Position.java:
public class Position {
private char type;
private boolean hasBeenVisited;
public Position(char t) {
type = t;
hasBeenVisited = false;
}
public char getType() {
return type;
}
public void visit() {
hasBeenVisited = true;
}
public boolean beenVisited() {
return hasBeenVisited;
}
public String toString() {
return ("" + type);
}
}