Horje
Knight’s Tour Problem in C

Knight’s Tour problem is a classic puzzle in which the goal is to move a knight on a chessboard such that the knight visits every square exactly once. The knight moves in an L-shape: two squares in one direction and then one square perpendicular to that or vice versa. In this article, we will learn how to solve this problem in C language.

Knight'sTour

Valid Moves of Knight

Example:

Consider a 8×8 chessboard, and the knight starts at position (0, 0). The goal is to find a sequence of moves that allows the knight to visit each square exactly once.

Input: 8

Output:
0 59 38 33 30 17 8 63
37 34 31 60 9 62 29 16
58 1 36 39 32 27 18 7
35 48 41 26 61 10 15 28
42 57 2 49 40 23 6 19
47 50 45 54 25 20 11 14
56 43 52 3 22 13 24 5
51 46 55 44 53 4 21 12

To solve the Knight’s Tour problem there are two primary methods: Backtracking and Warnsdorff’s Rule. Here, we will discuss both methods using the C programming language.

Knight’s Tour using Backtracking in C

As we know a knight can move in the cells which are shown in the above image in his single move. Suppose the current position of the knight is (i,j) then his possible moves are :

(i+2 , j+2), (i+2, j+2), (i-1,j+2), (i-2, j+1), (i-2, j-1), (i-1 , j-2), (i+1 , j-2), (i+2, j-1)

So, to solve this kind of problem where we will need to try each of given options backtracking is the best strategy, where we try all possible moves for the knight and backtrack if we reach an invalid state. This method ensures that we explore all potential solutions.

Approach

  • Create an empty solution matrix to track the knight’s path.
  • Place the knight at the starting position.
  • Try all possible moves from the current position.
  • If a move is valid, mark the move in the solution matrix.
  • Recursively attempt to solve the tour from the new position.
  • If the tour is complete, return the solution.
  • If no valid moves are available, backtrack and try the next move.

C Program to Solve Knight’s Tour using Backtracking

The below program demonstrates how we can solve the Knight’s tour problem using backtracking in C language.

C
// C Program to Solve Knight’s Tour using Backtracking

#include <stdio.h>

#define N 8

// Function to check if (x, y) is a valid move for the
// knight
int isSafe(int x, int y, int sol[N][N])
{
    return (x >= 0 && x < N && y >= 0 && y < N
            && sol[x][y] == -1);
}

// Function to print the solution matrix
void printSolution(int sol[N][N])
{
    for (int x = 0; x < N; x++) {
        for (int y = 0; y < N; y++)
            printf(" %2d ", sol[x][y]);
        printf("\n");
    }
}

// Utility function to solve the Knight's Tour problem
int solveKTUtil(int x, int y, int movei, int sol[N][N],
                int xMove[N], int yMove[N])
{
    int k, next_x, next_y;
    if (movei == N * N)
        return 1;

    // Try all next moves from the current coordinate x, y
    for (k = 0; k < 8; k++) {
        next_x = x + xMove[k];
        next_y = y + yMove[k];
        if (isSafe(next_x, next_y, sol)) {
            sol[next_x][next_y] = movei;
            if (solveKTUtil(next_x, next_y, movei + 1, sol,
                            xMove, yMove)
                == 1)
                return 1;
            else
                // Backtracking
                sol[next_x][next_y] = -1;
        }
    }
    return 0;
}

// This function solves the Knight's Tour problem using
// Backtracking
int solveKT()
{
    int sol[N][N];

    // Initialization of solution matrix
    for (int x = 0; x < N; x++)
        for (int y = 0; y < N; y++)
            sol[x][y] = -1;

    // xMove[] and yMove[] define the next move of the
    // knight xMove[] is for the next value of x coordinate
    // yMove[] is for the next value of y coordinate
    int xMove[8] = { 2, 1, -1, -2, -2, -1, 1, 2 };
    int yMove[8] = { 1, 2, 2, 1, -1, -2, -2, -1 };

    // Starting position of knight
    sol[0][0] = 0;

    // Start from (0, 0) and explore all tours using
    // solveKTUtil()
    if (solveKTUtil(0, 0, 1, sol, xMove, yMove) == 0) {
        printf("Solution does not exist");
        return 0;
    }
    else
        printSolution(sol);

    return 1;
}

int main()
{
    solveKT();
    return 0;
}


Output

  0  59  38  33  30  17   8  63 
37 34 31 60 9 62 29 16
58 1 36 39 32 27 18 7
35 48 41 26 61 10 15 28
42 57 2 49 40 23 6 19
47 50 45 54 25 20 11 14
56 43 52 3 22 13 24 5
51 46 55 44 53 4 21 12

Time Complexity: O(8N^2), as there are N^2 Cells and for each, we have a maximum of 8 possible moves to choose from, so the worst running time is .
Auxiliary Space: O(N^2)

Knight’s Tour using Warnsdorff’s Algorithm in C

Warnsdorff’s rule is a heuristic method to solve the Knight’s Tour problem. The rule says that the knight should always move to the square from which the knight will have the fewest onward moves. We cannot count steps that return to a square that has already been visited when calculating the number of onward moves for each candidate square. 

Approach

  • Set P to be a random initial position on the board
  • Mark the board at P with the move number “1”
  • Do following for each move number from 2 to the number of squares on the board: 
    • let S be the set of positions accessible from P.
    • Set P to be the position in S with minimum accessibility
    • Mark the board at P with the current move number
  • Return the marked board — each square will be marked with the move number on which it is visited.

C Program to Solve Knight’s Tour using Warnsdorff’s Rule

The below program demonstrates how we can solve the Knight’s tour problem using Warnsdorff’s algorithm in C language.

C
// C Program to Solve Knight’s Tour using Warnsdorff’s Rule

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define N 8

// Move pattern on basis of the change of
// x coordinates and y coordinates respectively
static int cx[N] = { 1, 1, 2, 2, -1, -1, -2, -2 };
static int cy[N] = { 2, -2, 1, -1, 2, -2, 1, -1 };

// function restricts the knight to remain within
// the 8x8 chessboard
bool limits(int x, int y)
{
    return ((x >= 0 && y >= 0) && (x < N && y < N));
}

/* Checks whether a square is valid and empty or not */
bool isempty(int a[], int x, int y)
{
    return (limits(x, y)) && (a[y * N + x] < 0);
}

/* Returns the number of empty squares adjacent to (x, y) */
int getDegree(int a[], int x, int y)
{
    int count = 0;
    for (int i = 0; i < N; ++i)
        if (isempty(a, (x + cx[i]), (y + cy[i])))
            count++;

    return count;
}

// Picks next point using Warnsdorff's heuristic.
// Returns false if it is not possible to pick next point.
bool nextMove(int a[], int* x, int* y)
{
    int min_deg_idx = -1, c, min_deg = (N + 1), nx, ny;

    // Try all N adjacent of (*x, *y) starting from a random
    // adjacent. Find the adjacent with minimum degree.
    int start = rand() % N;
    for (int count = 0; count < N; ++count) {
        int i = (start + count) % N;
        nx = *x + cx[i];
        ny = *y + cy[i];
        if ((isempty(a, nx, ny))
            && (c = getDegree(a, nx, ny)) < min_deg) {
            min_deg_idx = i;
            min_deg = c;
        }
    }

    // If we could not find a next cell
    if (min_deg_idx == -1)
        return false;

    // Store coordinates of next point
    nx = *x + cx[min_deg_idx];
    ny = *y + cy[min_deg_idx];

    // Mark next move
    a[ny * N + nx] = a[(*y) * N + (*x)] + 1;

    // Update next point
    *x = nx;
    *y = ny;

    return true;
}

/* displays the chessboard with all the legal knight's moves
 */
void print(int a[])
{
    for (int i = 0; i < N; ++i) {
        for (int j = 0; j < N; ++j)
            printf("%2d\t", a[j * N + i]);
        printf("\n");
    }
}

/* checks its neighbouring squares */
/* If the knight ends on a square that is one knight's move
 * from the beginning square, then tour is closed */
bool neighbour(int x, int y, int xx, int yy)
{
    for (int i = 0; i < N; ++i)
        if (((x + cx[i]) == xx) && ((y + cy[i]) == yy))
            return true;

    return false;
}

/* Generates the legal moves using Warnsdorff's heuristics.
 * Returns false if not possible */
bool findClosedTour()
{
    // Filling up the chessboard matrix with -1's
    int a[N * N];
    for (int i = 0; i < N * N; ++i)
        a[i] = -1;

    // Random initial position
    int sx = rand() % N;
    int sy = rand() % N;

    // Current points are same as initial points
    int x = sx, y = sy;
    a[y * N + x] = 1; // Mark first move.

    // Keep picking next points using Warnsdorff's heuristic
    for (int i = 0; i < N * N - 1; ++i)
        if (nextMove(a, &x, &y) == 0)
            return false;

    // Check if tour is closed (Can end at starting point)
    if (!neighbour(x, y, sx, sy))
        return false;

    print(a);
    return true;
}

int main()
{
    // To make sure that different random initial positions
    // are picked.
    srand(time(NULL));

    // While we don't get a solution
    while (!findClosedTour()) {
        ;
    }

    return 0;
}


Output

45       8      27      24      41      10      29      14
26 23 44 9 28 13 42 11
7 46 25 40 43 52 15 30
22 39 56 51 48 31 12 53
57 6 47 32 61 54 49 16
38 21 60 55 50 33 62 1
5 58 19 36 3 64 17 34
20 37 4 59 18 35 2 63

Time complexity: O(N^3)
Auxiliary Space: O(N^2)




Reffered: https://www.geeksforgeeks.org


C Language

Related
nextafter() Function in C nextafter() Function in C
copysign() Function in C copysign() Function in C
scalbn() Function in C scalbn() Function in C
Floyd-Warshall Algorithm in C Floyd-Warshall Algorithm in C
fdim() Function in C fdim() Function in C

Type:
Geek
Category:
Coding
Sub Category:
Tutorial
Uploaded by:
Admin
Views:
22