How to resolve the algorithm Knight's tour step by step in the C++ programming language

Published on 7 June 2024 03:52 AM

How to resolve the algorithm Knight's tour step by step in the C++ programming language

Table of Contents

Problem Statement

Problem: you have a standard 8x8 chessboard, empty but for a single knight on some square. Your task is to emit a series of legal knight moves that result in the knight visiting every square on the chessboard exactly once. Note that it is not a requirement that the tour be "closed"; that is, the knight need not end within a single move of its start position. Input and output may be textual or graphical, according to the conventions of the programming environment. If textual, squares should be indicated in algebraic notation. The output should indicate the order in which the knight visits the squares, starting with the initial position. The form of the output may be a diagram of the board with the squares numbered according to visitation sequence, or a textual list of algebraic coordinates in order, or even an actual animation of the knight moving around the chessboard. Input: starting square Output: move sequence

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Knight's tour step by step in the C++ programming language

This C++ code is a program that solves the Knight's Tour problem, which is to find a path for a knight on a chessboard such that it visits all squares exactly once. The program uses a backtracking algorithm to find a solution.

The Board class represents the chessboard and the knight's position. It has an array of 8 moves, which are the possible moves for a knight from any given square. It also has an array of arrays of integers to represent the chessboard, where each element of the array represents the number of the move that the knight made to get to that square.

The sortMoves method sorts the moves for a given square in order of the number of squares that the knight can move to from that square. This is used to prioritize moves that will lead to a solution.

The solve method starts the knight at the given starting square and tries to find a path for the knight to visit all squares exactly once. It does this by repeatedly moving the knight to the next square in the sorted list of moves, and if it can't find a move, it backtracks to the previous square and tries a different move.

The main function creates three instances of the Board class, one for each of the starting squares "c3", "b5", and "a1". It then calls the solve method on each instance and prints the resulting chessboard.

Here is an example of the output for the starting square "c3":

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

This output shows the path that the knight took to visit all squares exactly once, starting from "c3".

Source code in the cpp programming language

#include <iostream>
#include <iomanip>
#include <array>
#include <string>
#include <tuple>
#include <algorithm>
using namespace std;

template<int N = 8>
class Board 
{
public:
    array<pair<int, int>, 8> moves;
    array<array<int, N>, N> data;

    Board() 
    {
        moves[0] = make_pair(2, 1);
        moves[1] = make_pair(1, 2);
        moves[2] = make_pair(-1, 2);
        moves[3] = make_pair(-2, 1);
        moves[4] = make_pair(-2, -1);
        moves[5] = make_pair(-1, -2);
        moves[6] = make_pair(1, -2);
        moves[7] = make_pair(2, -1);
    }

    array<int, 8> sortMoves(int x, int y) const 
    {
        array<tuple<int, int>, 8> counts;
        for(int i = 0; i < 8; ++i) 
        {
            int dx = get<0>(moves[i]);
            int dy = get<1>(moves[i]);

            int c = 0;
            for(int j = 0; j < 8; ++j) 
            {
                int x2 = x + dx + get<0>(moves[j]);
                int y2 = y + dy + get<1>(moves[j]);

                if (x2 < 0 || x2 >= N || y2 < 0 || y2 >= N)
                    continue;
                if(data[y2][x2] != 0)
                    continue;

                c++;
            }

            counts[i] = make_tuple(c, i);
        }

        // Shuffle to randomly break ties
        random_shuffle(counts.begin(), counts.end());

        // Lexicographic sort
        sort(counts.begin(), counts.end());

        array<int, 8> out;
        for(int i = 0; i < 8; ++i)
            out[i] = get<1>(counts[i]);
        return out;
    }

    void solve(string start) 
    {
        for(int v = 0; v < N; ++v)
            for(int u = 0; u < N; ++u)
                data[v][u] = 0;

        int x0 = start[0] - 'a';
        int y0 = N - (start[1] - '0');
        data[y0][x0] = 1;

        array<tuple<int, int, int, array<int, 8>>, N*N> order;
        order[0] = make_tuple(x0, y0, 0, sortMoves(x0, y0));

        int n = 0;
        while(n < N*N-1) 
        {
            int x = get<0>(order[n]);
            int y = get<1>(order[n]);

            bool ok = false;
            for(int i = get<2>(order[n]); i < 8; ++i) 
            {
                int dx = moves[get<3>(order[n])[i]].first;
                int dy = moves[get<3>(order[n])[i]].second;

                if(x+dx < 0 || x+dx >= N || y+dy < 0 || y+dy >= N)
                    continue;
                if(data[y + dy][x + dx] != 0) 
                    continue;

                get<2>(order[n]) = i + 1;
                ++n;
                data[y+dy][x+dx] = n + 1;
                order[n] = make_tuple(x+dx, y+dy, 0, sortMoves(x+dx, y+dy));
                ok = true;
                break;
            }

            if(!ok) // Failed. Backtrack.
            {
                data[y][x] = 0;
                --n;
            }
        }
    }

    template<int N>
    friend ostream& operator<<(ostream &out, const Board<N> &b);
};

template<int N>
ostream& operator<<(ostream &out, const Board<N> &b) 
{
    for (int v = 0; v < N; ++v) 
    {
        for (int u = 0; u < N; ++u) 
        {
            if (u != 0) out << ",";
            out << setw(3) << b.data[v][u];
        }
        out << endl;
    }
    return out;
}

int main() 
{
    Board<5> b1;
    b1.solve("c3");
    cout << b1 << endl;

    Board<8> b2;
    b2.solve("b5");
    cout << b2 << endl;

    Board<31> b3; // Max size for <1000 squares
    b3.solve("a1");
    cout << b3 << endl;
    return 0;
}


  

You may also check:How to resolve the algorithm List comprehensions step by step in the Wrapl programming language
You may also check:How to resolve the algorithm Dot product step by step in the Elena programming language
You may also check:How to resolve the algorithm Pythagoras tree step by step in the uBasic/4tH programming language
You may also check:How to resolve the algorithm String length step by step in the Simula programming language
You may also check:How to resolve the algorithm De Bruijn sequences step by step in the Kotlin programming language