-3

I'm trying to write a program that allows the user to enter any coordinate on a chess board and complete the knight's tour using brute force recursion. I am getting an infinite loop and I have no idea why. This is in C++, and I have to write this only using brute force recursion. After entering the starting place for the knight, my console output window prints the current board after each move (only temporarily, for troubleshooting purposes), but according to my output, the move number is stuck at 1, and the program isn't trying any other moves. Any help is appreciated.

#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;

void printBoard();
bool moveKnight(int col, int row, int movNum);


int totalMoves = 0;
int board[7][7] = { { 0 } };


int main()
{
    cout << "Welcome to the Knight's Tour Program!  Enter a starting place for the knight on a chess board to get started.\n";

    int col;
    int row;

    int a;
    int b;

    while (1 == 1)
    {
        col = 0;
        row = 0;

        cout << "Enter column (0-7): ";
        cin >> col;

        cout << "Enter row (0-7): ";
        cin >> row;

        if (row < 0 || row > 7 || col < 0 || col > 7)
        {
            cout << "Invalid knight placement.  Please try again.\n";
        }

        else
        {
            break;
        }
    }

    int movNum = 1;

    board[col][row] = movNum;
    totalMoves++;

    moveKnight(col, row, movNum);

    if (moveKnight(col, row, movNum == true))
    {
        cout << "Tour finished!  Total moves: " << totalMoves << endl;
        printBoard();
        cout << "\n\n";
    }

    system("pause");
    return 0;
}


void printBoard()
{
    cout << "Current board\n";
    for (int i = 0; i < 8; i++)
    {
        for (int x = 0; x < 8; x++)
        {
            cout << setw(3) << board[i][x] << "  ";

            if (x == 7)
            {
                cout << "\n\n";
            }
        }
    }
    cout << "\n";
}


bool moveKnight(int col, int row, int movNum)
{
     printBoard(); //just for troubleshooting
     cout << "\n" << totalMoves << endl;

     if (moveKnight(col, row, movNum) == false)
     {
         board[col][row] = 0; //if there are no available moves then set the current space to 0 and move back a spot
     }

     if (movNum == 64)
     {
         return true; //if tour complete return true
     }

     if (totalMoves % 10000 == 0)
     {
         printBoard(); //printBoard() every 10000 moves
     }

     if (col >= 0 && col <= 7 && row >= 0 && row <= 7 && board[row][col] == 0) //check if space is on board and if it is unoccupied
     {
        board[col][row] = movNum;
        totalMoves++;

        if (moveKnight(col + 1, row - 2, movNum + 1) != false)
            moveKnight(col + 1, row - 2, movNum + 1);

        else if (moveKnight(col + 2, row - 1, movNum + 1) != false)
            moveKnight(col + 2, row - 1, movNum + 1);

        else if (moveKnight(col + 2, row + 1, movNum + 1) != false)
            moveKnight(col + 2, row + 1, movNum + 1);

        else if (moveKnight(col + 1, row + 2, movNum + 1) != false)
            moveKnight(col + 1, row + 2, movNum + 1);

        else if (moveKnight(col - 1, row + 2, movNum + 1) != false)
            moveKnight(col - 1, row + 2, movNum + 1);

        else if (moveKnight(col - 2, row + 1, movNum + 1) != false)
            moveKnight(col - 2, row + 1, movNum + 1);

        else if (moveKnight(col - 2, row - 1, movNum + 1) != false)
            moveKnight(col - 2, row - 1, movNum + 1);

        else if (moveKnight(col - 1, row - 2, movNum + 1) != false)
            moveKnight(col - 1, row - 2, movNum + 1);
        else
            return false;
     }
}

2 Answers2

0

If you look in the moveKnight() function, notice that the line if (moveKnight(col, row, movNum) == false) does a recursive call of the function no matter what the inputs are.

Whenever you use a recursive function, it must have what is called a base case, where a recursive call does not happen. Otherwise, the recursive calls will just keep going on until a stack overflow since one execution of the function will start another one which will start another one and so on..

By the way, the bunch of if statements in the function make no sense since you are calling a function and checking the output, and if it is true then you call the function a second time with the exact same arguments. Also, if you want an infinite loop that you will break later, there is no need for something like while(1 == 1). Use while(1) or while(true).

eesiraed
  • 4,626
  • 4
  • 16
  • 34
0

int board[7][7] = { { 0 } };

Chess board is 8 x 8, so you need 8 elements in the array (from 0 to up to and including 7, that's 8)

if (moveKnight(col, row, movNum == true))

You have syntax erros, the compiler will tell you about all this. In Visual Studio make sure warning level is set to 4. Then make sure the program is compiled with zero errors and zero warnings.

I would recommend writing a program which does not require user input. This will make it easier to debug the program and fix the logic.

Below is a simple recursion which moves the knight until the knight gets stuck at the end. You will have to further improve the logic so that it covers all the squares.

Make sure the recursive function is allowed to break. That's discussed in more detail in the other answer.

int board[8][8] = { 0 };

void printBoard()
{
    cout << "Current board\n";
    for(int i = 0; i < 8; i++)
    {
        for(int x = 0; x < 8; x++)
            cout << board[i][x] << " ";
        cout << "\n";
    }
    cout << "\n";
}

int test(int &row, int &col, int move_row, int move_col)
{
    int r = row + move_row;
    int c = col + move_col;
    if(r >= 0 && r < 8 && c >= 0 && c < 8 && !board[r][c])
    {
        row = r;
        col = c;
        return 1;
    }
    return 0;
}

bool move_knight(int &row, int &col)
{
    board[row][col] = 1;
    printBoard();
    system("pause");
    if(!test(row, col, 1, 2))
        if(!test(row, col, 1, -2))
            if(!test(row, col, -1, 2))
                if(!test(row, col, -1, -2))
                    if(!test(row, col, 2, 1))
                        if(!test(row, col, 2, -1))
                            if(!test(row, col, -2, 1))
                                if(!test(row, col, -2, -1))
                                    return false;

    move_knight(row, col);
    return true;
}

int main()
{
    int col = 0;
    int row = 0;
    move_knight(col, row);
    system("pause");
    return 0;
}
Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77