如何将游戏关卡高分文件按分数从高到低排序并重写
Hey there, let's solve this high score sorting issue step by step. We'll break the problem into three key parts: reading and parsing the score file, sorting the entries, and rewriting the sorted scores back to the original file. Here's a practical, maintainable implementation tailored to your existing code:
1. Create a Score Entry Class
First, we need a simple class to hold player names and their scores—this makes sorting straightforward:
class ScoreEntry implements Comparable<ScoreEntry> { private final String playerName; private final int score; public ScoreEntry(String playerName, int score) { this.playerName = playerName.trim(); this.score = score; } // Getters public String getPlayerName() { return playerName; } public int getScore() { return score; } // Implement descending sort (highest score first) @Override public int compareTo(ScoreEntry other) { // Reverse the default ascending order for descending sort return Integer.compare(other.score, this.score); // Optional: Tiebreaker by player name (ascending) if scores are equal // if (other.score != this.score) return Integer.compare(other.score, this.score); // return this.playerName.compareTo(other.playerName); } }
2. Read and Parse the Score File
Next, we'll read the level's high score file, skip the header comments, and extract valid score entries:
private List<ScoreEntry> readScores(int levelID) throws IOException { List<ScoreEntry> scores = new ArrayList<>(); File scoreFile = new File("Scoreboard/Level_" + levelID + "_Highscore.txt"); if (!scoreFile.exists()) { return scores; // Return empty list if file doesn't exist yet } // Use try-with-resources to auto-close the reader try (BufferedReader reader = new BufferedReader(new FileReader(scoreFile))) { String line; while ((line = reader.readLine()) != null) { line = line.trim(); // Skip empty lines and the header comment if (line.isEmpty() || line.startsWith("/*")) { continue; } // Parse lines formatted like: "Mathew's score: 540 points;" Pattern scorePattern = Pattern.compile("(.*)'s score: (\\d+) points;"); Matcher matcher = scorePattern.matcher(line); if (matcher.matches()) { String player = matcher.group(1).trim(); int score = Integer.parseInt(matcher.group(2)); scores.add(new ScoreEntry(player, score)); } } } return scores; }
3. Sort and Rewrite the File
Now, we'll sort the parsed scores and overwrite the original file with the sorted entries:
public void sortAndRewriteHighscores(int levelID) throws IOException { List<ScoreEntry> sortedScores = readScores(levelID); Collections.sort(sortedScores); // Uses our custom compareTo for descending order // Overwrite the original file File scoreFile = new File("Scoreboard/Level_" + levelID + "_Highscore.txt"); try (FileWriter writer = new FileWriter(scoreFile, false)) { // Write the header comment first writer.write("/*---Highscores---*/ \n \n"); // Write each sorted score entry for (ScoreEntry entry : sortedScores) { writer.write(String.format("%s's score: %d points;\n", entry.getPlayerName(), entry.getScore())); } } }
4. Integrate with Your Existing scoreWrite Method
To make sorting automatic every time a new score is added, call the sort method at the end of your scoreWrite function:
public void scoreWrite(int levelID) throws IOException { File highscores = new File("Scoreboard/Level_" + levelID + "_Highscore.txt"); if (highscores.createNewFile()) { try (FileWriter writer = new FileWriter(highscores, false)) { writer.write("/*---Highscores---*/ \n \n"); writer.write(SokobanGame.getInstance().getPlayerName() + "'s score: " + getScore() + " points;\n"); } } else { try (FileWriter writer = new FileWriter(highscores, true)) { writer.write(SokobanGame.getInstance().getPlayerName() + "'s score: " + getScore() + " points;\n"); } } // Auto-sort after adding a new score sortAndRewriteHighscores(levelID); }
Quick Notes
- Duplicate Players: If you want to keep only the highest score per player, add a check when reading entries (e.g., use a
Map<String, Integer>to track the highest score for each player, then convert to a list). - File Permissions: Make sure your app has read/write access to the
Scoreboarddirectory—if it doesn't exist, add code to create it withnew File("Scoreboard").mkdirs();before writing files. - Alternative Format: If your file uses the space-separated format from your example (
/*Scores*/ Mathew: 540 Stacy: 070...), adjust the parsing logic to split the line after the comment, then iterate over name-score pairs.
内容的提问来源于stack exchange,提问作者Coder101

