Java 學習記錄85 — I/O Load Big Location and Exits Files — 4/7

張小雄
4 min readOct 16, 2021

--

承 84 — BufferedReader

到本頁最下面的 本篇代碼

下載 directions_big.txt、locations_big.txt

並把代碼裡的文檔路徑更新成這兩個

來比對當數據龐大的時候,我們從文檔寫跟讀和當初寫在代碼裡的差異

輸出結果:

YOU ARE STANDING AT THE END OF A ROAD BEFORE A SMALL BRICK BUILDING. AROUND YOU IS A FOREST. A SMALL STREAM FLOWS OUT OF THE BUILDING AND DOWN A GULLY.

Available exits are Q, S, D, U, E, W, N,

s

YOU ARE IN A VALLEY IN THE FOREST BESIDE A STREAM TUMBLING ALONG A ROCKY BED.

Available exits are Q, S, D, E, U, W, N,

e

YOU ARE IN OPEN FOREST, WITH A DEEP VALLEY TO ONE SIDE.

Available exits are Q, S, D, E, W, N,

d

YOU ARE IN A VALLEY IN THE FOREST BESIDE A STREAM TUMBLING ALONG A ROCKY BED.

Available exits are Q, S, D, E, U, W, N,

e

YOU ARE IN OPEN FOREST, WITH A DEEP VALLEY TO ONE SIDE.

Available exits are Q, S, D, E, W, N,

w

YOU ARE IN OPEN FOREST, WITH A DEEP VALLEY TO ONE SIDE.

Available exits are Q, S, D, E, W, N,

n

YOU ARE IN OPEN FOREST NEAR BOTH A VALLEY AND A ROAD.

Available exits are Q, S, D, E, W, N,

e

YOU ARE IN A VALLEY IN THE FOREST BESIDE A STREAM TUMBLING ALONG A ROCKY BED.

Available exits are Q, S, D, E, U, W, N,

u

YOU ARE IN OPEN FOREST, WITH A DEEP VALLEY TO ONE SIDE.

Available exits are Q, S, D, E, W, N,

q

YOU ARE SITTING IN FRONT OF A COMPUTER LEARNING JAVA.

Tim 說這是當初 colossal cave adventure game 的資料

而為什麼敘述都是大寫的呢?

因為在當時 1970 年代的 terminal 只能輸出大寫

真是一款上古遊戲呢!

當時的電腦玩家用 terminal 玩遊戲,還真強 = =

小挑戰:

static 裡的兩個讀檔文件改成 try-with-resources

補充: Java try-with-resources examples

參考答案:

//         read locations.txt with try-with-resources
try (Scanner scanner = new Scanner(new FileReader("src/introduceIo/locations_big.txt"))) {
scanner.useDelimiter(",");
while (scanner.hasNext()) {
int locInt = scanner.nextInt();
scanner.skip(scanner.delimiter());
String description = scanner.nextLine();
Map<String, Integer> tempExit = new HashMap<>();
locations.put(locInt, new Location(locInt, description, tempExit));
}
} catch (IOException e) {
e.printStackTrace();
}
// read directions.txt with try-with-resources
try (Scanner scanner = new Scanner(new BufferedReader(new FileReader("src/introduceIo/directions_big.txt")))) {
while (scanner.hasNextLine()) {
String input = scanner.nextLine();
String[] data = input.split(",");
int loc = Integer.parseInt(data[0]);
String direction = data[1];
int destination = Integer.parseInt(data[2]);
Location location = locations.get(loc);
location.addExit(direction, destination);
}
} catch (IOException e) {
e.printStackTrace();
}

還能這樣寫

//        read directions.txt with try-with-resources version 2        try (BufferedReader dirFile = new BufferedReader(new FileReader("src/introduceIo/directions_big.txt"))) {
String input;
while ((input = dirFile.readLine())!=null) {
String[] data = input.split(",");
int loc = Integer.parseInt(data[0]);
String direction = data[1];
int destination = Integer.parseInt(data[2]);
Location location = locations.get(loc);
location.addExit(direction, destination);
}
} catch (IOException e) {
e.printStackTrace();
}

不過比較起來,感覺還是 Scanner 比較簡單好用

小挑戰:

1.將剩下的讀取跟寫入都改成 BufferedReader

2.修改寫入,不要把出口 Q 也寫進去,讓寫入的結果跟原來的 directions_big.txt 內容一樣

ps.可把 Locations、Location 的 Hashmap 改成 LinkedHashMap 也可不改

參考答案:

Location.java

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>();
}
}

Locations.java

private static Map<Integer, Location> locations = new LinkedHashMap<Integer, Location>();

public static void main(String[] args) throws IOException {
try (BufferedWriter file = new BufferedWriter(new FileWriter("src/introduceIo/locations_big.txt"));
BufferedWriter dirFile = new BufferedWriter(new FileWriter("src/introduceIo/directions_big.txt"))) {
for (Location location : locations.values()) {
file.write(location.getLocationID() + "," + location.getDescription() + "\n");
for (String direction : location.getExits().keySet()) {
dirFile.write(location.getLocationID() + "," + direction + "," + location.getExits().get(direction) + "\n");
}
}
}
}

static {
try (Scanner scanner = new Scanner(new BufferedReader(new FileReader("src/introduceIo/locations_big.txt")))) {
scanner.useDelimiter(",");
while (scanner.hasNext()) {
int locInt = scanner.nextInt();
scanner.skip(scanner.delimiter());
String description = scanner.nextLine();
Map<String, Integer> tempExit = new HashMap<>();
locations.put(locInt, new Location(locInt, description, tempExit));
}
} catch (IOException e) {
e.printStackTrace();
}
}

Main.java

package introduceIo;import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Scanner;
public class Main {
private static Locations locations = new Locations();
public static void main(String[] args) {
// 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");
int loc = 1;
while (true) {
System.out.println(locations.get(loc).getDescription());
if (loc == 0) {
break;
}
Map<String, Integer> exits = new LinkedHashMap<String, Integer>();
exits.put("Q", 0);
exits.putAll(locations.get(loc).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)) {
loc = exits.get(direction);
} else {
System.out.println("You cannot go in that direction");
}
}
}
}

本篇代碼

--

--

張小雄
張小雄

Written by 張小雄

記錄成為軟體工程師的過程

No responses yet