Knight's tour problem



What is Knight's tour problem?

In the knight's tour problem, we are given with an empty chess board of size NxN, and a knight. In chess, the knight is a piece that looks exactly like a horse. Assume, it can start from any location on the board. Now, our task is to check whether the knight can visit all of the squares on the board or not. When it can visit all of the squares, then print the number of jumps needed to reach that location from the starting point.

There can be two ways in which a knight can finish its tour. In the first way, the knight moves one step and returns back to the starting position forming a loop which is called a closed tour. In the second way i.e. the open tour, it finishes anywhere in the board.

For a person who is not familiar with chess, note that the knight moves in a special manner. It can move either two squares horizontally and one square vertically or two squares vertically and one square horizontally in each direction. So, the complete movement looks like English letter 'L'.

Knight's Move

Suppose the size of given chess board is 8 and the knight is at the top-left position on the board. The next possible moves are shown below −

Knight's Solution

Each cell in the above chess board holds a number, that indicates where to start and in how many moves the knight will reach a cell. The final values of the cell will be represented by the below matrix −

  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 

Remember, this problem can have multiple solutions, the above matrix is one possible solution.

One way to solve the knight's tour problem is by generating all the tours one by one and then checking if they satisfy the specified constraint or not. However, it is time consuming and not an efficient way.

Backtracking Approach to Solve Knight's tour problem

The other way to solve this problem is to use backtracking. It is a technique that tries different possibilities until a solution is found or all options are tried. It involves choosing a move, making it, and then recursively trying to solve the rest of the problem. If the current move leads to a dead end, we backtrack and undo the move, then try another one.

To solve the knight's tour problem using the backtracking approach, follow the steps given below −

  • Start from any cell on the board and mark it as visited by the knight.

  • Move the knight to a valid unvisited cell and mark it visited. From any cell, a knight can take a maximum of 8 moves.

  • If the current cell is not valid or not taking to the solution, then backtrack and try other possible moves that may lead to a solution.

  • Repeat this process until the moves of knight are equal to 8 x 8 = 64.

Example

In the following example, we will practically demonstrate how to solve the knight's tour problem.

#include <stdio.h>
#define N 8
int sol[N][N];
//check place is in range and not assigned yet
int isValid(int x, int y) {    
   return ( x >= 0 && x < N && y >= 0 && y < N && sol[x][y] == -1);
}
void displaySolution() {
   printf("The possible solution: \n");    
   for (int x = 0; x < N; x++) {
      for (int y = 0; y < N; y++)
         printf("%3d ", sol[x][y]);
      printf("\n");
   }
}
int knightTour(int x, int y, int move, int xMove[N], int yMove[N]) {
   int xNext, yNext;
   //when the total board is covered
   if (move == N*N)     
      return 1;
   for (int k = 0; k < 8; k++) {
      xNext = x + xMove[k];
      yNext = y + yMove[k];
      //check room is preoccupied or not
      if (isValid(xNext, yNext)) {     
         sol[xNext][yNext] = move;
         if (knightTour(xNext, yNext, move+1, xMove, yMove) == 1)
            return 1;
         else
            // backtracking
            sol[xNext][yNext] = -1;
      }
   }
   return 0;
}
int findKnightTourSol() {
   //initially set all values to -1 of solution matrix    
   for (int x = 0; x < N; x++)     
      for (int y = 0; y < N; y++)
         sol[x][y] = -1;
   //all possible moves for knight
   int xMove[8] = {  2, 1, -1, -2, -2, -1,  1,  2 };
   int yMove[8] = {  1, 2,  2,  1, -1, -2, -2, -1 };
   //starting from room (0, 0)
   sol[0][0]  = 0;     
   if (knightTour(0, 0, 1, xMove, yMove) == 0) {
      printf("Solution does not exist");
      return 0;
   } else
      displaySolution();
   return 1;
}
int main() {
   findKnightTourSol();
   return 0;
}
#include <iostream>
#include <iomanip>
#define N 8
using namespace std;
int sol[N][N];
 //check place is in range and not assigned yet
bool isValid(int x, int y, int sol[N][N]) {    
   return ( x >= 0 && x < N && y >= 0 && y < N && sol[x][y] == -1);
}
void displaySolution() {
   cout << "The possible solution: " << endl;    
   for (int x = 0; x < N; x++) {
      for (int y = 0; y < N; y++)
         cout << setw(3) << sol[x][y] << " ";
      cout << endl;
   }
}
int knightTour(int x, int y, int move, int sol[N][N], int xMove[N], int yMove[N]) {
   int xNext, yNext;
   //when the total board is covered
   if (move == N*N)     
      return true;
   for (int k = 0; k < 8; k++) {
      xNext = x + xMove[k];
      yNext = y + yMove[k];
      //check room is preoccupied or not
      if (isValid(xNext, yNext, sol)) {     
         sol[xNext][yNext] = move;
         if (knightTour(xNext, yNext, move+1, sol, xMove, yMove) == true)
            return true;
         else
            // backtracking
            sol[xNext][yNext] = -1;
      }
   }
   return false;
}
bool findKnightTourSol() {
   //initially set all values to -1 of solution matrix    
   for (int x = 0; x < N; x++)     
      for (int y = 0; y < N; y++)
         sol[x][y] = -1;
   //all possible moves for knight
   int xMove[8] = {  2, 1, -1, -2, -2, -1,  1,  2 };
   int yMove[8] = {  1, 2,  2,  1, -1, -2, -2, -1 };
   //starting from room (0, 0)
   sol[0][0]  = 0;     
   if (knightTour(0, 0, 1, sol, xMove, yMove) == false) {
      cout << "Solution does not exist";
      return false;
   } else
      displaySolution();
   return true;
}
int main() {
   findKnightTourSol();
}
import java.util.Arrays;
public class Main {
   static final int N = 8;
   static int[][] sol = new int[N][N];
   //check place is in range and not assigned yet
   static boolean isValid(int x, int y) {    
      return (x >= 0 && x < N && y >= 0 && y < N && sol[x][y] == -1);
   }
   static void displaySolution() {
      System.out.println("The possible solution: ");
      for (int x = 0; x < N; x++) {
         for (int y = 0; y < N; y++)
            System.out.printf("%3d ", sol[x][y]);
         System.out.println();
      }
   }
   static boolean knightTour(int x, int y, int move, int[] xMove, int[] yMove) {
      int xNext, yNext;
      //when the total board is covered
      if (move == N*N)     
         return true;
      for (int k = 0; k < 8; k++) {
         xNext = x + xMove[k];
         yNext = y + yMove[k];
         //check room is preoccupied or not
         if (isValid(xNext, yNext)) {     
            sol[xNext][yNext] = move;
               if (knightTour(xNext, yNext, move+1, xMove, yMove))
                  return true;
               else
                  // backtracking
                  sol[xNext][yNext] = -1;
         }
      }
      return false;
   }
   static boolean findKnightTourSol() {
      //initially set all values to -1 of solution matrix    
      for (int[] row : sol)
         Arrays.fill(row, -1);
         //all possible moves for knight
         int[] xMove = {2, 1, -1, -2, -2, -1, 1, 2};
         int[] yMove = {1, 2, 2, 1, -1, -2, -2, -1};
         //starting from room (0, 0)
         sol[0][0] = 0;     
         if (!knightTour(0, 0, 1, xMove, yMove)) {
            System.out.println("Solution does not exist");
            return false;
         } else
            displaySolution();
      return true;
   }
   public static void main(String[] args) {
      findKnightTourSol();
   }
}
N = 8

# The solution matrix
sol = [[-1 for _ in range(N)] for _ in range(N)]

# Check if place is in range and not assigned yet
def isValid(x, y):
    return (x >= 0 and x < N and y >= 0 and y < N and sol[x][y] == -1)

# Function to print the solution
def displaySolution():
    print("The possible solution: ")
    for x in range(N):
        for y in range(N):
            print(f"{sol[x][y]:3}", end=" ")
        print()

# Recursive function to solve the problem
def knightTour(x, y, move, xMove, yMove):
    if move == N*N:
        return True
    for k in range(8):
        xNext = x + xMove[k]
        yNext = y + yMove[k]
        if isValid(xNext, yNext):
            sol[xNext][yNext] = move
            if knightTour(xNext, yNext, move+1, xMove, yMove):
                return True
            else:
                # Backtracking
                sol[xNext][yNext] = -1
    return False

def findKnightTourSol():
    # All possible moves for knight
    xMove = [2, 1, -1, -2, -2, -1, 1, 2]
    yMove = [1, 2, 2, 1, -1, -2, -2, -1]
    # Starting from room (0, 0)
    sol[0][0] = 0
    if not knightTour(0, 0, 1, xMove, yMove):
        print("Solution does not exist")
        return False
    else:
        displaySolution()
    return True

if __name__ == "__main__":
    findKnightTourSol()

Output

The possible solution: 
  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 
Advertisements