2

I have problem with the Play Again button, which is to reset the panel to initial state.

The Play Again button should reset the panel, it does reshuffle the gameList, but not reset the panel, which means all the buttons remain and lost the ActionListener function.

Here is my program :

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import static java.util.Collections.*;

public class MemoryGame extends JFrame
{
    private JButton exitButton, replayButton;
    private JButton[] gameButton = new JButton[16];
    private ArrayList<Integer> gameList = new ArrayList<Integer>();
    private int counter = 0;
    private int[] buttonID = new int[2];
    private int[] buttonValue = new int[2];

    public static Point getCenterPosition(int frameWidth, int frameHeight)
    {
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        Dimension dimension = toolkit.getScreenSize();

        int x = (dimension.width - frameWidth)/2;
        int y = (dimension.height - frameHeight)/2;
        return (new Point(x,y));
    }

    public MemoryGame(String title)
    {
        super(title);

        initial();      
    }

    public void initial()
    {
        for (int i = 0; i < gameButton.length; i++) 
        {
            gameButton[i] = new JButton();
            gameButton[i].setFont(new Font("Serif", Font.BOLD, 28));
            gameButton[i].addActionListener(new ButtonListener());
        }
        exitButton = new JButton("Exit");
        replayButton = new JButton("Play Again");
        exitButton.addActionListener(new ButtonListener());
        replayButton.addActionListener(new ButtonListener());

        Panel gamePanel = new Panel();
        gamePanel.setLayout(new GridLayout(4, 4));
        for (int i = 0; i < gameButton.length; i++) 
        {
            gamePanel.add(gameButton[i]);
        }

        Panel buttonPanel = new Panel();
        buttonPanel.add(replayButton);
        buttonPanel.add(exitButton);
        buttonPanel.setLayout(new GridLayout(1, 0));

        add(gamePanel, BorderLayout.CENTER);
        add(buttonPanel, BorderLayout.SOUTH);

        for (int i = 0; i < 2; i++) 
        {
            for (int j = 1; j < (gameButton.length / 2) + 1; j++) 
            {
                gameList.add(j);
            }
        }
        shuffle(gameList);

        int newLine = 0;
        for (int a = 0; a < gameList.size(); a++) 
        {
            newLine++;
            System.out.print(" " + gameList.get(a));
            if (newLine == 4) 
            {
                System.out.println();
                newLine = 0;
            }
        }  
    }

    public boolean sameValues() 
    {
        if (buttonValue[0] == buttonValue[1]) 
        {
            return true;
        }
        return false;
    }

    private class ButtonListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e) 
        {
            if (exitButton == e.getSource()) 
            {
                System.exit(0);
        }
        else if (replayButton == e.getSource()) 
        {
            initial();
        }
        for (int i = 0; i < gameButton.length; i++) 
        {
            if (gameButton[i] == e.getSource()) 
            {
                gameButton[i].setText("" + gameList.get(i));
                gameButton[i].setEnabled(false);
                counter++;

                if (counter == 3) 
                {
                    if (sameValues()) 
                    {
                        gameButton[buttonID[0]].setEnabled(false);
                        gameButton[buttonID[1]].setEnabled(false);
                    } 
                    else 
                    {
                        gameButton[buttonID[0]].setEnabled(true);
                        gameButton[buttonID[0]].setText("");
                        gameButton[buttonID[1]].setEnabled(true);
                        gameButton[buttonID[1]].setText("");
                    }
                    counter = 1;
                }
                if (counter == 1) 
                {
                    buttonID[0] = i;
                    buttonValue[0] = gameList.get(i);
                }
                if (counter == 2) 
                {
                    buttonID[1] = i;
                    buttonValue[1] = gameList.get(i);
                }
            }
        }
    }
    }

    public static void main(String[] args)
    {
        int x, y;
        int width = 500;
        int height = 500;

        Point position = getCenterPosition(width, height);
        x = position.x;
        y = position.y;

        JFrame frame = new MemoryGame("Memory Game");
        frame.setBounds(x, y, width, height);

        frame.setVisible(true);
        frame.setResizable(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }   
}

How can I solve this problem?

EDIT :

Another problem is after reset(), all buttons seem like become sameValue(). I have insert some audio to the buttons, and it's happen in the condition of the ButtonListener. Here is the part :

if (counter == 3) 
    {
        if (sameValues()) 
        {
            gameButton[buttonID[0]].setEnabled(false);
            gameButton[buttonID[1]].setEnabled(false);
        } 

Seems like it's satisfy the condition sameValue(), but why?

LATEST UPDATE :

Problem Solved. Latest code is not uploaded.

Chin
  • 593
  • 4
  • 15
  • 36
  • `frame.setLocationRelativeTo(null);`, can also place your `JFrame` to the middle of the screen, so why to apply a logic for this thing too. Why you have those first two loops for initializing `JButton` and then another loop to add the `JButton` to the `JPanel`, why not put those things in a single loop. Though not related to your asked question, but will help you in your quest :-) – nIcE cOw May 12 '12 at 16:01
  • Your exit button won't work too. Just use `equals()` instead of `==` to compare `Objects`. Another quick fix is to use an `if..else if..else` structure in your `actionPerformed()` method, otherwise it will execute the `for (int i = 0; i < gameButton.length; i++) { if (gameButton[i].equals(e.getSource())) { gameButton[i].setText("" + gameList.get(i)); gameButton[i].setEnabled(false); counter++; ...` everytime tha you hit a button – StepTNT May 12 '12 at 16:07
  • @nIcEcOw `frame.setLocationRelativeTo(null);` Ich! Looks like a splash. Use [`setLocationByPlatform(true)`](http://stackoverflow.com/questions/7143287/how-to-best-position-swing-guis) instead. – Andrew Thompson May 12 '12 at 16:09
  • I'm just start learning `Java`, and the code to place the `JFrame` to the middle of the screen, I was following what is written in the reference book. About the two loops, I'm not expert in programming, so sometimes I may not able to reduce the number of lines of the codes. – Chin May 12 '12 at 16:12
  • @AnonyNewbie : Simply take the lines written above the loop having this line `gamePanel.add(gameButton[i]);` to the first loop and place this line in that loop, so one loop will do that work, which now two are doing :-) – nIcE cOw May 12 '12 at 16:18
  • @AndrewThompson : Since it's a game by the look of the variables being used, so I really don't know where exactly the developer wants it to be forced on the screen, though that fabulous thingy is always great, `setLocationByPlatform(true);` it's one of my favourtie questions, and I forgot to upvote that thingy, LOL, did that today :-) – nIcE cOw May 12 '12 at 16:20

2 Answers2

3

In the initial() method the code is creating a new GUI. It would be preferable to retain handles to the original controls, and reset them to a 'begin game' state and the correct values (for number).

Alternatives with your current method are to remove() and add() new for every component (not recommended) or to use a CardLayout (not necessary - see first suggestion).

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
2

Ok, I've fixed your code.

Be sure to check out my comment to your question and let me know if it works (I did a quick test and it went fine)

package varie;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import static java.util.Collections.shuffle;
import javax.swing.JButton;
import javax.swing.JFrame;

public class MemoryGame extends JFrame {

private JButton exitButton, replayButton;
private JButton[] gameButton = new JButton[16];
private ArrayList<Integer> gameList = new ArrayList<>();
private int counter = 0;
private int[] buttonID = new int[2];
private int[] buttonValue = new int[2];

public static Point getCenterPosition(int frameWidth, int frameHeight) {
    Toolkit toolkit = Toolkit.getDefaultToolkit();
    Dimension dimension = toolkit.getScreenSize();

    int x = (dimension.width - frameWidth) / 2;
    int y = (dimension.height - frameHeight) / 2;
    return (new Point(x, y));
}

public MemoryGame(String title) {
    super(title);

    initial();
}

public void initial() {        
    for (int i = 0; i < gameButton.length; i++) {
        gameButton[i] = new JButton();
        gameButton[i].setFont(new Font("Serif", Font.BOLD, 28));
        gameButton[i].addActionListener(new ButtonListener());
    }
    exitButton = new JButton("Exit");
    replayButton = new JButton("Play Again");
    exitButton.addActionListener(new ButtonListener());
    replayButton.addActionListener(new ButtonListener());

    Panel gamePanel = new Panel();
    gamePanel.setLayout(new GridLayout(4, 4));
    for (int i = 0; i < gameButton.length; i++) {
        gamePanel.add(gameButton[i]);
    }

    Panel buttonPanel = new Panel();
    buttonPanel.add(replayButton);
    buttonPanel.add(exitButton);
    buttonPanel.setLayout(new GridLayout(1, 0));

    add(gamePanel, BorderLayout.CENTER);
    add(buttonPanel, BorderLayout.SOUTH);

    for (int i = 0; i < 2; i++) {
        for (int j = 1; j < (gameButton.length / 2) + 1; j++) {
            gameList.add(j);
        }
    }
    shuffle(gameList);

    int newLine = 0;
    for (int a = 0; a < gameList.size(); a++) {
        newLine++;
        System.out.print(" " + gameList.get(a));
        if (newLine == 4) {
            System.out.println();
            newLine = 0;
        }
    }

}

public boolean sameValues() {
    if (buttonValue[0] == buttonValue[1]) {
        return true;
    }
    return false;
}

public void reset() {        
    for(int i = 0; i< gameButton.length; i++){
        gameButton[i].setEnabled(true);
        gameButton[i].setText("");
        for(ActionListener al : gameButton[i].getActionListeners()){
            gameButton[i].removeActionListener(al);
        }
        gameButton[i].addActionListener(new ButtonListener());
    }
    buttonID = new int[2];
    buttonValue = new int[2];
    counter = 0;
    shuffle(gameList);
    int newLine = 0;
    for (int a = 0; a < gameList.size(); a++) {
        newLine++;
        System.out.print(" " + gameList.get(a));
        if (newLine == 4) {
            System.out.println();
            newLine = 0;
        }
    }
}

private class ButtonListener implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
        if (exitButton.equals(e.getSource())) {
            System.exit(0);
        } else if (replayButton.equals(e.getSource())) {
            reset();
        } else {
            for (int i = 0; i < gameButton.length; i++) {
                if (gameButton[i].equals(e.getSource())) {
                    gameButton[i].setText("" + gameList.get(i));
                    gameButton[i].setEnabled(false);
                    counter++;

                    if (counter == 3) {
                        if (sameValues()) {
                            gameButton[buttonID[0]].setEnabled(false);
                            gameButton[buttonID[1]].setEnabled(false);
                        } else {
                            gameButton[buttonID[0]].setEnabled(true);
                            gameButton[buttonID[0]].setText("");
                            gameButton[buttonID[1]].setEnabled(true);
                            gameButton[buttonID[1]].setText("");
                        }
                        counter = 1;
                    }
                    if (counter == 1) {
                        buttonID[0] = i;
                        buttonValue[0] = gameList.get(i);
                    }
                    if (counter == 2) {
                        buttonID[1] = i;
                        buttonValue[1] = gameList.get(i);
                    }
                }
            }
        }
    }
}

public static void main(String[] args) {
    int x, y;
    int width = 500;
    int height = 500;

    Point position = getCenterPosition(width, height);
    x = position.x;
    y = position.y;

    JFrame frame = new MemoryGame("Memory Game");
    frame.setBounds(x, y, width, height);

    frame.setVisible(true);
    frame.setResizable(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
StepTNT
  • 3,867
  • 7
  • 41
  • 82
  • Thanks, it's work fine. I think I've miss out the `buttonID = new int[2];` and `buttonValue = new int[2];`, that's why the buttons are not recreate. I want to ask a question, what is the use of the `@Override`? I google it but not so understand. – Chin May 12 '12 at 16:38
  • 1
    It's better to start a new question if you want to ask about the `@Override` annotation. Basically it's used when you have a class `B` extending a class `A` and you want to rewrite a method of `A`. But opening a new question will get to you better answers ;) Don't forget to accept the answer if you think that it was useful :) – StepTNT May 12 '12 at 16:41
  • I found an error with the code, that it does reset to initial state, but seems like the second time onward it loses the compare function. If same value is clicked, it'll not back to blank button. – Chin May 13 '12 at 15:28
  • I've tested it before posting the answer and I've got no error. Please explain WHEN you got the error and what's happening. – StepTNT May 14 '12 at 17:28
  • After press the `Play Again` button. It's will back to the initial state, but the button will display once it clicked and even the number is not same. Meaning that every number will revealed once it clicked. – Chin May 15 '12 at 01:21
  • Added two lines to the reset method. I forgot to remove the previous `ActionListener` bound to each gameButton, that's why it acted weird! – StepTNT May 15 '12 at 08:47
  • Thanks. I'm even edit my program to more weird and everytime I press `Play Again`, then once I press a button, it's non-responding. But now I follow what you said, I removed the `ActionListener` and now work fine. Thanks a lot. – Chin May 15 '12 at 09:40