2011-01-30 22 views
5

Estoy haciendo botones con forma de teclado para mi juego Hangman (SEE PICTURE HERE), mi problema es sobre las clases internas. He leído esto LINK sobre clases internas y dice que solo se puede acceder a las variables externas con el tipo FINAL. Pero si declaro la variable como tal, ya no puedo cambiar el valor de ella ... Así que mi problema es que necesito cambiar el valor dentro de la clase interna. Mi código es el siguiente:Clases internas en Java

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++; 
      } 
     } 

NOTA: El código anterior no está completo. El corrector int se utiliza para contar el número de letras correctas ya están adivinado por lo que si es igual a la longitud de la palabra, ahora puedo pasar a la siguiente nivel enter image description here

¿Cómo puedo volver a hacer mi código?

+0

Si explica lo que 'checker' está haciendo, además de la verificación de control obvia, podría ayudar a las personas a sugerir alternativas de diseño. – Carl

Respuesta

3

Puede declarar checker como un campo de clase externa, y acceder a él con algún método, algo así como increaseChecker().

ACTUALIZACIÓN: Algo como esto:

1) Crear campo ortográfico en clase externa:

public class OuterClassName { 
    private int checker; 

    protected void increaseChecker() { 
     checker++; 
    } 

    void checkLetter() { 
     // ... 
    } 

} 

2) Utilice increaseChecker() método de llamada en lugar de checker++

+0

no entiendo :( – newbie

+0

Ver la actualización en la respuesta – Kel

3

no puede acceder a variables locales en una clase interna anónima, y ​​eso es por una buena razón. No se garantiza que el método actionPerformed() se invoque dentro de la función checkLetter(). Se llamará más tarde, posiblemente (y muy probablemente) después de que la función finalice, por lo que sus variables locales se destruirán en ese momento. Por lo tanto, la clase anónima recién creada recibe implícitamente una copia de esa variable. Pero no tendría sentido aumentar la copia, por eso solo se puede acceder a las variables locales finales desde los métodos de una clase anónima.

La solución más simple es simplemente hacer checker un campo de la clase externa. Pero eso no tendría ningún sentido si se accede solo dentro de la función checkLetter() a menos que sea necesario para conservar su valor entre las llamadas a checkLetter(). Para descubrir la respuesta verdadera, debe pensar por qué está tratando de aumentar checker dentro de actionPerformed()? ¿Cuándo debería suceder y qué estás tratando de lograr al hacerlo?

+0

. El corrector int se usa para contar cuántas letras correctas ya se han adivinado de modo que si es igual a la longitud de la palabra, ahora puedo pasar al siguiente nivel – newbie

+1

@newbie: Entonces la variable 'checker' debe existir hasta que el juego termine. En Java, las variables locales de un método existen solo mientras se está ejecutando ese método. Por lo tanto, 'checker' se descarta en cuanto el nuevo juego ha comenzado, pero debería existir hasta que el juego termine - al igual que 'wordChar'. Por lo tanto, la solución directa es declarar' checker' como lo hace 'wordChar' - y restablecerlo en' newGame() '. – meriton

1

¿Por qué no mantener la clase interna anónima pero hacer que llame a un método de la clase. De esta manera final no es un problema.

  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!!!! 
         } 
        } 
      } 
Cuestiones relacionadas