Skip to Content
Course content

154: Building a Simple Chess Move Validator

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Think of a chess move validator like a strict bouncer at a high-end club. The bouncer doesn't care who you are; they only care if you meet the specific criteria on their clipboard. "Are you on the list? Are you wearing the right shoes? Is your ID valid?" If any one of those is a "no," you aren't getting in. The bouncer doesn't try to guess where you wanted to go; they just compare your current state against a set of rigid rules and give a binary yes or no.

In C#, our validator works exactly the same way. We aren't simulating the whole game or handling the UI here. We are building a "bouncer" method that takes a starting position and an ending position, looks at the piece involved, and returns a bool. If the move violates the rules of that piece, the bouncer kicks the move out.

Defining the Coordinate System

Before we can validate a move, we need a way to talk about where things are. I find that using a record is the cleanest way to handle this in modern C#. It's lightweight and gives us value-based equality out of the box, which is perfect for a 2D grid.

public record Position(int Row, int Col);

Now, we can represent a move as a pair of these positions. If we're moving from Row 0, Col 0 to Row 0, Col 5, we know we've moved horizontally. This simple structure prevents us from passing around loose integers and getting our X and Y coordinates swapped—a mistake I've made more times than I'd like to admit.

Enforcing the Rook's Straight-Line Rule

Let's build the logic for the Rook. A Rook is simple: it can move any number of squares, but it must stay in the same row or the same column. It can't do both, and it certainly can't move diagonally.

I like to write these as "Guard Clauses." Instead of one giant if statement, we check for the valid conditions. For a Rook, the rule is: (start.Row == end.Row) OR (start.Col == end.Col). If neither of those is true, the move is illegal.

public bool IsRookMoveValid(Position start, Position end)
{
    // A piece can't move to the spot it's already standing on
    if (start == end) return false;

    // The Rook must move either vertically or horizontally
    bool isHorizontal = start.Row == end.Row;
    bool isVertical = start.Col == end.Col;

    return isHorizontal || isVertical;
}

The Bishop's Diagonal Logic

The Bishop is a bit trickier. It doesn't care about rows or columns individually; it cares about the relationship between them. For a move to be diagonal, the distance moved vertically must be exactly equal to the distance moved horizontally.

This is where Math.Abs becomes your best friend. We don't care if the Bishop is moving up-left or down-right; we only care about the absolute difference between the coordinates.

public bool IsBishopMoveValid(Position start, Position end)
{
    if (start == end) return false;

    int rowDiff = Math.Abs(start.Row - end.Row);
    int colDiff = Math.Abs(start.Col - end.Col);

    // In a perfect diagonal, the change in Row equals the change in Col
    return rowDiff == colDiff;
}

Notice how we're keeping these methods pure. They don't change the state of the board; they just answer a question. This makes them incredibly easy to unit test. You can feed in a hundred different start and end positions and verify the output without ever having to actually "set up" a game board.




📋 Practical Task

Exercise: Implementing the Knight's "L-Shape" Constraint

The Knight is the most unique piece in chess because it doesn't move in a straight line. Its movement is always an "L" shape: it moves two squares in one cardinal direction and then one square perpendicularly. In mathematical terms, if the change in rows is 2, the change in columns must be 1 (or vice versa).

Your Task: Create a method called IsKnightMoveValid that takes two Position records (start and end). The method should return true only if the move follows the Knight's L-shape rule. Otherwise, it should return false.

Requirements:

  • Use Math.Abs to calculate the differences between rows and columns.
  • Ensure the move isn't to the same square.
  • Verify that one axis changed by 2 and the other axis changed by 1.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.