OOP Design for Chess Game in Java (Trouble with Pi

2020-07-13 12:06发布

问题:

I'm trying to write my own chess game in Java. I've started writing the classes and my high level idea is as follows:

I have a Piece class with these fields:

private String name;
private String color;

Originally I was going to have an x and y coordinate for each piece but that seems like it's more a property of the board. Which brings me to...

I have a Board class with a field like this:

Piece[][] myBoard = new Piece[8][8];

I'm not really sure where / how I should be keeping track of where pieces are. As of now, I just have a 2d array of Piece objects. However, I think this'll present some challenges. For instance, say a user clicks on a piece, wants to move it. I need to figure out whether the move is valid and for that, I'll need the current square the piece is on.

If I have an x and y coordinate for each piece, I'm updating the state of the game in two places (in the Board class's 2d array) and the current piece's x and y coordinates. This seems bad...

Any suggestions?

Thanks for the help, Mariogs

回答1:

I can help, as I've written a complete chess engine in Java you can find here

A few things to consider:

Instead of having your board be an 8x8 array of pieces, why not have a single dimensional array of 64 Tile's. The Tile class can be abstract and have two sub classes, OccupiedTile and EmptyTile. Each tile can have an integer coordinate, numbered 0 to 63, and OccupiedTiles also have a Piece on them.

Originally I was going to have an x and y coordinate for each piece but that seems like it's more a property of the board. Which brings me to...

It is convenient for a piece to 'know' it's position, and so tracking this with an integer field in piece is, imho, not a bad thing.

Piece should also have sub classes like Knight, Bishop, Pawn, Rook, Queen, and King. That way their toString() method can return a fixed value for the pieceName, instead of tracking it as a member field

Lastly, why not have enum called Alliance to track White or Black pieces. String is pretty flimsy for the job, as the caller can pass it any value it wants really. See my version of Alliance.

I create a piece like this in my program:

King king = new King(Alliance.BLACK, 4);

which I think is pretty readable.



回答2:

Your Piece[8][8] approach seems adequate for tracking the positions of the pieces (except that I would rather make it its own class, with an array inside of it, you will probably want it to have more logic sooner or later than just setting and moving pieces). As to determining where a piece can move, that seems like a function of the actual piece:

public class BoardCoordinates {
   public final char vertical;
   public final int horizontal;
   public BoardCoordinates(char v, int h) { vertical = v; horizontal = h; }
}
public class Board {
    private Piece[8][8] state = new Piece[8][8]{};
    public Piece at(BoardCoordinates c) { 
        state[c.vertical - 'a'][c.horizontal];
    }
    public void set(Piece what, BoardCoordinates where) { 
        state[where.vertical - 'a'][where.horizontal] = what;
    }
    public void move(BoardCoordinates from, BoardCoordinates to) {
        set(at(from), to);
        set(null, from);           
    }
}

public class Piece {
    ....
    public List<BoardCoordinates> findMoves(BoardCoordinates from, Board theBoard) {
        ... 
    }
}

Most of the time, you won't need the second argument, but it will be necessary to handle special cases - like castling or en passant - where the possibility of a move depends on other pieces on the board (you actually need even more info to handle en passant properly, but it's not much to do with the question at hand.

I definitely agree with your assement of keeping coordinates in each piece, it does sound like a terrible idea.



回答3:

There is another object that could be missing from your description: the BoardTile. Every BoardTile knows its location, deduces its color, and its neighbor tiles. It also knows if it is empty or has any Piece on it. In addition, the BoardTile and the Board know each other (obviously!)

Given that the behavior of a Piece strongly depends on its position in the Board, it should know in which tile it. Thus, when you first put all the pieces in the Board, the Board should assign the corresponding tile to each Piece (note however that this knowledge corresponds to the rules of the ChessGame, not the Board as you might want to use the Board and Pieces for, say, a variation of Chess.) Similarly, when a Piece is taken out from the Board (presumably by the ChessGame), the Piece should lose its tile (by annihilating it.)

With these three objects you will have several alternatives. For instance, a Piece could learn its position by answering the location of its tile. The Board could know the position of each Piece by inquiring its tiles, etc.



标签: java oop