You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java命令行Wordle克隆程序每日游戏次数限制逻辑异常

Java Wordle克隆程序每日游戏次数限制问题修复

问题描述

开发命令行版Java Wordle克隆程序,需求为限制玩家每日最多10局游戏,每24小时重置游戏次数。但当前代码仅允许玩家每日玩1局,怀疑问题出在canPlayGame方法的逻辑中。

核心问题分析

canPlayGame方法的分支逻辑存在错误,导致非新周期的情况下直接禁止游戏:

  1. 第三个else if (hoursBetween < 24)分支完全多余,因为前面已经判断过hoursBetween >=24,剩余所有情况都是hoursBetween <24,这会导致只要不是新的24小时周期,不管玩家是否玩满10局,都会直接返回false,阻止继续游戏。
  2. 额外问题:
    • 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;
    }
}

关键修复点

  1. 修正canPlayGame逻辑:移除错误的else if (hoursBetween < 24)分支,仅在超过每日次数时返回false
  2. 调整计数递增时机:每局游戏结束后立即递增gamesPlayedToday,并更新保存时间戳
  3. 移除重复初始化:删除start(InputStream, PrintStream, String[])中的重复initializeLastGameTimestamp调用
  4. 统一输出流:将canPlayGame的提示输出改为使用传入的PrintStream
  5. 初始化时的周期判断:在initializeLastGameTimestamp中增加周期判断,确保程序重启后也能正确重置计数

内容的提问来源于stack exchange,提问作者Rory Steuart

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 04:37:02