10
\$\begingroup\$

I am currently developing a chess game but have made the mistake of putting all my Java code in one .java file.

I need help cutting up my code into more manageable chucks. Could someone show me how to take out all the piece movements and put them in a separate file which then links back in to the main file? I have tried myself but I end up just breaking the game.

Here is the full messy Java file currently I only have some of the pieces coded up so I thought I would not go further without solving the terrible architecture here.

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

public class ChessProject extends JFrame implements MouseListener, MouseMotionListener {

    JLayeredPane layeredPane;
    JPanel chessBoard;
    JLabel chessPiece;
    int xAdjustment;
    int yAdjustment;
    int startX;
    int startY;
    int initialX;
    int initialY;
    JPanel panels;
    JLabel pieces;

    public ChessProject() {
        Dimension boardSize = new Dimension(600, 600);

        //  Use a Layered Pane for this application
        layeredPane = new JLayeredPane();
        getContentPane().add(layeredPane);
        layeredPane.setPreferredSize(boardSize);
        layeredPane.addMouseListener(this);
        layeredPane.addMouseMotionListener(this);

        //Add a chess board to the Layered Pane
        chessBoard = new JPanel();
        layeredPane.add(chessBoard, JLayeredPane.DEFAULT_LAYER);
        chessBoard.setLayout(new GridLayout(8, 8));
        chessBoard.setPreferredSize(boardSize);
        chessBoard.setBounds(0, 0, boardSize.width, boardSize.height);

        for (int i = 0; i < 64; i++) {
            JPanel square = new JPanel(new BorderLayout());
            chessBoard.add(square);

            int row = (i / 8) % 2;
            if (row == 0) {
                square.setBackground(i % 2 == 0 ? Color.white : Color.gray);
            } else {
                square.setBackground(i % 2 == 0 ? Color.gray : Color.white);
            }
        }

        // Setting up the Initial Chess board.
        for (int i = 8; i < 16; i++) {
            pieces = new JLabel(new ImageIcon("WhitePawn.png"));
            panels = (JPanel) chessBoard.getComponent(i);
            panels.add(pieces);
        }
        pieces = new JLabel(new ImageIcon("WhiteRook.png"));
        panels = (JPanel) chessBoard.getComponent(0);
        panels.add(pieces);
        pieces = new JLabel(new ImageIcon("WhiteKnight.png"));
        panels = (JPanel) chessBoard.getComponent(1);
        panels.add(pieces);
        pieces = new JLabel(new ImageIcon("WhiteKnight.png"));
        panels = (JPanel) chessBoard.getComponent(6);
        panels.add(pieces);
        pieces = new JLabel(new ImageIcon("WhiteBishup.png"));
        panels = (JPanel) chessBoard.getComponent(2);
        panels.add(pieces);
        pieces = new JLabel(new ImageIcon("WhiteBishup.png"));
        panels = (JPanel) chessBoard.getComponent(5);
        panels.add(pieces);
        pieces = new JLabel(new ImageIcon("WhiteKing.png"));
        panels = (JPanel) chessBoard.getComponent(3);
        panels.add(pieces);
        pieces = new JLabel(new ImageIcon("WhiteQueen.png"));
        panels = (JPanel) chessBoard.getComponent(4);
        panels.add(pieces);
        pieces = new JLabel(new ImageIcon("WhiteRook.png"));
        panels = (JPanel) chessBoard.getComponent(7);
        panels.add(pieces);
        for (int i = 48; i < 56; i++) {
            pieces = new JLabel(new ImageIcon("BlackPawn.png"));
            panels = (JPanel) chessBoard.getComponent(i);
            panels.add(pieces);
        }
        pieces = new JLabel(new ImageIcon("BlackRook.png"));
        panels = (JPanel) chessBoard.getComponent(56);
        panels.add(pieces);
        pieces = new JLabel(new ImageIcon("BlackKnight.png"));
        panels = (JPanel) chessBoard.getComponent(57);
        panels.add(pieces);
        pieces = new JLabel(new ImageIcon("BlackKnight.png"));
        panels = (JPanel) chessBoard.getComponent(62);
        panels.add(pieces);
        pieces = new JLabel(new ImageIcon("BlackBishup.png"));
        panels = (JPanel) chessBoard.getComponent(58);
        panels.add(pieces);
        pieces = new JLabel(new ImageIcon("BlackBishup.png"));
        panels = (JPanel) chessBoard.getComponent(61);
        panels.add(pieces);
        pieces = new JLabel(new ImageIcon("BlackKing.png"));
        panels = (JPanel) chessBoard.getComponent(59);
        panels.add(pieces);
        pieces = new JLabel(new ImageIcon("BlackQueen.png"));
        panels = (JPanel) chessBoard.getComponent(60);
        panels.add(pieces);
        pieces = new JLabel(new ImageIcon("BlackRook.png"));
        panels = (JPanel) chessBoard.getComponent(63);
        panels.add(pieces);
    }

    private Boolean piecePresent(int x, int y) {
        Component c = chessBoard.findComponentAt(x, y);
        if (c instanceof JPanel) {
            return false;
        } else {
            return true;
        }
    }

    //Check if a piece is a Black piece.
    private Boolean checkWhiteOponent(int newX, int newY) {
        Boolean oponent;
        Component c1 = chessBoard.findComponentAt(newX, newY);
        JLabel awaitingPiece = (JLabel) c1;
        String tmp1 = awaitingPiece.getIcon().toString();
        if (((tmp1.contains("Black")))) {
            oponent = true;
        } else {
            oponent = false;
        }
        return oponent;
    }

    //Check if a piece is a White piece.

    private Boolean checkBlackOponent(int newX, int newY) {
        Boolean oponent;
        Component c1 = chessBoard.findComponentAt(newX, newY);
        JLabel awaitingPiece = (JLabel) c1;
        String tmp1 = awaitingPiece.getIcon().toString();
        if (((tmp1.contains("White")))) {
            oponent = true;
        } else {
            oponent = false;
        }
        return oponent;
    }

    public void mousePressed(MouseEvent e) {
        chessPiece = null;
        Component c = chessBoard.findComponentAt(e.getX(), e.getY());
        if (c instanceof JPanel) {
            return;
        }

        Point parentLocation = c.getParent().getLocation();
        xAdjustment = parentLocation.x - e.getX();
        yAdjustment = parentLocation.y - e.getY();
        chessPiece = (JLabel) c;
        initialX = e.getX();
        initialY = e.getY();
        startX = (e.getX() / 75);
        startY = (e.getY() / 75);
        chessPiece.setLocation(e.getX() + xAdjustment, e.getY() + yAdjustment);
        chessPiece.setSize(chessPiece.getWidth(), chessPiece.getHeight());
        layeredPane.add(chessPiece, JLayeredPane.DRAG_LAYER);
    }

    public void mouseDragged(MouseEvent me) {
        if (chessPiece == null) {
            return;
        }
        chessPiece.setLocation(me.getX() + xAdjustment, me.getY() + yAdjustment);
    }

    public void mouseReleased(MouseEvent e) {
        if (chessPiece == null) {
            return;
        }

        chessPiece.setVisible(false);
        Boolean success = false;
        Component c = chessBoard.findComponentAt(e.getX(), e.getY());
        String tmp = chessPiece.getIcon().toString();
        String pieceName = tmp.substring(0, (tmp.length() - 4));
        Boolean validMove = false;

//Pawn Moves
//White Pawn
        if (pieceName.equals("WhitePawn")) {
            if (startY == 1) {
                if ((startX == (e.getX() / 75)) && ((((e.getY() / 75) - startY) == 1) || ((e.getY() / 75) - startY) == 2)) {
                    if ((((e.getY() / 75) - startY) == 2)) {
                        if ((!piecePresent(e.getX(), (e.getY()))) && (!piecePresent(e.getX(), (e.getY() + 75)))) {
                            validMove = true;
                        } else {
                            validMove = false;
                        }
                    } else {
                        if ((!piecePresent(e.getX(), (e.getY())))) {
                            validMove = true;
                        } else {
                            validMove = false;
                        }
                    }
                } else {
                    validMove = false;
                }
            } else {
                int newY = e.getY() / 75;
                int newX = e.getX() / 75;
                if ((startX - 1 >= 0) || (startX + 1 <= 7)) {
                    if ((piecePresent(e.getX(), (e.getY()))) && ((((newX == (startX + 1) && (startX + 1 <= 7))) || ((newX == (startX - 1)) && (startX - 1 >= 0))))) {
                        if (checkWhiteOponent(e.getX(), e.getY())) {
                            validMove = true;
                            if (startY == 6) {
                                success = true;
                            }
                        } else {
                            validMove = false;
                        }
                    } else {
                        if (!piecePresent(e.getX(), (e.getY()))) {
                            if ((startX == (e.getX() / 75)) && ((e.getY() / 75) - startY) == 1) {
                                if (startY == 6) {
                                    success = true;
                                }
                                validMove = true;
                            } else {
                                validMove = false;
                            }
                        } else {
                            validMove = false;
                        }
                    }
                } else {
                    validMove = false;
                }
            }
        }
//Black Pawn
        if (pieceName.equals("BlackPawn")) {
            if (startY == 6) {
                if ((startX == (e.getX() / 75)) && ((((e.getY() / 75) - startY) == -1) || ((e.getY() / 75) - startY) == -2)) {
                    if ((((e.getY() / 75) - startY) == -2)) {
                        if ((!piecePresent(e.getX(), (e.getY()))) && (!piecePresent(e.getX(), (e.getY() + 75)))) {
                            validMove = true;
                        } else {
                            validMove = false;
                        }
                    } else {
                        if ((!piecePresent(e.getX(), (e.getY())))) {
                            validMove = true;
                        } else {
                            validMove = false;
                        }
                    }
                } else {
                    validMove = false;
                }
            } else {
                int newY = e.getY() / 75;
                int newX = e.getX() / 75;
                if ((startX - 1 >= 0) || (startX + 1 <= 7)) {
                    if ((piecePresent(e.getX(), (e.getY()))) && ((((newX == (startX + 1) && (startX + 1 <= 7))) || ((newX == (startX - 1)) && (startX - 1 >= 0))))) {
                        if (checkBlackOponent(e.getX(), e.getY())) {
                            validMove = true;
                            if (startY == 1) {
                                success = true;
                            }
                        } else {
                            validMove = false;
                        }
                    } else {
                        if (!piecePresent(e.getX(), (e.getY()))) {
                            if ((startX == (e.getX() / 75)) && ((e.getY() / 75) - startY) == -1) {
                                if (startY == 2) {
                                    success = true;
                                }
                                validMove = true;
                            } else {
                                validMove = false;
                            }
                        } else {
                            validMove = false;
                        }
                    }
                } else {
                    validMove = false;
                }
            }
        }
        //End of Pawn Moves
        //Knight Moves
        //White Knight Code
        else if (pieceName.contains("WhiteKnight")) {

            // next we need to get the new coordinates for where the piece is being dropped.
            int newY = e.getY() / 75;
            int newX = e.getX() / 75;

            // We need to make sure that the piece is being put back on the board...if its not being on
            // the board why would we want to check anything else!
            if (((newX < 0) || (newX > 7)) || ((newY < 0) || (newY > 7))) {
                validMove = false;
            } else {

                if (((newX == startX + 1) && (newY == startY + 2)) || ((newX == startX - 1) && (newY == startY + 2)) || ((newX == startX + 2) && (newY == startY + 1)) || ((newX == startX - 2) && (newY == startY + 1)) || ((newX == startX + 1) && (newY == startY - 2)) || ((newX == startX - 1) && (newY == startY - 2)) || ((newX == startX + 2) && (newY == startY - 1)) || ((newX == startX - 2) && (newY == startY - 1))) {
                    validMove = true;

                    if (piecePresent(e.getX(), (e.getY()))) {
                        if (pieceName.contains("White")) {
                            if (checkWhiteOponent(e.getX(), e.getY())) {
                                validMove = true;
                            } else {
                                validMove = false;
                            }
                        } else {
                            if (checkBlackOponent(e.getX(), e.getY())) {
                                validMove = true;
                            } else {
                                validMove = false;
                            }
                        }
                    }
                } else {
                    validMove = false;
                }
            }
        } //Black Knight Code
        else if (pieceName.contains("BlackKnight")) {

                    // next we need to get the new coordinates for where the piece is being dropped.
            int newY = e.getY() / 75;
            int newX = e.getX() / 75;

                    // We need to make sure that the piece is being put back on the board...if its not being on
                    // the board why would we want to check anything else!
            if (((newX < 0) || (newX > 7)) || ((newY < 0) || (newY > 7))) {
                validMove = false;
            } else {
                if (((newX == startX + 1) && (newY == startY + 2)) || ((newX == startX - 1) && (newY == startY + 2)) || ((newX == startX + 2) && (newY == startY + 1)) || ((newX == startX - 2) && (newY == startY + 1)) || ((newX == startX + 1) && (newY == startY - 2)) || ((newX == startX - 1) && (newY == startY - 2)) || ((newX == startX + 2) && (newY == startY - 1)) || ((newX == startX - 2) && (newY == startY - 1))) {
                    validMove = true;

                    if (piecePresent(e.getX(), (e.getY()))) {
                        if (pieceName.contains("Black")) {
                            if (checkBlackOponent(e.getX(), e.getY())) {
                                validMove = true;
                            } else {
                                validMove = false;
                            }
                        } else {
                            if (checkWhiteOponent(e.getX(), e.getY())) {
                                validMove = true;
                            } else {
                                validMove = false;
                            }
                        }
                    }
                } else {
                    validMove = false;
                }
            }
        }
        //End of Knight Code
        //Bishop Code
        //White Bishup
        else if (pieceName.contains("WhiteBishup")) {
            int newY = e.getY() / 75;
            int newX = e.getX() / 75;
            boolean inTheWay = false;
            int distance = Math.abs(startX - newX);
            if (((newX < 0) || (newX > 7)) || ((newY < 0) || (newY > 7))) {
                validMove = false;
            } else {
                validMove = true;
                if (Math.abs(startX - newX) == Math.abs(startY - newY)) {
                    if ((startX - newX < 0) && (startY - newY < 0)) {
                        for (int i = 0; i < distance; i++) {
                            if (piecePresent((initialX + (i * 75)), (initialY + (i * 75)))) {
                                inTheWay = true;
                            }
                        }
                    } else if ((startX - newX < 0) && (startY - newY > 0)) {
                        for (int i = 0; i < distance; i++) {
                            if (piecePresent((initialX + (i * 75)), (initialY - (i * 75)))) {
                                inTheWay = true;
                            }
                        }
                    } else if ((startX - newX > 0) && (startY - newY > 0)) {
                        for (int i = 0; i < distance; i++) {
                            if (piecePresent((initialX - (i * 75)), (initialY - (i * 75)))) {
                                inTheWay = true;
                            }
                        }
                    } else if ((startX - newX > 0) && (startY - newY < 0)) {
                        for (int i = 0; i < distance; i++) {
                            if (piecePresent((initialX - (i * 75)), (initialY + (i * 75)))) {
                                inTheWay = true;
                            }
                        }
                    }
                    if (inTheWay) {
                        validMove = false;
                    } else {
                        if (piecePresent(e.getX(), (e.getY()))) {
                            if (pieceName.contains("White")) {
                                if (checkWhiteOponent(e.getX(), e.getY())) {
                                    validMove = true;
                                } else {
                                    validMove = false;
                                }
                            } else {
                                if (checkBlackOponent(e.getX(), e.getY())) {
                                    validMove = true;
                                } else {
                                    validMove = false;
                                }
                            }
                        } else {
                            validMove = true;
                        }
                    }
                } else { // the move that is being tried is not a diagonal move...
                    validMove = false;
                }
            }
        } //Black Bishup
        else if (pieceName.contains("BlackBishup")) {
            int newY = e.getY() / 75;
            int newX = e.getX() / 75;
            boolean inTheWay = false;
            int distance = Math.abs(startX - newX);
            if (((newX < 0) || (newX > 7)) || ((newY < 0) || (newY > 7))) {
                validMove = false;
            } else {
                validMove = true;
                if (Math.abs(startX - newX) == Math.abs(startY - newY)) {
                    if ((startX - newX < 0) && (startY - newY < 0)) {
                        for (int i = 0; i < distance; i++) {
                            if (piecePresent((initialX + (i * 75)), (initialY + (i * 75)))) {
                                inTheWay = true;
                            }
                        }
                    } else if ((startX - newX < 0) && (startY - newY > 0)) {
                        for (int i = 0; i < distance; i++) {
                            if (piecePresent((initialX + (i * 75)), (initialY - (i * 75)))) {
                                inTheWay = true;
                            }
                        }
                    } else if ((startX - newX > 0) && (startY - newY > 0)) {
                        for (int i = 0; i < distance; i++) {
                            if (piecePresent((initialX - (i * 75)), (initialY - (i * 75)))) {
                                inTheWay = true;
                            }
                        }
                    } else if ((startX - newX > 0) && (startY - newY < 0)) {
                        for (int i = 0; i < distance; i++) {
                            if (piecePresent((initialX - (i * 75)), (initialY + (i * 75)))) {
                                inTheWay = true;
                            }
                        }
                    }
                    if (inTheWay) {
                        validMove = false;
                    } else {
                        if (piecePresent(e.getX(), (e.getY()))) {
                            if (pieceName.contains("Black")) {
                                if (checkBlackOponent(e.getX(), e.getY())) {
                                    validMove = true;
                                } else {
                                    validMove = false;
                                }
                            } else {
                                if (checkWhiteOponent(e.getX(), e.getY())) {
                                    validMove = true;
                                } else {
                                    validMove = false;
                                }
                            }
                        } else {
                            validMove = true;
                        }
                    }
                } else { // the move that is being tried is not a diagonal move...
                    validMove = false;
                }
            }
        }
        //End of Bishup Code


//Changes to new pawn Piece and Validates Move

    if(!validMove){
        int location=0;
        if(startY ==0){
            location = startX;
        }
        else{
            location  = (startY*8)+startX;
        }
        String pieceLocation = pieceName+".png";
        pieces = new JLabel( new ImageIcon(pieceLocation) );
        panels = (JPanel)chessBoard.getComponent(location);
        panels.add(pieces);
    }
    else{
        if(success){

            if (c instanceof JLabel){
                Container parent = c.getParent();
                parent.remove(0);

                String promoteTo;
                do {
                    promoteTo = (String) JOptionPane.showInputDialog(null,
                        "Promote Pawn to :", "Pawn Promotion",
                        JOptionPane.QUESTION_MESSAGE, null,
                        new String[]{"Queen", "Bishup", "Knight", "Rook"}, "Queen");
                } while (promoteTo == null);
                String newPiece = null;
                int location = 0;
                if (pieceName.contains("White"))
                {
                    location = 56 + (e.getX()/75);
                    newPiece = "White"+promoteTo;
                }
                else
                {
                    location =  (e.getX()/75);
                    newPiece = "Black"+promoteTo;
                }

                pieces = new JLabel( new ImageIcon(newPiece+".png") );
                parent = (JPanel)chessBoard.getComponent(location);
                parent.add(pieces);
                validate();
                repaint();
            }
        }
        else{
            if (c instanceof JLabel){
                Container parent = c.getParent();
                parent.remove(0);
                parent.add( chessPiece );
            }
            else {
                Container parent = (Container)c;
                parent.add( chessPiece );
            }
            chessPiece.setVisible(true);
        }
    }
    }

    public void mouseClicked(MouseEvent e) {

    }

    public void mouseMoved(MouseEvent e) {
    }

    public void mouseEntered(MouseEvent e) {

    }

    public void mouseExited(MouseEvent e) {

    }

    public static void main(String[] args) {
        JFrame frame = new ChessProject();
        frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        frame.pack();
        frame.setResizable(true);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
\$\endgroup\$
3
  • 3
    \$\begingroup\$ Note that asking for code to be written is off-topic for Code Review. Answers provide advice, and may or may not include code. Please do not pester reviewers into writing code for you, if they haven't done so voluntarily. \$\endgroup\$ Commented Nov 6, 2014 at 12:53
  • \$\begingroup\$ What you really need is a tutorial on classes in Java. \$\endgroup\$ Commented Nov 6, 2014 at 13:53
  • \$\begingroup\$ This has also been posted at Stack Overflow: stackoverflow.com/questions/26779966/chess-code-split \$\endgroup\$ Commented Nov 6, 2014 at 13:57

4 Answers 4

11
\$\begingroup\$

You should separate the modelling of the game, board and pieces from the display components. (google: model-view-controller, separation of concerns).

  • You can create a Game class that models the game and the game-logic
  • You can create a Board class that models the internal state of the chess-board.
  • You can create a Piece class and subclasses for each Piece, e.g. Rook, King
  • You can create a Display class that uses this model to display a Board

All the UI interaction can be done in the Display class. All the game-logic should be in the Game class and should ask stuff from the Board. For example the check.. methods should go there. The movement checks can go into the Piece subclasses.

\$\endgroup\$
0
10
\$\begingroup\$

Lets start by naming:

  1. It should be clear that the frame doesn't have the name of the project, so instead of the class ChessProject you can call this class ChessFrame instead.
  2. It's all about separation of concerns, you should have seperate class that does the Chess logic and one that does the UI and use composition to use its features

    class ChessBoard{
       ...
    } 
    
    class ChessBoardFrame extends JFrame implements MouseListener, MouseMotionListener {
      private ChessBoard chessBoard;
    }
    
  3. Access modifiers are important: always try to hide your fields by declaring them private.

    private JLayeredPane layeredPane;
    private JPanel chessBoard;
    private JLabel chessPiece;
    
  4. Don't use magic numbers in your code, extract them to constants instead.

     final int sideSize = 600;
     Dimension boardSize = new Dimension(sideSize, sideSize);
    

    Especially in loops where the boundaries are hard to understand, don't assume the code maintainer is a professional chess player.

    for (int i = 8; i < 16; i++) {
     // extract those boundaries to constants 
    }
    
  5. Delete unnecessary code, replace

    if (((tmp1.contains("Black")))) {
        oponent = true;
    } else {
        oponent = false;
    }
    return oponent;
    

    By

    return temp1.contains("Black");
    
\$\endgroup\$
2
  • \$\begingroup\$ can you show me a move detailed example of say how i would go about separating the pieces from the main body of code ? \$\endgroup\$
    – Jamiex304
    Commented Nov 6, 2014 at 21:10
  • \$\begingroup\$ @Jamiex304 thejavageek.com/2013/08/11/… \$\endgroup\$ Commented Nov 6, 2014 at 22:22
3
+25
\$\begingroup\$

Here are two simple suggestions for improving code structure:

  1. Create base class for chess pieces abstract class Piece and subclasses for each of the pieces (e.g. class King extends Piece). Each class can then contain code that applies to the piece it represents. This will make it easier to maintain game logic in smaller self-contained chunks of code.

    class Position { /* ... */ }
    abstract class Piece
    {
        abstract boolean canMove(Position from, Position to);
        protected List<Piece> attackedBy() { return null; }   // shared code example
    }
    class King extends Piece
    {
        boolean canMove(Position from, Position to) { return false; }
    }
    
  2. Separate UI code from game logic. Put UI code into View classes. Make a view object for each piece on the board. Make game Controller class for working with both view objects and game state. Keep game state in Model class. Search for MVC to get further details about this approach.

\$\endgroup\$
3
\$\begingroup\$

Your code is procedural, yet still very elegant. I'll attempt to walk through a refactoring process to help you to think more object oriented. Also, be sure to include all of your classes within a package when you're programming in java.

The simplest change to start with is to begin isolating responsibilities

Move the public static void main method into its own class. This will form the aggregate root of our program once we separate out the business concerns from display concerns in the classes later on. For now, let's just copy exactly what you have.

jamiex304/chessgame/App.java

package jamiex304.chessgame;    
/* Imports ... */

public class App {    
    public static void main(String[] args) {
        JFrame frame = new ChessProject();
        frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        frame.pack();
        frame.setResizable(true);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }        
}

Next, let's begin extracting the objects from the system. Anything named as a noun is a likely candidate for becoming an object. Each object will be defined as a class in its own file. Because we are not yet separating the view from the behaviors, we'll keep the classes in the jamiex304.chessgame package for now.

jamiex304/chessgame/Board.java

package jamiex304.chessgame;
/* Imports ... */
public class Board extends JPanel {

}

jamiex304/chessgame/Square.java

package jamiex304.chessgame;
/* Imports ... */
public class Square extends JPanel {

}

jamiex304/chessgame/Piece.java

package jamiex304.chessgame;
/* Imports ... */    
public abstract class Piece extends JLabel {

}

Notice that we've only extracted a single abstract Piece at this point. There are 6 distinct pieces in a chess set. Each have special features such as shape and maneuvers, but we want to focus on the common features or interface of a Piece at this level.

Now, let's focus on moving the Board code from ChessProject. Again, we will focus on the isolating responsibilities.

1 Rather than implementing the MouseListener and MouseMotionListener interfaces, we'll encapsulate a MouseAdapter and delegate the mouse input responsibility to it. The current mouse interface methods are doing too much as can be seen by the number of global state variables they reference. We'll leave the definition of the MouseAdapter methods blank for now.

2 We'll keep the construction logic in the constructor, but separate the square initialization to it's own private method.

jamiex304/chessgame/Board.java

package jamiex304/chessgame/Board.class;
/* Imports ... */
public class Board extends JPanel {
    private class BoardMouseAdapter extends MouseAdapter {
        @Override
        public void mousePressed(MouseEvent e) { }

        @Override
        public void mouseDragged(MouseEvent e) { }

        @Override
        public void mouseReleased(MouseEvent e) { }
    }

    public Board() {
        BoardMouseAdapter mouseAdapter = new BoardMouseAdapter();
        addMouseListener(mouseAdapter);
        addMouseMotionListener(mouseAdapter);
        setLayout(new GridLayout(8, 8));

        initializeSquares();
    }

    private void initializeSquares() {
        for (int row = 1; row <= 8; row++) {
            for (char column = 'a'; column <= 'h'; column++) {
                Color squareColor = (row % 2 == column % 2) ? Color.white : Color.gray;
                Square square = new Square(squareColor);
                add(square);
            }
        }
    }
}

Notice I changed the loop for initializing the squares a little. The places on a chessboard are not just 64 squares, they are 8 rows and 8 columns of squares which are normally designated by an alphanumeric pair. Let the code reflect what we are virtualizing.

And we can see that square needs a color attribute. A square must have a color and will not change color after creation, so it belongs in the Square constructor. We'll update the class to match

jamiex304/chessgame/Square.java

package jamiex304.chessgame;
/* Imports ... */    
public class Square extends JPanel {
    Square(Color squareColor) {
        this.setBackground(squareColor);
    }
}

If you have found this answer to be helpful so far, then you have work to do. Follow along with your own project this far and continue pulling the code from your ChessProject.java file into the Square.java class to set up a square as well as the Piece.java class. Post what you arrive at as another code review and I will continue there.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.