HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpModerate

Enum, constants, or other to represent chess pieces

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
piecesrepresentenumchessotherconstants

Problem

I'm learning C# and I decided to write a chess program to help me practice the concepts I'm learning in my book. I started the Board class tonight, which is going to handle 1) the board state and 2) checking if moves are legal.

I feel like I need to give careful consideration to how I represent the board. I started with a list of constants:

// CONSTANTS
private const sbyte EMPTYSQUARE = 0;
private const sbyte WKING = 1;
private const sbyte WQUEEN = 2;
private const sbyte WROOK = 3;
private const sbyte WBISHOP = 4;
private const sbyte WKNIGHT = 5;
private const sbyte WPAWN = 6;
private const sbyte BKING = 7;
private const sbyte BQUEEN = 8;
private const sbyte BROOK = 9;
private const sbyte BBISHOP = 10;
private const sbyte BKNIGHT = 11;
private const sbyte BPAWN = 12;

private const sbyte GAMEINPROGRESS = 0;
private const sbyte CHECKMATEWHITE = 1;
private const sbyte CHECKMATEBLACK = 2;
private const sbyte NOLEGALMOVESDRAW = 3;
private const sbyte THREEMOVEDRAW = 4;
private const sbyte FIFTYMOVEDRAW = 5;
private const sbyte WHITERESIGNED = 6;
private const sbyte BLACKRESIGNED = 7;

// VARIABLES
private sbyte[,] board =
{
    {9, 11, 10, 8,  7,  10, 11, 9},
    {12,12, 12, 12, 12, 12, 12,12},
    {0, 0,  0,  0,  0,  0,  0,  0},
    {0, 0,  0,  0,  0,  0,  0,  0},
    {0, 0,  0,  0,  0,  0,  0,  0},
    {0, 0,  0,  0,  0,  0,  0,  0},
    {6, 6,  6,  6,  6,  6,  6,  6},
    {3, 5,  4,  2,  1,  4,  5,  3}
};


Then I realized I could use an enum here, which I hear is good practice so you don't go mixing up your "magic numbers":

private enum Piece
{
    EMPTY, WKING, WQUEEN, WROOK, WBISHOP, WKNIGHT, WPAWN, BKING, BQUEEN, BROOK, BBISHOP, BKNIGHT, BPAWN
}

private enum State
{
    GAMEINPROGRESS, CHECKMATEWHITE, CHECKMATEBLACK, NOLEGALMOVEDRAW, THREEMOVEDRAW, FIFTYMOVEDRAW, WHITERESIGNED, BLACKRESIGNED
}


I then go to declare the board array and I had to use this ugly-looking monstrosity:

```
private sbyte[,] board =
{
{(sbyte)Piece.BROOK, (sbyte)P

Solution

I think it definitely makes sense to use an object hierarchy here. What's the difference between a black and a white pawn? Its colour! (which will affect which way it can move relative to the board).

All pieces must have exactly one colour, and we have two to chose from:

public enum PieceColour
{
    White = 0,
    Black = 1
}


As we've already reasoned, all pieces have to have a colour and unless you've got a defective set, none of the pieces can change colour midway through. Sounds like we have an invariant that we want all pieces to obey. We can lock that up with a base class:

public abstract class Piece
{
    private readonly PieceColour colour;

    public PieceColour Colour { get { return colour; } }

    protected Piece(PieceColour colour)
    {
        this.colour = colour;
    }
}


By making the piece class abstract, we are saying "you can't have a generic Piece, you have to have a specialized subclass". Let's see what that some of those might look like:

public class Pawn : Piece
{
    public Pawn(PieceColour colour)
        : base(colour)
    {
    }
}

public class Rook : Piece
{
    public Rook(PieceColour colour)
        : base(colour)
    {
    }
}

public class Knight : Piece
{
    public Knight(PieceColour colour)
        : base(colour)
    {
    }
}


Now you can start playing around with a board. To be completely honest, I haven't thought enough about it to figure out how I'd really want it to look but something like the following would be enough to get along with. Tuple is just a convenient wrapper around two ints (the coordinates of a space).

public class Board
{
    private Dictionary, Piece> currentState;

    public static Board CreateNewBoard()
    {
        var board = new Board();

        board.currentState = new Dictionary, Piece> 
        {                      // x, y
            { new Tuple(0, 0), new Rook(PieceColour.White) },
            { new Tuple(1, 0), new Knight(PieceColour.White) }
            // etc. 
        };

        return board;
    }
}


}

Any common behaviour you should find behind all pieces you should add it to the base class Piece, for example they can all move...

Edit

I thought the above made it clear that I think there should be an abstract method on the piece class that deals with movement. I didn't commit to making a suggestion on the signature of the method because I haven't seen what you're doing currently. I have the impression OP intends on "moving pieces" entirely within the board class.

Code Snippets

public enum PieceColour
{
    White = 0,
    Black = 1
}
public abstract class Piece
{
    private readonly PieceColour colour;

    public PieceColour Colour { get { return colour; } }

    protected Piece(PieceColour colour)
    {
        this.colour = colour;
    }
}
public class Pawn : Piece
{
    public Pawn(PieceColour colour)
        : base(colour)
    {
    }
}

public class Rook : Piece
{
    public Rook(PieceColour colour)
        : base(colour)
    {
    }
}

public class Knight : Piece
{
    public Knight(PieceColour colour)
        : base(colour)
    {
    }
}
public class Board
{
    private Dictionary<Tuple<int, int>, Piece> currentState;

    public static Board CreateNewBoard()
    {
        var board = new Board();

        board.currentState = new Dictionary<Tuple<int, int>, Piece> 
        {                      // x, y
            { new Tuple<int, int>(0, 0), new Rook(PieceColour.White) },
            { new Tuple<int, int>(1, 0), new Knight(PieceColour.White) }
            // etc. 
        };

        return board;
    }
}

Context

StackExchange Code Review Q#73721, answer score: 11

Revisions (0)

No revisions yet.