4
\$\begingroup\$

I recently started learning programming and in particular Java. I wrote this small hangman game which takes the input for the secret word from the user.

It all works as intended; I would like to know ways to optimize or improve this code (taking into account that the input must be taken from the user and not from a file).

import java.util.Scanner;
import java.util.List;
import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("Write the word");
        String word = sc.nextLine();
        List<String> wordSeg = new ArrayList<>(word.length());
        for (int x = 0; x < word.length(); x++) {
            wordSeg.add("*");
        }
        int i = 0;
        int chancesLeft;
        String usedCharacters = "";
        while (i < 6) {
            chancesLeft = 6 - i;
            System.out.println("Write a character or a word");
            String character  = sc.nextLine();
            char characterChar = character.charAt(0);
            if (character.equals(word)){
                System.out.println("You won!");
                break;
            }
            else if (word.contains(Character.toString(characterChar)) && character.length() < 2){
                for (int indx = 0; indx < word.length(); indx++){
                    if (word.charAt(indx) == characterChar) {
                        wordSeg.set(indx, character);
                    }
                }
                System.out.print(wordSeg);
                continue;
            } else {
                usedCharacters = character + " - " + usedCharacters;
            }
            i++;
            System.out.println("Chances left: " + chancesLeft);
            System.out.println("Characters not included: " + usedCharacters);
        }
    }
}
```
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

As your wordSeg doesn't change in length I'd use an array instead of ArrayList (String[] wordSeg = new String[word.length]). To fill the array you'd need to change for loop setting to wordSeg[x] = "*"; (or use Array.fill(wordSeg, "*");, though this would require an additional import). Because wordSeg is a list, using StringBuilder to create current output/guess is really easy:

StringBuilder builder;
...
builder = new StringBuilder();
for (String ch : wordSeg) {  
    builder.append(ch);  
}  
System.out.println(builder.toString());

Then you can add a check to see if guessed matches word (if(builder.toString().equals(word)){).

Next I'd make usedCharacters an ArrayList so it looks cleaner when you output the contents, as currently there is a dangling -. You need to update value in else with usedCharacters.add(character).

Before the loop I'd create a boolean flag win that I would set when the word is guessed, so that after the loop the output can change on win/lose. I'd also update wording of Characters not included to be something like Wrong Guesses because if the word is test and I guess then, there are correct characters, but the guess is wrong.

I'd get rid of characterChar, as the else if already checks if character.length() < 2

chancesLeft is outputting the wrong value, need to add - 1 in output

Technically the scanner should be closed as well (sc.close())

Whole program:

import java.util.Scanner;
import java.util.ArrayList;
import java.lang.StringBuilder;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
                StringBuilder builder = new StringBuilder();  
        System.out.println("Write the word");
        String word = sc.nextLine();
        String[] wordSeg = new String[word.length()];
        //Arrays.fill(wordSeg, "*"); // if you use this don't forget the import
        for (int x = 0; x < word.length(); x++) {
            wordSeg[x] = "*";
        }
        int i = 0;
        int chancesLeft;
        ArrayList<String> usedCharacters = new ArrayList<String>();
        boolean win = false;
        while (i < 6) {
            chancesLeft = 6 - i;
            System.out.println("Write a character or a word");
            String character  = sc.nextLine();
            if (character.equals(word)){
              win = true;
              break;
            }
            else if (word.contains(character) && character.length() < 2){                
                for (int indx = 0; indx < word.length(); indx++){
                    if (word.charAt(indx) == character.charAt(0)) {
                        wordSeg[indx] = character;
                    }
                } 
                builder = new StringBuilder();
                for (String ch : wordSeg) {  
                    builder.append(ch);  
                }  
                System.out.println(builder.toString());
                if(builder.toString().equals(word)){
                  win = true;
                  break;
                }
                continue;
            } else {
                usedCharacters.add(character);
            }
            i++;
            System.out.println("Chances left: " + (chancesLeft-1));
            System.out.println("Wrong Guesses: " + usedCharacters);
        }
        if (win) {
          System.out.println("You Won!");
        } else {
          System.out.println("You lose!");
          System.out.println("The word was " + word);
        }
        sc.close();
    }
}
\$\endgroup\$
1
  • \$\begingroup\$ What you call a "normal list" is an array, and not a List at all. \$\endgroup\$ Commented Feb 7, 2023 at 20:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.