5

I am making a keyboard-like buttons for my Hangman game (SEE PICTURE HERE), my problem is about the inner classes. I've read this LINK about inner classes and it says that you can only access the outside variables with FINAL type. But if I declared the variable as such, I cannot change the value of it anymore... So my problem is that I need to change the value inside the inner class. My code is as follows:

public class MainGame extends JDialog { private String player; private char [] wordChar; private JButton[] buttons; private int level; private int score; private int livesLeft; private int missedGuess; void newGame() { level = 0; score = 0; livesLeft = 10; missedGuess = 0; //label1: // while (livesLeft!= 0) { //get random WORD from LIST Word hiddenWord = new Word(); //put random word in Array wordChar = new char[hiddenWord.getHiddenWord().length()]; wordChar = hiddenWord.getHiddenWord().toCharArray(); buttons = new JButton[wordChar.length]; for (int i = 0; i < wordChar.length; i++){ JButton guessWord = new JButton(" "); guessWord.setFont(new Font("Microsoft Sans Serif", 1, 18)); guessWord.setEnabled(false); jPanel3.setLayout(new GridLayout(1, wordChar.length)); jPanel3.add(guessWord); buttons[i] = guessWord; } checkLetter(); } void checkLetter() { int checker = 0; while(checker != wordChar.length){ jPanel1.setLayout(new GridLayout(3, 9, 3, 5)); for (char buttonChar = 'a'; buttonChar <= 'z'; buttonChar++) { String buttonText = String.valueOf(buttonChar); final JButton letterButton = new JButton(buttonText); letterButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String actionCommand = e.getActionCommand(); for (int j = 0; j < wordChar.length; j++){ String text = String.valueOf(wordChar[j]); if(actionCommand.equals(text)){ buttons[j].setText(text); checker++; //THIS CODE IS NOT POSSIBLE!!!! } } } }); jPanel1.add(letterButton); } checker++; } } 

NOTE: The code above is not complete. The int checker is used to count how many correct letters are already guessed so that if it is equal to the length of the word, I can now proceed to the next levelenter image description here

How can I re-do my code?

1
  • If you explain what checker is doing, aside from the obvious control check, it might help people suggest design alternatives. Commented Jan 30, 2011 at 13:51

3 Answers 3

3

You can declare checker as a field of outer class, and access it with some method, something like increaseChecker().

UPDATE: Something like this:

1) Create checker field in outer class:

public class OuterClassName { private int checker; protected void increaseChecker() { checker++; } void checkLetter() { // ... } } 

2) Use increaseChecker() method call instead of checker++

Sign up to request clarification or add additional context in comments.

Comments

3

You can't access local variables in an anonymous inner class, and that's for a good reason. The actionPerformed() method isn't guaranteed to be called inside the checkLetter() function. It will be called later, possibly (and most probably) after the function exits so its local variables will be destroyed by that time. Therefore, the newly created anonymous class implicitly gets a copy of that variable. But it wouldn't make any sense to increase the copy, that's why only final local variables can be accessed from methods of an anonymous class.

The simplest workaround is just to make checker a field of the outer class. But that wouldn't make any sense if it's accessed only within the checkLetter() function unless it is necessary for it to retain its value between checkLetter() calls. In order to find out the true answer, you need to think why you are trying to increase checker inside actionPerformed()? When should it happen and what are you trying to achieve by doing it?

2 Comments

. The int checker is used to count how many correct letters are already guessed so that if it is equal to the length of the word, i can now proceed to the next level
@newbie: Then the variable checker needs to exist until the game is over. In Java, a method's local variables exist only while that method is being executed. Therefore checker is currently disposed of as soon as the new game has started, but it should exist until the game is over - just like wordChar. Therefore, the straightforward solution is to declare checker as you do wordChar - and reset it in newGame().
1

Why not keep the anonymous inner class but have it call a method of the class. This way final isn't an issue.

 letterButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { letterButtonActionPerformed(e); // create this method } }); //..... // new method private void letterButtonActionPerformed(ActionEvent e) { String actionCommand = e.getActionCommand(); for (int j = 0; j < wordChar.length; j++){ String text = String.valueOf(wordChar[j]); if(actionCommand.equals(text)){ buttons[j].setText(text); checker++; //THIS CODE IS NOT POSSIBLE!!!! } } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.