0

I am writing a Reversi application. I implemented the turns manager class, but I have a little problem in the while loop.

This is my snippet:

while (!table.isFull() || passFlag != 2) {
    if (player1.isActive()) {
        for (int i = 0; i < table.getSize(); i++) {
            for (int j = 0; j < table.getSize(); j++) {
                table.getField(i, j).addActionListener(new ActionListener() {
                            public void actionPerformed(ActionEvent e) {
                                if (e.getSource() instanceof Field) {
                                    ((Field) e.getSource()).changeToBlack();
                                }
                            }
                        });
            }
        }
    }
    if (player2.isActive()) {
        for (int i = 0; i < table.getSize(); i++) {
            for (int j = 0; j < table.getSize(); j++) {
                table.getField(i, j).addActionListener(new ActionListener() {
                            public void actionPerformed(ActionEvent e) {
                                if (e.getSource() instanceof Field) {
                                    ((Field) e.getSource()).changeToWhite();
                                }
                            }
                        });
            }
        }
    }
    sentinel.changeActivePlayer(player1, player2);

The table is a grid of buttons, and the fields are the buttons. The loop does not wait for the player interaction. How can I implement the code so that it waits for the user's mouse click?

This is the full code of this class

package Core;

import GUILayer.Field;
import GUILayer.MainFrame;
import elements.Player;
import elements.Table;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class TurnManager {

    int passFlag = 0;
    int TurnFlag = 0;
    Sentinel sentinel = new Sentinel();

    public TurnManager() {
    }

    public void manage(MainFrame mainframe, Table table, Player player1, Player player2) {

        while (!table.isFull() || passFlag != 2) {
            if (player1.isActive()) {
                for (int i = 0; i < table.getSize(); i++) {
                    for (int j = 0; j < table.getSize(); j++) {
                        table.getField(i, j).addActionListener(
                                new ActionListener() {

                                    public void actionPerformed(ActionEvent e) {
                                        if (e.getSource() instanceof Field) {
                                            ((Field) e.getSource()).changeToBlack();
                                        }
                                    }
                                });
                    }
                }
            }
            if (player2.isActive()) {
                for (int i = 0; i < table.getSize(); i++) {
                    for (int j = 0; j < table.getSize(); j++) {
                        table.getField(i, j).addActionListener(
                                new ActionListener() {

                                    public void actionPerformed(ActionEvent e) {
                                        if (e.getSource() instanceof Field) {
                                            ((Field) e.getSource()).changeToWhite();
                                        }
                                    }
                                });
                    }
                }
            }
            sentinel.changeActivePlayer(player1, player2);
        }
    }
}
2
  • If this is homework, please tag it as such. Also, that code could benefit from a little refactoring ... Commented May 29, 2011 at 9:27
  • 4
    Can you please provide a more complete example. Where is your while-loop located? It seems to me that it is a broken design. The while-loop assigns listeners to your buttons over and over again. Commented May 29, 2011 at 9:27

3 Answers 3

4

I agree with Howards comment...this looks very misdesigned. Using listeners and events means that you (most of the time) don't have to use an event loop yourself.

Try the following: Create a class that holds your board. The board knows what color each field has (and everything else it needs to know). When your GUI is initialized, you create single EventListener that calls some method of the board object. This method gets passed the field that was clicked (I suppose it get's clicked, or am I wrong?). You store a reference to this EventListener in a variable. Then you loop over each for and column and attach this listener to each field. Then you display the GUI.

Let me clarify: All this is done on initialization time.

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

1 Comment

Thanks the helps. The main problem was the Listeners konwledge missing, but I learned... The solutions was, I created an own listener class, that implemented from the ActionListener, and in the actionPerformed method implemented the event driven operations...so thanks again the ideas, and helps. BR.
0

This is not a complete solution, but your code should look more like this. I think it is a good starting point to hack things together. Hope this helps.

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class TurnManager implements ActionListener{

    int passFlag = 0;
    int TurnFlag = 0;
    Sentinel sentinel = new Sentinel();
    Player player1,player2;


    public TurnManager(MainFrame mainframe, Table table, Player p1, Player p2) {
        player1 = p1;
        player2 = p2;
        for (int i = 0; i < table.getSize(); i++) {
            for (int j = 0; j < table.getSize(); j++) {
                table.getField(i, j).addActionListener(this);
            }
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() instanceof Field) {
            Field field = ((Field) e.getSource());
            //implement logic here, for example:
            if (table.isFull())
                throw new RuntimeException("Table full! Stop! STOP!");

            if (player1.isActive())
                field.changeToBlack();
            if (player2.isActive())
                field.changeToBlack();
        }
    }
}

Comments

0

A few suggestions:

  • As already noted, there's no need for your while loops, and having them (even if they did work) makes your code non-event driven.
  • You want to separate model from view. The model -- which should be fairly ignorant of the view -- will know who's turn it is. It will have a non-static field that will tell it whose turn it is, an enum works well for this, and when it's time to change terms, the value of this field changes.
  • Each cell will have a listener (or "control") attached, probably the same listener (as per Martin's post -- +1 for him), and the listener's only job will be to tell the model which cell was clicked, information that can be gained by calling getSource on the listener's Event parameter. If the listener is an ActionListener, the Event I'm talking about will be the ActionEvent object that is passed into the listener's actionPerformed method.
  • The model will then decide what to do with the information, if anything, based on which cell was pressed and whose turn it is.
  • The view (the GUI) will listen for model changes, possibly with a PropertyChangeListener, or with another listener of your own creation, and will change its display based on the model's state.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.