0

I'm trying to make a hangman game in javafx. So naturally, instead of making 26 individual buttons, I am trying to use a for loop to create each button. I am putting them into an ArrayList called alphabet and adding them to a flowPane. The trouble I am running into is when I try to set the action of each button to go to a function with the parameter of it's letter that checks to see if the letter has been used or if it is in the word.

All the instantiations:

ArrayList<Button> alphabet = new ArrayList<Button>();
FlowPane keyboard = new FlowPane();

letterGuess function (currently empty)

public void letterGuess(char letter) {

}

The code in my launch() function:

char letter;
for(int i=0 ; i<26 ; i++) {
    letter = (char) (i+65);
    alphabet.add(new Button("" + letter));
    keyboard.getChildren().add(alphabet.get(i));
    alphabet.get(i).setOnAction(e -> letterGuess(letter));
}

I expect the code to run through without an error and successfully pass letter to letterGuess() for each button. The error I get is at letter in alphabet.get(i).setOnAction(e -> letterGuess(letter)); The error says: Local variable letter defined in an enclosing scope must be final or effectively final

Siksika
  • 3
  • 1

4 Answers4

1

The issue is that you're declaring letter outside the loop and thus trying to change it's value inside the loop. This means the lambda can't use it since it isn't a final or "effectively" final.

You can solve this by declaring the char as new within the loop.

Here is another way you could write the loop which will work fine:

    for (int i = 0; i < 26; i++) {
        char letter = (char) (i + 65);
        Button button = new Button(String.valueOf(letter));
        button.setOnAction(event -> letterGuess(letter));
        alphabet.add(button);
    }

You could also declare letter as final within the loop, but it is not necessary in this case. Because letter is only assigned a value once in the loop, it is effectively final and the lamba knows it.

Zephyr
  • 9,885
  • 4
  • 28
  • 63
0

variables used in lambda must be global , final or effectively final for its proper execution. so you can make it final as it is local in loop :

final char letter = (char) (i+65);

OR

Declare letter as global variable.

Mustahsan
  • 3,852
  • 1
  • 18
  • 34
0

Working code looks like:

for(int i=0; i<26 ; i++) {
    char letter = (char) (i+65);
    alphabet.add(new Button("" + letter));
    keyboard.getChildren().add(alphabet.get(i));
    alphabet.get(i).setOnAction(e -> letterGuess(letter));
}
Siksika
  • 3
  • 1
0
List alphabets = IntStream.range(0, 26)
            .mapToObj(i -> (char) (i + 65))
            .map(l -> new Button(String.valueOf(l)))
            .collect(Collectors.toList());

You can do it in a single line forgive me for the syntax error if you have coz I am typing it from my mobile.

Zephyr
  • 9,885
  • 4
  • 28
  • 63