Java programming - Chess moves (basic, no AI)

Smooth Operator picture Smooth Operator · Jan 5, 2011 · Viewed 42.3k times · Source

I need help in designing a Chess game. I've already started but haven't got far as I'm pretty new to Java, new to programming at all actually.

Anyway, I have my abstract class Piece and the various pieces as subclasses. I have a method movePiece, in my abstract class, which I want to define for all subclasses.

All it currently does is move the piece from one square to another. I have a Square class which can hold a Piece object, the board consists of a 64x1 Square array.

I know how pieces move, but how do I actually do the programming? I want to try to apply the MVC pattern but this is really the first time I will be using patterns.

Basically I was thinking on using Graphics2D to create a box for each Square. Then when a player clicks a piece, the squares that are available as destination after the move will be outlined in some colour. After the player clicks one of these squares, the code that I already have in my movePiece method will run.

What I want to do is override my movePiece method in each subclass of Piece. The question is, how could the code look in one of these methods? take the Pawn subclass for example.

I'm not asking for code to copy/paste, just some pointers on how to do this, eventually some sample code.

Thanks!

public class Game {


@SuppressWarnings("unused")
public static void main(String[] args){
    Board board = new Board();
} }

public class Board {

Square[] grid;

public Board(){
    grid = new Square[64];
}   
public Square getSquare(int i){
    return grid[i];
}   
public void setDefault(){

}   
public Boolean isMoveValid(){
    return null;    
} }

public class Square {

private Piece piece;

public void addPiece(Piece pieceType, String pieceColour, String pieceOwner) 
        throws ClassNotFoundException, InstantiationException, IllegalAccessException{

    PieceFactory factory = new PieceFactory();
    Piece piece = factory.createPiece(pieceType);

    piece.setColour(pieceColour);
    piece.setOwner(pieceOwner);

    this.piece = piece; 
}
public void addPiece(Piece pieceType){ 
    this.piece = pieceType; 
}
public void removePiece(){  
    piece = null;
}
public Piece getPiece(){
    return piece;       
}

class PieceFactory {     
     @SuppressWarnings("rawtypes")
     public Piece createPiece(Piece pieceType) 
            throws ClassNotFoundException, InstantiationException, IllegalAccessException{
         Class pieceClass = Class.forName(pieceType.toString());
         Piece piece = (Piece) pieceClass.newInstance();

         return piece;       
     } }

public void setColour(String colour){

} }

public abstract class Piece {

Board board;

public void setColour(String pieceColour) {
}

public void setOwner(String pieceOwner) {
}

public String getColour() {
    return "";
}

public String getOwner() {
    return "";      
}
public void movePiece(int oldIndex, int newIndex){
    board.getSquare(oldIndex).removePiece();
    board.getSquare(newIndex).addPiece(this);
}
public String toString(){
    return this.getClass().getSimpleName();
} }

You wanted to see the code, very basic I know. And I will change the [64] to [8][8]. I'm trying to not make it harder then it has to be. I can probably combine Colour and Owner as an attribute and make it an enum (either BLACK or WHITE).

Sorry if the formatting isn't good.

Answer

meriton picture meriton · Jan 6, 2011

When designing software, I find it helpful to think about how I would use a method, then write down the method signature (and if you do test driven development, the unit test), and only then think about how I would implement it.

Doing this here, I find that the requirement

Then when a player clicks a piece, the squares that are available as destination after the move will be outlined in some colour.

is impossible to satisfy with a method like

void move(Square destination);

because there is no way to find out the possible moves without actually making them. To highlight the squares, it would probably be best if we had a method like

Collection<Square> getPossibleMoves();

and then we could implement

void move(Square destination) {
    if (!getPossibleMoves().contains(destination) {
        throw new IllegalMoveException();
    }

    this.location.occupyingPiece = null;
    this.location = destination;
    this.location.occupyingPiece = this;
}

as for implementing getPossibleMoves:

class Pawn extends Piece {
    @Override Collection<Square> getPossibleMoves() {
        List<Square> possibleMoves = new ArrayList<Square>();
        int dy = color == Color.white ? 1 : -1;
        Square ahead = location.neighbour(0, dy);
        if (ahead.occupyingPiece == null) {
            possibleMoves.add(ahead);
        }
        Square aheadLeft = location.neighbour(-1, dy);
        if (aheadLeft != null && aheadLeft.occupyingPiece != null && aheadLeft.occupyingPiece.color != color) {
            possibleMoves.add(aheadLeft);
        }
        Square aheadRight = location.neighbour(1, dy);
        if (aheadRight != null && aheadRight.occupyingPiece != null && aheadRight.occupyingPiece.color != color) {
            possibleMoves.add(aheadRight);
        }
        return possibleMoves;
    }
}

Edit:

class Knight extends Piece {
    @Override Collection<Square> getPossibleMoves() {
        List<Square> possibleMoves = new ArrayList<Square>();
        int[][] offsets = {
            {-2, 1},
            {-1, 2},
            {1, 2},
            {2, 1},
            {2, -1},
            {1, -2},
            {-1, -2},
            {-2, -1}
        };
        for (int[] o : offsets) {
            Square candidate = location.neighbour(o[0], o[1]);
            if (candidate != null && (candidate.occupyingPiece == null || candidate.occupyingPiece.color != color)) {
                possibleMoves.add(candidate);
            }
        }
        return possibleMoves;
    }
}