Question

I'm working on a Java version of chess. I've been a programmer for a few years, but have never received a great explanation of Object-oriented, event-based programming.

Here's my issue: My current program is a linear, console-driven game where the user enters a move for one color and the computer enters a move for the other. To do this, I have a generalized "Player" class that has a "getMove" method. The HumanPlayer gets its move from console input and the AIPlayer generates its move from an algorithm.

I'm now trying to create a third type of player, the GUIPlayer, which generates its move from GUI events. Here's what I want to happen:

Game ---(request for move)---> GUIPlayer --------(request for move)---------> GUI
  ^------(resulting move)--------|<-----(resulting move from click events)-----|

In other words, the Game gives the Player limited access to the GUI in order to request a move, then the Player waits until a specific condition in the GUI is met. I like this design, but I'm not sure how to implement it. I'm assuming some sort of threaded wait-notify structure is needed for the Player class or the GUI.

Here's a reduced version of my code. This is a very rough prototype that is designed solely to return a move.

public class ChessPanel
    extends Component
    implements MouseListener, MouseMotionListener {

Board b;
Piece selectedPiece;
Position selectedPiecePosition;
Move playerMove;

public void mouseClicked(MouseEvent e) {
    Position clickPosition = getSquare(e.getX(), e.getY());

    if(this.selectedPiece.getType() == PieceType.NONE) {
        // Attempts to select the piece that was just clicked
        Piece piece = b.getPiece(clickPosition);

        System.out.println("Selected "+piece);

        if(piece.getType() != PieceType.NONE) {
            this.selectedPiece = b.getPiece(clickPosition);
            this.selectedPiecePosition = clickPosition;
        }
    } else {
        // Attempts to move the selected piece
        try {
            this.playerMove = b.getMove(selectedPiecePosition, clickPosition);

            System.out.println("Made a VALID move");
        } catch(InvalidMoveException ex) {
            // Deselects the selected piece if move is invalid
            this.selectedPiece = new NonePiece();

            System.out.println("Made an INVALID move");
        }
    }
}

}

Basically, I want the GUIPlayer to wait until (playerMove != null) to return it as its move. Does this sound like good design? If so, how could I implement it?

Was it helpful?

Solution

GOT IT.

Turns out it was a basic wait-notify problem. Here's my final code for the ChessPanel's "mouseClicked" method:

public void mouseClicked(MouseEvent e) {
    Position clickPosition = getSquare(e.getX(), e.getY());

    if(this.selectedPiece.getType() == PieceType.NONE) {
        // Attempts to select the piece that was just clicked
        Piece piece = b.getPiece(clickPosition);

        if(piece.getType() != PieceType.NONE) {
            this.selectedPiece = b.getPiece(clickPosition);
            this.selectedPiecePosition = clickPosition;
        }
    } else {
        // Attempts to move the selected piece
        try {
            this.playerMove = b.getMove(selectedPiecePosition, clickPosition);
            synchronized(this) {
                this.notify();
            }
        } catch(InvalidMoveException ex) {

        }
        this.selectedPiece = new NonePiece();
        this.selectedPiecePosition = new Position(0, 0);
        updateCurrentHover(e.getX(), e.getY());
    }

    repaint();
}

And for the GUI itself:

    while(cp.getMove() == null) {
        try {
            synchronized(cp) {
                cp.wait();
            }
        } catch (InterruptedException e) {}
    }

This solved it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top