开发者

Java programming - Chess moves (basic, no AI)

开发者 https://www.devze.com 2023-02-02 11:26 出处:网络
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.

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.getS开发者_Go百科quare(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.


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;
    }
}


The way you describe it, more than a movePiece method you need a getPossibleMoves method that gives you all the places you can move to. Alternatively or additionally a moveAllowed method for a piece that tells you whether it is allowed for a piece to move to tha given location.

Instead of using raw (x,y) coordinates, you could create a class to define a Location in the board. This could provide you with methods to translate a Location into "chess coordinates" as used in chess literature. A Location would be constructed as new Location(x, y).

Also I'd rather go with a Board class that represents the 8x8 cell board and is the container for pieces, and can have a richer logic than just an array (e.g. could give you a pathClear(from, to) that tells you whether there aren't any pieces blocking your passage from one Location to another) etc.


I would do a isValidMove(Board boardState, int square) abstract method, which would be overriden in each piece and called to highlight the valid movements (in each drawing iteration.) This same method would be called in movePiece(int square) to would check if the move is valid, and perform the movement if it is so. In fact, the movePiece method would belong to the Board itself (and would call the Piece.isValidMove(...) to check.)

Pawn's isValidMove would be something like (note this is pseudo-code):

if ( boardState.getSquare(square).isFree() && square == this.square+ONE_FILE)
    return true;
else
    return false;


I would create a method called getValidMoves() that returns the list of all possible moves for a given piece. That way you don't have to loop over the whole board to find the squares to highlight. I'd also make the base class abstract so that methods such this don't need a base implementation.


I'm just finishing my own chessgame. Here are some tips/points for you I want to share.

Remember, Java is object oriented language, divide the game in to logical objects and interact with methods.

Keep methods as simple as possible (like always). Make human readable code. Sometimes! 8 different methods to check for pieces(King) available moves are more readable then some cryptic for-sentence trying to do all that calculation work.

You wanted to apply MVC pattern, you might want to consider your gui to be also your controller which has a reference to your actual board.

Piece.java protected List allowedSquares; public abstract void calculateAllowedSquares(ChessBoard chessBoard); public void move(ChessBoard chessBoard, Square fromSquare, Square toSquare)

In King class you may need to override the move-method. For example in castling move, you need move the rook at the same time.

  • You will need to know also from where you are moving (check rule for passant move) also probably you will need to clear the "fromSquare" of your move since you are using [][] board.

Two major issues in the whole concept of making chess game are: 1. How you eliminate moves which exposes your own king to check. Sometimes pieces can't move at all. 2. How you allow a piece to move only for protecting your king in check situations. Meaning if for.ex bishop is threatning your king and you can move some piece to block that threat but nowhere else.

And lastly I advise you to create your gui hand in hand with your logic. It is a big help when you click your piece(or square where the piece is) and you can immediately see on the screen what are the available squares. It saves you hours and hours of debugging.


you gotta slow down!

first you should make a class for each item and add possible moves for each one and also implement a method for checking possible moves during the game , then use Netbeans GUI and add some JLabels and change their color to white and black, so you can have a good view of the whole process.

just start , don't ever hesitate about removing old codes and changing them with new better codes. that's how it works dude.

good luck.

0

精彩评论

暂无评论...
验证码 换一张
取 消