请找到随附的Java代码。我无法修复和执行代码。如果我执行Locations.java,则不会出现错误消息,
在main(MainAdventure.java:30)
在Locations.getLocation(Locations.java:96)
如果我执行MainAdventure.java,则会得到空指针异常。 我尝试调试但没有帮助。有人可以指导我吗?
MainAdventure.java
public class MainAdventure {
private static Locations locations = new Locations();
public static void main(String[] args) throws IOException {
/*
* Change the program to allow players to type full words, or phrases, then move
* to the correct location based upon their input. The player should be able to
* type commands such as "Go West", "run South", or just "East" and the program
* will move to the appropriate location if there is one. As at present, an
* attempt to move in an invalid direction should print a message and remain in
* the same place.
*
* Single letter commands (N, W, S, E, Q) should still be available.
*/
Scanner scanner = new Scanner(System.in);
Map<String, String> vocabulary = new HashMap<String, String>();
vocabulary.put("QUIT", "Q");
vocabulary.put("NORTH", "N");
vocabulary.put("SOUTH", "S");
vocabulary.put("WEST", "W");
vocabulary.put("EAST", "E");
Location currentLocation = locations.getLocation(1);
while (true) {
System.out.println(currentLocation.getDescription());
if (currentLocation.getLocationID() == 0) {
break;
}
Map<String, Integer> exits = currentLocation.getExits();
System.out.print("Available exits are ");
for (String exit : exits.keySet()) {
System.out.print(exit + ", ");
}
System.out.println();
String direction = scanner.nextLine().toUpperCase();
if (direction.length() > 1) {
String[] words = direction.split(" ");
for (String word : words) {
if (vocabulary.containsKey(word)) {
direction = vocabulary.get(word);
break;
}
}
}
if (exits.containsKey(direction)) {
currentLocation = locations.getLocation(currentLocation.getExits().get(direction));
} else {
System.out.println("You cannot go in that direction");
}
}
locations.close();
}
}
Locations.java
public class Locations implements Map<Integer, Location> {
private static Map<Integer, Location> locations = new LinkedHashMap<Integer, Location>();
private static Map<Integer, IndexRecord> index = new LinkedHashMap<>();
private static RandomAccessFile ra;
public static void main(String[] args) throws IOException {
try (RandomAccessFile rao = new RandomAccessFile("locations_rand.dat", "rwd")) {
rao.writeInt(locations.size());
int indexSize = locations.size() * 3 * Integer.BYTES;
int locationStart = (int) (indexSize + rao.getFilePointer() + Integer.BYTES);
rao.writeInt(locationStart);
long indexStart = rao.getFilePointer();
int startPointer = locationStart;
rao.seek(startPointer);
for (Location location : locations.values()) {
rao.writeInt(location.getLocationID());
rao.writeUTF(location.getDescription());
StringBuilder builder = new StringBuilder();
for (String direction : location.getExits().keySet()) {
if (!direction.equalsIgnoreCase("Q")) {
builder.append(direction);
builder.append(",");
builder.append(location.getExits().get(direction));
builder.append(",");
}
}
rao.writeUTF(builder.toString());
IndexRecord record = new IndexRecord(startPointer, (int) (rao.getFilePointer() - startPointer));
index.put(location.getLocationID(), record);
startPointer = (int) rao.getFilePointer();
}
rao.seek(indexStart);
for (Integer locationID : index.keySet()) {
rao.writeInt(locationID);
rao.writeInt(index.get(locationID).getStartByte());
rao.writeInt(index.get(locationID).getLength());
}
}
}
// 1. This first four bytes will contain the number of locations (bytes 0-3)
// 2. The next four bytes will contain the start offset of the locations section
// (bytes 4-7)
// 3. The next section of the file will contain the index (the index is 1692
// bytes long. It will start at byte 8 and end at byte 1699
// 4. The final section of the file will contain the location records (the
// data). It will start at byte 1700
static {
try {
ra = new RandomAccessFile("locations_rand.dat", "rwd");
int numLocations = ra.readInt();
long locationStartPoint = ra.readInt();
while (ra.getFilePointer() < locationStartPoint) {
int locationId = ra.readInt();
int locationStart = ra.readInt();
int locationLength = ra.readInt();
IndexRecord record = new IndexRecord(locationStart, locationLength);
index.put(locationId, record);
}
} catch (IOException e) {
System.out.println("IOException in static initializer: " + e.getMessage());
}
}
public Location getLocation(int locationId) throws IOException {
IndexRecord record = index.get(locationId);
ra.seek(record.getStartByte());
int id = ra.readInt();
String description = ra.readUTF();
String exits = ra.readUTF();
String[] exitPart = exits.split(",");
Location location = new Location(locationId, description, null);
if (locationId != 0) {
for (int i = 0; i < exitPart.length; i++) {
System.out.println("exitPart = " + exitPart[i]);
System.out.println("exitPart[+1] = " + exitPart[i + 1]);
String direction = exitPart[i];
int destination = Integer.parseInt(exitPart[++i]);
location.addExit(direction, destination);
}
}
return location;
}
@Override
public int size() {
return locations.size();
}
@Override
public boolean isEmpty() {
return locations.isEmpty();
}
@Override
public boolean containsKey(Object key) {
return locations.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return locations.containsValue(value);
}
@Override
public Location get(Object key) {
return locations.get(key);
}
@Override
public Location put(Integer key, Location value) {
return locations.put(key, value);
}
@Override
public Location remove(Object key) {
return locations.remove(key);
}
@Override
public void putAll(Map<? extends Integer, ? extends Location> m) {
}
@Override
public void clear() {
locations.clear();
}
@Override
public Set<Integer> keySet() {
return locations.keySet();
}
@Override
public Collection<Location> values() {
return locations.values();
}
@Override
public Set<Entry<Integer, Location>> entrySet() {
return locations.entrySet();
}
public void close() throws IOException {
ra.close();
}
}
Location.java
public class Location implements Serializable {
private final int locationID;
private final String description;
private final Map<String, Integer> exits;
private long serialVersionUID = 1L;
public Location(int locationID, String description, Map<String, Integer> exits) {
this.locationID = locationID;
this.description = description;
if (exits != null) {
this.exits = new LinkedHashMap<String, Integer>(exits);
} else {
this.exits = new LinkedHashMap<String, Integer>();
}
this.exits.put("Q", 0);
}
public int getLocationID() {
return locationID;
}
public String getDescription() {
return description;
}
public Map<String, Integer> getExits() {
return new LinkedHashMap<String, Integer>(exits);
}
protected void addExit(String direction, int location) {
exits.put(direction, location);
}
}
我发现的错误似乎是由方法ra.seek(record.getStartByte());
;中Locations
类中的getLocation(int locationId)
引起的。
Here是 .dat 文件。