I am creating a hangman game for my school summative. However I have been experiencing some difficulties with one of my methods called Random Words which performs a few tasks for my program including:

  • Generates a random word from a file which contains 6 different words
  • Does not generate the same random word twice. (this is part I'm having difficulties with).

This program works fine however it randomly stops in the middle returning secretWord as null even when there are still words left in my Words file.

Can anyone please help me please and thank you.

ps: A lot of people asked me why I have || secretWord==null in my do while statement and the reason I have that is because my program was giving me a null exception error and this prevents this from happening.
**

What I have tried:

public static String RandomWord() throws IOException {      
        FileReader fr = new FileReader ("./Hang Man File/Words.txt");           
        BufferedReader br = new BufferedReader(fr);                             
        int random = 0;
        String secretWord =" ";
        do {
            random =(int) ((int) 1+(Math.random()*6));
            for (int lineNo = 1; lineNo < 10; lineNo++) {
                if (lineNo == random) {
                     secretWord = br.readLine();
                } 
                else {
                    br.readLine();
                }
            }
        }
        while(usedWord.contains(secretWord) || secretWord==null); 

        usedWord.add(secretWord);
        return secretWord;
    }

Dani AI

Generated

The symptom (secretWord sometimes becoming null) is almost always caused by reading past the end of the file and brittle loop bounds. The routine in the first post reads a fixed number of lines instead of using the actual file length and re-opens/reads the file on every call. That makes it easy to get a null from readLine and it also makes the used-word logic fragile (if all words become used the do/while can never succeed).

A clean, robust pattern is: read the file once into a List<String>, trim out blanks, shuffle the list, and then hand out words by advancing an index (or remove the used entry). This guarantees no duplicates until you intentionally reshuffle or run out of words. It is also simpler to test and avoids repeated IO.

Example pattern:

private static List<String> words = new ArrayList<>();
private static int nextIndex = 0;

public static void loadWords(Path file) throws IOException {
    words = Files.readAllLines(file).stream()
                .map(String::trim)
                .filter(s -> !s.isEmpty())
                .collect(Collectors.toList());
    Collections.shuffle(words);
    nextIndex = 0;
}

public static String nextWord() {
    if (words.isEmpty()) throw new IllegalStateException("no words loaded");
    if (nextIndex >= words.size()) {
        Collections.shuffle(words); // or throw to signal exhaustion
        nextIndex = 0;
    }
    return words.get(nextIndex++);
}

This implements 's shuffle idea while avoiding per-call file scanning and EOF problems mentioned by . Use Files.readAllLines and Collections.shuffle for convenience: Files API and Collections.shuffle. Also use try-with-resources when you must read streams and always trim/filter blank lines.

"Does not generate the same random word twice."

Consider an array the size equal to the number of words. Start with.

  1. The array with the number 1 in array location 1 and so on till the end.
  2. Now shuffle the array. (Google shuffle an array for many prior discussions.)

For each game you increment a game counter and that is used to look up the next random word and there will be no duplicates.
Test for when you've exchausted your word count and then your choice to repeat step 1 and 2 or start at position 1.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.