Java命令行Wordle克隆程序每日游戏次数限制逻辑异常
Java Wordle克隆程序每日游戏次数限制问题修复
问题描述
开发命令行版Java Wordle克隆程序,需求为限制玩家每日最多10局游戏,每24小时重置游戏次数。但当前代码仅允许玩家每日玩1局,怀疑问题出在canPlayGame方法的逻辑中。
核心问题分析
canPlayGame方法的分支逻辑存在错误,导致非新周期的情况下直接禁止游戏:
- 第三个
else if (hoursBetween < 24)分支完全多余,因为前面已经判断过hoursBetween >=24,剩余所有情况都是hoursBetween <24,这会导致只要不是新的24小时周期,不管玩家是否玩满10局,都会直接返回false,阻止继续游戏。 - 额外问题:
start方法中重复调用initializeLastGameTimestamp,可能覆盖正确的时间戳gamesPlayedToday的递增时机错误,需在每局游戏结束后立即计数,而非用户选择继续之后- 未在每局游戏结束后更新并保存
lastGameTimestamp,导致24小时周期计算不准确 canPlayGame中使用System.out输出提示,未统一使用传入的PrintStream
修复后的代码
import java.io.*; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.*; public class Commandle { public static final int MAX_TRIES = 6; public static final int MAX_DAILY_GAMES = 10; private static final String TIMESTAMP_FILE = "lastGameTimestamp.txt"; private static int gamesPlayedToday = 0; private static LocalDateTime lastGameTimestamp = LocalDateTime.MIN; public static void main(String[] args) throws IOException { initializeLastGameTimestamp(); start(System.in, System.out, args); } // Initialize last game timestamp from the file or set to current time if the file doesn't exist private static void initializeLastGameTimestamp() { try { File file = new File(TIMESTAMP_FILE); if (file.exists()) { BufferedReader reader = new BufferedReader(new FileReader(file)); String timestampString = reader.readLine(); if (timestampString != null) { lastGameTimestamp = LocalDateTime.parse(timestampString, DateTimeFormatter.ISO_LOCAL_DATE_TIME); // 从文件读取后,判断是否过了24小时,重置计数 long hoursBetween = ChronoUnit.HOURS.between(lastGameTimestamp, LocalDateTime.now()); if (hoursBetween >=24) { gamesPlayedToday = 0; } } reader.close(); } } catch (IOException e) { e.printStackTrace(); } } private static void saveLastGameTimestamp() { try { File file = new File(TIMESTAMP_FILE); BufferedWriter writer = new BufferedWriter(new FileWriter(file)); writer.write(lastGameTimestamp.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); writer.close(); } catch (IOException e) { e.printStackTrace(); } } public static void start(InputStream in, PrintStream out, String[] args) throws IOException { String dictionaryFileName = "testdictionary.txt"; if (null != args && args.length > 0) { dictionaryFileName = args[0]; } List<String> wordList = getWordList(dictionaryFileName); start(in, out, wordList); } public static void start(InputStream in, PrintStream out, List<String> wordList) throws IOException { Scanner scanner = new Scanner(in); while (true) { if (!canPlayGame(out)) { break; } if (gamesPlayedToday >= MAX_DAILY_GAMES) { out.println("You have reached the maximum number of games for today."); break; } GameBoard gameBoard = new GameBoard(wordList); gameBoard.startGame(); out.println("Games played today: " + gamesPlayedToday); boolean result = playOneGame(out, MAX_TRIES, gameBoard, scanner); if (result) { out.println("Congratulations, you won!"); } else { out.println("Sorry, you lost!"); } // 每局游戏结束后立即递增计数,并更新时间戳 gamesPlayedToday++; lastGameTimestamp = LocalDateTime.now(); saveLastGameTimestamp(); out.println("Play again? (Y/N)"); if (!"Y".equalsIgnoreCase(scanner.nextLine().trim())) { break; } } out.println("See you next time!"); scanner.close(); } private static boolean canPlayGame(PrintStream out) { LocalDateTime currentTime = LocalDateTime.now(); long hoursBetween = ChronoUnit.HOURS.between(lastGameTimestamp, currentTime); if (hoursBetween >= 24) { lastGameTimestamp = currentTime; saveLastGameTimestamp(); gamesPlayedToday = 0; // Reset games played for a new day } else if (gamesPlayedToday >= MAX_DAILY_GAMES) { out.println("You have reached the maximum number of games for today."); return false; } // 只要不是超过次数或新周期未重置,都允许游戏 return true; } private static List<String> getWordList(String dictionaryFileName) throws IOException { List<String> wordList = new ArrayList<>(); try (InputStream inputStream = Commandle.class.getClassLoader().getResourceAsStream(dictionaryFileName); InputStreamReader inputStreamReader = new InputStreamReader(inputStream); BufferedReader br = new BufferedReader(inputStreamReader)) { String line; while ((line = br.readLine()) != null) { wordList.add(line.trim().toLowerCase()); } } return wordList; } private static String getNextValidGuess(Scanner scanner, Set<String> guesses, GameBoard gameBoard) { String guess = scanner.nextLine().trim().toLowerCase(); if (guess.length() != 5) { System.err.print("Please enter a word of 5 letters: "); } else if (guesses.contains(guess)) { System.err.print("Please enter a new word: "); } else if (!gameBoard.containsWord(guess)) { System.err.print("Please enter a valid word: "); } else { guesses.add(guess); return guess; } return getNextValidGuess(scanner, guesses, gameBoard); } private static boolean playOneGame(PrintStream out, int rounds, GameBoard gameBoard, Scanner scanner) { Set<String> guesses = new HashSet<>(); for (int i = 0; i < rounds; i++) { out.print("Please enter your guess: "); String guess = getNextValidGuess(scanner, guesses, gameBoard); GameBoard.Status[] result = gameBoard.isInTarget(guess.toLowerCase().toCharArray()); String hint = ""; for (int j = 0; j < result.length; j++) { switch (result[j]) { case correct -> hint += guess.charAt(j); case wrong -> hint += "#"; case partial -> hint += "?"; } } int round = i + 1; out.println(round + ": " + guess + " " + round + ": " + hint); if (gameBoard.hasWon(result)) { return true; } } return false; } }
关键修复点
- 修正
canPlayGame逻辑:移除错误的else if (hoursBetween < 24)分支,仅在超过每日次数时返回false - 调整计数递增时机:每局游戏结束后立即递增
gamesPlayedToday,并更新保存时间戳 - 移除重复初始化:删除
start(InputStream, PrintStream, String[])中的重复initializeLastGameTimestamp调用 - 统一输出流:将
canPlayGame的提示输出改为使用传入的PrintStream - 初始化时的周期判断:在
initializeLastGameTimestamp中增加周期判断,确保程序重启后也能正确重置计数
内容的提问来源于stack exchange,提问作者Rory Steuart
相关产品推荐
相关产品推荐

