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
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
N Queen Problem Using Branch and Bound in C
N Queen Problem is a classic combinatorial problem. The objective is to place N queens on an NÃN chessboard such that no two queens threaten each other according to the rules of the chess game. No two queens can share the same row, column, or diagonal. This problem has a variety of applications in f
6 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
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
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
std::search_n with example in C++
Prerequisite: std::search std::search_n is an STL algorithm defined inside the header file , which is used to search whether a given element satisfies a predicate (equality if no such predicate is defined ) a given no. of times consecutively with the container elements. It searches the range [first,
4 min read
Tic-Tac-Toe Game in C++
In this article, we will learn how to develop a tic-tac-toe game in C++. Tic-tac-toe is a game played between two players usually with paper and pencil but here, we will create a C++ program that will display the game on the console screen and players can use different keys from the keyboard to play
7 min read
Count ways to reach the Nth station
Given N stations and three trains A, B, and C such that train A stops at every station, train B stops at every second station, and train C stops at every third station, the task is to find the number of ways to reach the Nth station can be reached from station 1. Examples: Input: N = 4Output: 3Expla
8 min read
Minimum Cost Path in C++
Minimum Cost Path problem involves finding the path in a grid from the top-left to the bottom-right corner such that the total cost incurred is minimized. In this problem, movement is allowed in all four directions: left, right, up, and down. Example: Consider the below example in which a two-dimens
5 min read