javaarraysmultidimensional-arraychess

Placing numbers in a 2D array by a chess knight move pattern in Java using recursion


public class ChessComplete 
{
    private int size;
    private int[][] board;
    private long callNum;
    
    public ChessComplete(int size)//constructor with 2D array size as a parameter
    {
        this.size = size;
        board = new int [size][size];
        board[0][0] = 1;
    }

    // To check the if the number that is added is in the 2D array is in  bound
    public boolean isValid(int r, int c)
    {
        if (r < 0 || c < 0 || r >= size || c >= size)
        {
            return false;
        }
        return true;
    }
    
    /*
     * Move through the 2D array by placing the consecutive number for each (row,col) until its full
     * Moves Are only allowed in a chess knight pattern
     */
    public boolean move(int r, int c, int count) {
        callNum++;

        if (!isValid(r, c)) {
            return false;
        }

        if (count == (size * size))  // Base case if count reaches the end of 2D array
        {
            return true;
        }

        board[r][c] = count;  // fills the position with the current count

        if (board[r][c] == 0) {
            return false; 
        }

        // Check if each possible move is valid or not
        if (board[r][c] != 0) {
            for (int i = 0; i < 8; i++) {
                int X[] = { 2, 1, -1, -2, -2, -1, 1, 2 };
                int Y[] = { 1, 2, 2, 1, -1, -2, -2, -1 };

                // Position of knight after move
                int x = r + X[i];
                int y = c + Y[i];

                if (move(x, y, count + 1)) {
                    return move(x, y, count + 1);
                }
            }
        }

        board[r][c] = 0;
        return false;
    }

    public long getSteps()   // Number of recursive trials
    {
        return callNum;
    }

    public void displayBoard()
    {
        String s = " ";

        for (int r = 0; r < size; r++)
        {
            for(int c = 0; c < size; c++)
            {
                System.out.print(board[r][c] + " ");
            }

            System.out.println();
        }
    }
}

The output is:

1,  0,  0,  0,  0, 

0,  0,  0,  23, 0, 

0,  2,  0,  0,  0, 

0,  0,  0,  0, 24, 

0,  0,  3,  0,  0 

Recursive method call count: 78,293,671

Explanation

Notice at position (row, column) (0, 0) there is a 1 and at position (2, 1) there is a 2. As you can see, the knight in chess board moves in a similar way. In this way We need to populate the whole 2D array with consecutive numbers such that it strictly follows the knight pattern.

The problem

I don't get why the whole 2D array is not being filled with all other consecutive numbers. For instance, after filling the position with 3 in the 2D array, the numbers skips all the way to 23.


Solution

  • You aren't checking that the square is unoccupied before performing the move, so your solution includes duplicate moves which write over each other.

    Change isValid to check that the target square is empty:

    public boolean isValid(int r, int c) {
        if (r < 0 || c < 0 || r >= size || c >= size || board[r][c] != 0) {
            return false;
        }
        return true;
    }
    

    ... and remove the initialisation step board[0][0] = 1; in the constructor (it should be set by the first call to move).

    Additionally (but not fatally),

    if (move(x, y, count + 1)) {
        return move(x, y, count + 1);
    }
    

    Should be

    if (move(x, y, count + 1)) {
        return true;
    }
    

    And the checks if (board[r][c] == 0) and if (board[r][c] != 0) don't do anything because they occur just after you've set board[r][c] = count;.