
本文详解如何安全地将玩家当前得分与本地文件中的历史最高分比较,并在必要时更新文件,避免因流未重置导致的 NoSuchElementException 等运行时异常。
本文详解如何安全地将玩家当前得分与本地文件中的历史最高分比较,并在必要时更新文件,避免因流未重置导致的 `nosuchelementexception` 等运行时异常。
在 Java 蛇游戏开发中,实现高分持久化是提升用户体验的关键一环。但直接复用已关闭或未重置的输入流(如 FileInputStream)会导致 NoSuchElementException——正如你在 highScoreChecker() 方法中遇到的问题:当成功写入新高分后,尝试用同一未重置的 Scanner 和已关闭的 fileByteStream 再次读取文件,必然失败。
根本原因在于:
- FileInputStream 是一次性流,读取完毕或关闭后无法重复使用;
- Scanner 依赖底层流,流关闭后 inFS.nextInt() 将抛出异常;
- 你未在写入后重新打开文件流,却试图用旧 Scanner 继续读取。
✅ 正确做法是:每次读写都独立打开并关闭流,确保资源隔离、状态清晰。以下是优化后的 highScoreChecker() 方法(含完整异常处理与资源管理):
public int highScoreChecker() {
int currentHighScore = 0;
// Step 1: 读取现有高分(安全封装 try-with-resources)
try (Scanner fileScanner = new Scanner(new FileInputStream("HighScore.txt"))) {
if (fileScanner.hasNextInt()) {
currentHighScore = fileScanner.nextInt();
}
} catch (FileNotFoundException e) {
// 文件不存在 → 视为首次运行,高分为 0
System.out.println("HighScore.txt not found. Initializing high score to 0.");
}
// Step 2: 比较并更新(仅当当前分数更高时)
if (applesEaten > currentHighScore) {
try (FileWriter writer = new FileWriter("HighScore.txt")) {
writer.write(String.valueOf(applesEaten));
System.out.println("New high score saved: " + applesEaten);
return applesEaten; // 更新后返回新高分
} catch (IOException e) {
System.err.println("Failed to write high score: " + e.getMessage());
return currentHighScore; // 写入失败,返回原高分
}
}
return currentHighScore;
}? 关键改进说明:
立即学习“Java免费学习笔记(深入)”;
- ✅ 使用 try-with-resources 自动关闭 Scanner 和 FileWriter,杜绝资源泄漏;
- ✅ 移除对 fileByteStream 和 inFS 的跨作用域复用,每次操作新建独立流;
- ✅ 增加 hasNextInt() 校验,防止空文件或格式错误引发 InputMismatchException;
- ✅ 对 FileNotFoundException 做合理降级处理(初始化为 0),提升健壮性;
- ✅ 将高分逻辑与 UI 解耦,highScoreChecker() 仅负责计算与持久化,返回值供 gameOver() 或 draw() 调用显示。
? 额外建议:
- 在 gameOver() 中调用 highScoreChecker() 并缓存结果,避免每帧重复读写;
- 可扩展为读取/写入 JSON 或 Properties 文件,支持多玩家或时间戳;
- 生产环境推荐使用 java.nio.file(如 Files.readString() / Files.writeString())替代传统流,代码更简洁。
通过以上重构,你的蛇游戏不仅能稳定保存高分,还能优雅应对文件缺失、权限不足等边界场景,真正实现“一次编写,稳定运行”。



















