feat: save highscores per difficulty

This commit is contained in:
Martin Prokoph
2025-09-09 15:03:24 +02:00
parent db537f84ae
commit f881427a67
7 changed files with 64 additions and 27 deletions

View File

@@ -1,13 +1,22 @@
package eu.midnightdust.yaytris; package eu.midnightdust.yaytris;
import eu.midnightdust.yaytris.util.Difficulty;
import eu.midnightdust.yaytris.util.json.Comment;
import eu.midnightdust.yaytris.util.json.NightJson; import eu.midnightdust.yaytris.util.json.NightJson;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@SuppressWarnings("unused") // Comments are unused in code, but are added to the JSON file for readability
public class HighScores { public class HighScores {
private static final NightJson json = new NightJson(HighScores.class, "tetris_scores.json5"); private static final NightJson json = new NightJson(HighScores.class, "tetris_scores.json5");
public static Map<String, Integer> scores = new HashMap<>(); public static Comment c1 = new Comment("Highscores for each difficulty");
public static Map<String, Integer> Noob = new HashMap<>();
public static Map<String, Integer> Easy = new HashMap<>();
public static Map<String, Integer> Normal = new HashMap<>();
public static Map<String, Integer> Hard = new HashMap<>();
public static Map<String, Integer> Extreme = new HashMap<>();
public static Map<String, Integer> WTF = new HashMap<>();
/** /**
* Saves a new high score for the specified player * Saves a new high score for the specified player
@@ -16,10 +25,21 @@ public class HighScores {
* @param score the score to save * @param score the score to save
*/ */
public static void addScore(String playerName, int score) { public static void addScore(String playerName, int score) {
scores.put(playerName, score); diffToMap(Settings.difficulty).put(playerName, score);
write(); write();
} }
public static Map<String, Integer> diffToMap(Difficulty difficulty) {
switch (difficulty) {
case EASY: return Easy;
case NORMAL: return Normal;
case HARD: return Hard;
case EXTREME: return Extreme;
case WTF: return WTF;
default: return Noob;
}
}
public static void load() { public static void load() {
json.readJson(); json.readJson();
} }

View File

@@ -97,7 +97,7 @@ public class Tetris {
timer.purge(); timer.purge();
if (ui.getMenuPanel() instanceof ScoreMenu) ((ScoreMenu) ui.getMenuPanel()).gameOver(); if (ui.getMenuPanel() instanceof ScoreMenu) ((ScoreMenu) ui.getMenuPanel()).gameOver();
ui.transferFocus(); ui.transferFocus();
if (HighScores.scores.values().stream().noneMatch(hs -> hs > space.getScore())) ui.showHighscoreDialog(space.getScore()); if (HighScores.diffToMap(Settings.difficulty).values().stream().noneMatch(hs -> hs > space.getScore())) ui.showHighscoreDialog(space.getScore());
} }
/** /**

View File

@@ -1,6 +1,7 @@
package eu.midnightdust.yaytris.ui; package eu.midnightdust.yaytris.ui;
import eu.midnightdust.yaytris.HighScores; import eu.midnightdust.yaytris.HighScores;
import eu.midnightdust.yaytris.Settings;
import eu.midnightdust.yaytris.util.CatppuccinColor; import eu.midnightdust.yaytris.util.CatppuccinColor;
import javax.swing.*; import javax.swing.*;
@@ -8,6 +9,7 @@ import javax.swing.border.LineBorder;
import java.awt.*; import java.awt.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import static eu.midnightdust.yaytris.Translation.t; import static eu.midnightdust.yaytris.Translation.t;
import static eu.midnightdust.yaytris.ui.TetrisUI.scale; import static eu.midnightdust.yaytris.ui.TetrisUI.scale;
@@ -20,11 +22,12 @@ public class HighScoreMenu extends JPanel {
this.setBounds(x, y, width, height); this.setBounds(x, y, width, height);
this.setLayout(null); this.setLayout(null);
this.add(new JLabel(t("highscores.title"))); this.add(new JLabel(t("highscores.title", Settings.difficulty)));
List<String> highscores = new ArrayList<>(); List<String> highscores = new ArrayList<>();
for (String key : HighScores.scores.keySet()) { Map<String, Integer> scores = HighScores.diffToMap(Settings.difficulty);
highscores.add(String.format("%s %s", HighScores.scores.get(key), key)); for (String key : scores.keySet()) {
highscores.add(String.format("%s %s", scores.get(key), key));
} }
highscores.sort((s1, s2) -> Integer.compare(Integer.parseInt(s2.split("")[0].replace(" ", "")), Integer.parseInt(s1.split("")[0].replace(" ", "")))); highscores.sort((s1, s2) -> Integer.compare(Integer.parseInt(s2.split("")[0].replace(" ", "")), Integer.parseInt(s1.split("")[0].replace(" ", ""))));
JList<String> highscoreList = new JList<>(highscores.toArray(String[]::new)); JList<String> highscoreList = new JList<>(highscores.toArray(String[]::new));

View File

@@ -17,7 +17,7 @@ import java.util.regex.Pattern;
* Concept inspired by GSON * Concept inspired by GSON
*/ */
public class NightJson { public class NightJson {
private static final String KEY_PATTERN = "\"(-?[A-Za-z-_.]*)\":"; private static final String KEY_PATTERN = "\"(.*)\":";
Class<?> jsonClass; Class<?> jsonClass;
Field jsonMap; Field jsonMap;
String fileLocation; String fileLocation;
@@ -175,21 +175,8 @@ public class NightJson {
private Object getValue(String s, String key, Function<String, Class<?>> keyToType, Iterator<String> pairIterator) { private Object getValue(String s, String key, Function<String, Class<?>> keyToType, Iterator<String> pairIterator) {
String val = s.split(KEY_PATTERN, 2)[1]; String val = s.split(KEY_PATTERN, 2)[1];
if (s.contains("{")) { // Handle maps recursively if (s.contains("{")) {
StringBuilder submapString = new StringBuilder(); return readJsonMap(key, pairIterator, val);
int level = charAmount(s, '{');
submapString.append(val);
if (pairIterator.hasNext()) submapString.append(",");
while (pairIterator.hasNext()) {
String next = pairIterator.next();
submapString.append(next);
level += charAmount(next, '{');
level -= charAmount(next, '}');
if (level <= 0) break;
if (pairIterator.hasNext()) submapString.append(",");
}
Optional<Field> field = getField(key);
return jsonToMap(String.valueOf(submapString), k -> field.isPresent() ? getTypeArgument(field.get(), 1) : String.class);
} }
else { else {
while (val.startsWith(" ")) val = val.substring(1); while (val.startsWith(" ")) val = val.substring(1);
@@ -200,6 +187,27 @@ public class NightJson {
} }
} }
/**
* Handle maps recursively
*/
private Map<String, Object> readJsonMap(String key, Iterator<String> pairIterator, String val) {
StringBuilder submapString = new StringBuilder();
String next = val;
int level = 0;
while (next != null) {
submapString.append(next);
level += charAmount(next, '{');
level -= charAmount(next, '}');
if (level <= 0) break;
if (!pairIterator.hasNext()) {
submapString.append(",");
next = pairIterator.next();
} else next = null;
}
Optional<Field> field = getField(key);
return jsonToMap(String.valueOf(submapString), k -> field.isPresent() ? getTypeArgument(field.get(), 1) : String.class);
}
/** /**
* Count the amount of appearances of a char in a string. * Count the amount of appearances of a char in a string.
* *

View File

@@ -5,7 +5,7 @@
"game.over": "Game over :(", "game.over": "Game over :(",
"game.score": "Score: %s", "game.score": "Score: %s",
"game.time": "Zeit: %s", "game.time": "Zeit: %s",
"highscores.title": "Highscores:", "highscores.title": "Highscores (%s):",
"menu.exit": "Spiel verlassen", "menu.exit": "Spiel verlassen",
"menu.highscores": "Highscores", "menu.highscores": "Highscores",
"menu.settings": "Einstellungen", "menu.settings": "Einstellungen",

View File

@@ -5,7 +5,7 @@
"game.over": "Game over :(", "game.over": "Game over :(",
"game.score": "Score: %s", "game.score": "Score: %s",
"game.time": "Time: %s", "game.time": "Time: %s",
"highscores.title": "Highscores:", "highscores.title": "Highscores (%s):",
"menu.exit": "Exit Game", "menu.exit": "Exit Game",
"menu.highscores": "Highscores", "menu.highscores": "Highscores",
"menu.settings": "Settings", "menu.settings": "Settings",

View File

@@ -1,5 +1,11 @@
{ {
"scores": { // Highscores for each difficulty
"MartinProkoph": 8040 "Noob": {},
} "Easy": {},
"Normal": {
"Martin": 10593
},
"Hard": {},
"Extreme": {},
"WTF": {}
} }