Knight’s Tour Problem in C++
Last Updated :
05 Aug, 2024
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 using the C++ language.
Example:
Consider an 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.
A knight can move in an "L" shape, i.e., two squares in one direction and then one square perpendicular to that direction. Suppose the current position of the knight is (i,j). The possible moves are:
(i+2, j+1), (i+2, j-1), (i-2, j+1), (i-2, j-1),
(i+1, j+2), (i+1, j-2), (i-1, j+2), (i-1, j-2)
To solve this problem using backtracking, 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 following C++ program demonstrates how we can solve the Knight’s tour problem using backtracking.
C++
// C++ program to solve Knight’s tour problem using backtracking
#include <iomanip>
#include <iostream>
#include <vector>
#define N 8
using namespace std;
// Function to check if (x, y) is a valid move for the knight
bool isSafe(int x, int y, vector<vector<int>> &sol)
{
return (x >= 0 && x < N && y >= 0 && y < N && sol[x][y] == -1);
}
// Function to print the solution matrix
void printSolution(vector<vector<int>> &sol)
{
for (int x = 0; x < N; x++)
{
for (int y = 0; y < N; y++)
cout << " " << setw(2) << sol[x][y] << " ";
cout << endl;
}
}
// Utility function to solve the Knight's Tour problem
bool solveKTUtil(int x, int y, int movei, vector<vector<int>> &sol, const vector<int> &xMove,
const vector<int> &yMove)
{
int k, next_x, next_y;
if (movei == N * N)
return true;
// 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))
return true;
else
sol[next_x][next_y] = -1; // Backtracking
}
}
return false;
}
// This function solves the Knight's Tour problem using Backtracking
bool solveKT()
{
vector<vector<int>> sol(N, vector<int>(N, -1));
// xMove[] and yMove[] define the next move of the knight.
vector<int> xMove = {2, 1, -1, -2, -2, -1, 1, 2};
vector<int> yMove = {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))
{
cout << "Solution does not exist" << endl;
return false;
}
else
printSolution(sol);
return true;
}
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(8^(N^2)), where N is the size of the chessboard. This complexity arises because for each cell, we try up to 8 possible moves.
Auxiliary Space: O(N^2), as we use a 2D array to store the knight's path.
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 states that the knight should always move to the square from which the knight will have the fewest onward moves. This minimizes the branching factor and reduces the likelihood of running into a dead end.
Approach:
- Set the initial position of the knight randomly on the board.
- Mark the board at the starting position with the move number “1”.
- For each subsequent move number from 2 to the total number of squares on the board:
- Determine all possible positions the knight can move to from the current position.
- Choose the position with the minimum number of onward moves.
- Mark the board at this new position with the current move number.
- Return the marked board, where each square is marked with the move number on which it was visited.
C++ Program to Solve Knight’s Tour using Warnsdorff’s Rule
The following C++ program demonstrates how we can solve the Knight’s tour problem using Warnsdorff’s algorithm.
C++
// C++ program to solve the Knight’s tour problem using Warnsdorff’s algorithm.
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <vector>
#define N 8
using namespace std;
// Move pattern on basis of the change of x 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 to restrict 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
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
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)
cout << setw(2) << a[j * N + i] << "\t";
cout << endl;
}
}
// Checks its neighboring squares. If the knight ends on a square that is one knight's move from the beginning
// square, then the 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 the 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))
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
17 38 13 50 33 36 11 48
14 51 16 37 12 49 32 35
39 18 59 56 53 34 47 10
58 15 52 41 60 63 54 31
19 40 57 64 55 46 9 62
4 1 22 45 42 61 30 27
23 20 3 6 25 28 43 8
2 5 24 21 44 7 26 29
Time Complexity: O(N^3), where N is the size of the chessboard. The complexity is reduced significantly due to the heuristic used.
Auxiliary Space: O(N^2), as we use a 2D array to store the knight's path.
Similar Reads
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
9 min read
Implement Tower of Hanoi in C++ Tower of Hanoi is mathematical puzzle in which we have 3 rods and n disks. First, all the disks are arranged in first rod from larger disk to smaller disk. We have to move all the disk from the first disk to last disk in same arrangement from larger to smaller. Rules of Tower of HanoiThere are follo
3 min read
N Queen Problem Using Branch and Bound in C++ N-Queen problem involves placing N queens on an NÃN chessboard such that no two queens threaten each other. This means no two queens share the same row, column, or diagonal. In this article, we will learn to solve the N queen problem using the Branch and Bound technique which provides an efficient m
6 min read
8 puzzle Problem Using Branch and Bound in C++ 8 Puzzle problem is a sliding puzzle that consists of a 3x3 grid with 8 numbered tiles and a blank space. The goal is to rearrange the tiles to match a specific end configuration by sliding the tiles into the blank space.In this article, we will solve the 8 Puzzle problem using the Branch and Bound
7 min read
Partition Equal Subset Sum in C++ Partition Equal Subset Sum problem is a classic problem in which we have to find whether a given set of positive integers can be partitioned into two subsets such that the sum of the elements in both subsets is equal. In this article, we will learn the solution to this problem in C++ programming lan
7 min read
8 puzzle Problem using Branch and Bound in C 8-puzzle Problem is a classic sliding puzzle that consists of a 3x3 board with 8 numbered tiles and one blank space. The goal is to rearrange the tiles to match a target configuration by sliding the tiles into the blank space. The movement can be in four directions: left, right, up, and down. In thi
7 min read
Rat in a Maze in C++ The Rat in a Maze problem is a popular algorithmic problem in which a rat needs to find a path through a maze from a starting point to a destination. The maze is represented by a 2D grid, where each cell can either be open or blocked. The goal is to determine if there exists a path for the rat to re
4 min read
Output of C++ programs | Set 42 Prerequisite : Pointers and References Q.1 What Is The Output Of this program? CPP #include <iostream> using namespace std; void fun(int& a, int b) { a += 2; b += 1; } int main() { int x = 10, y = 2; fun(x, y); cout << x << " " << y << " "; fun(x
4 min read
Output of C++ programs | Set 35 1. What will be the output of following program? CPP #include<iostream> using namespace std; int main() { int x = 5; if(x==5) { if(x==5) break; cout<<"Hello"; } cout<<"Hi"; } Options A) Compile error B) Hi C) HelloHi D) Hello Answer : A Explanation: Compile erro
3 min read
Output of C++ programs | Set 23 Question 1 What will be the output? CPP #include <iostream> using namespace std; int main() { int x = 0; for (int i = 0; i < 10; i++) { x = x++ + ++x; if (x > 100) break; } cout << x; return 1; } Answer: Compiler dependent. The subexpression x++ causes a side effect, it modifies xâ
2 min read