0

I am currently working on Knight tour Chessboard game in c++ using Stack to store my move. I encounter a weird loop that does not end the program. Can anybody help me with the code?

#include <iostream>
#include <stack>
#include <map>
#include <cstdlib>
using namespace std;

struct whereIam
{
    int row, col;
};

struct L_shape_pattern
{
    int Lrow[8]={1,1,2,2,-1,-1,-2,-2};
    int Lcol[8]={2,-2,1,-1,2,-2,1,-1};


};
bool check_if_valid(int row, int col)
{
   if ((row >= 0 && col >= 0) && (row < 8 && col < 8))
   {
//       cout << "here in valid " <<endl;
              return true ;
   }

   else
       return false;

}

bool check_empty(bool board[8][8], whereIam position)
{
//   if (board[position.row][position.col] == false)
//       return false;
//   else
//       return true;
   if (board[position.row][position.col] == true)
   {
//       cout << "here in check empty" <<endl;
       return true;
   }

   else
       return false;

}
bool isReady(whereIam &position,bool board[8][8])
{
//    cout << "here" << endl;
    int ready = 0;
    for (int i = 0 ; i < 8 ; i ++)
    {
        for (int j = 0 ; j < 8 ; j++)
        {
            if(board[i][j] == false)
            {
                ready += 1;
            }

        }
    }
    cout << "ready: " <<ready << endl;
    if (ready == 64)
    {
        cout << "done" << endl;
        return true;
    }
    else
        return false;
}
void findspot(whereIam &position,bool board[8][8], stack<whereIam> &sequence)
{
    L_shape_pattern Lshape;

//    stack<whereIam> initial;
    stack<int> counter;


        for (int j = 0 ; j< 9 ;j++)
        {
            //nothing is assign here
            if (check_if_valid(position.row+Lshape.Lrow[j],position.col+Lshape.Lcol[j]) /*&& check_empty(board,position)*/)
            {
//                cout << "here in valid in spot " <<endl;
                whereIam hello;
                hello.row = position.row+Lshape.Lrow[j];

                hello.col = position.col+Lshape.Lcol[j];
//                cout << hello.row << " " << hello.col << endl;
                if (check_empty(board,hello))
                {
//                    cout << "here in empty" <<endl;
//                    int possible_row = position.row+Lshape.Lrow[j];
//                    int possible_col = position.col+Lshape.Lcol[j];
//                    position.row = possible_row;
//                    position.col = possible_col;
                    position.row = hello.row;
                    position.col = hello.col;

                    sequence.push(position);
//                    initial.push(position);
//                    cout << position.row << " " << position.col << endl;
                    counter.push(j);
                    board[position.row][position.col] = false;
                    j = -1;
                    if (isReady(position,board) == true)
                    {
                        cout << "in if ready" << endl;
                        exit(0);
                    }




                }



            }
            if (j == 8 )
            {
//                cout << "here in j = 8" <<endl;
                board[position.row][position.col] = true;
//                cout << " pop board " << position.row <<" " << position.col << endl;
                sequence.pop();
                position = sequence.top();
                // increment to the position where it need to be backtracking and it increment by one
                 j = counter.top();
                counter.pop();
                if (isReady(position,board) == true)
                {
                    cout << "in if ready" << endl;
                    exit(0);
                }

            }




        }



}
//bool movetheKnight(whereIam &position,bool board[8][8], stack<whereIam> &sequence)
//{

//}
void open_all_spot( bool board[8][8])
{

    for (int i = 0 ; i< 8 ; i++)
        for (int j= 0 ; j <8 ; j++)
        {
            board[i][j] = true;
        }
}
int main()
{
    bool board[8][8];
    open_all_spot(board);


    whereIam position;
    stack<whereIam> sequence;
    cout << "Enter the initial position" << endl;
    cout << "row : " ;
    cin >> position.row;
    cout << "column:";
    cin >> position.col;
    sequence.push(position);
    //assign the initial position to be occupied already
    board[position.row][position.col] = false;

    findspot(position,board,sequence);
    cout << "here end all" << endl;

    return 0;
}

Some part I just created to debug and see how each function work so ignore those part. The loop always goes on and never seems to end at all. I tried to track data in the stack but it does seems reasonable to me.

Any help would be appreciated.

grizzthedj
  • 7,131
  • 16
  • 42
  • 62
  • Without popping this in a debugger myself, I've noticed you're changing the value of j within the loop - there's a fair chance that's causing the problems, so it's a good place to focus your efforts. – Sean Apr 02 '18 at 00:58
  • Pop quiz: why are you passing `position`, by reference, on each recursive call, and why exactly do you think that each recursive call needs to know its parent position, and, more importantly, only to completely ***modify*** it and overwrite it with whatever move the recursive call wants to make. When you figure out the answer to your question, you will figure out your bug. – Sam Varshavchik Apr 02 '18 at 01:01
  • This is not a free debugging service. You really should learn to use a debugger to debug your own programs, as there isn't going to be someone willing to do it for you when you have bugs in the future. You can also try printing out the values of variables or making a [minimal, complete, and verifiable example](https://stackoverflow.com/help/mcve). http://idownvotedbecau.se/nodebugging/ – eesiraed Apr 02 '18 at 01:02
  • @sean my J loop seems to be complicated however I do make sure to exit the program once the game is done. I stilll cannot find my error so far. – sophadeth rithya Apr 02 '18 at 01:06
  • 1
    `for (int j = 0 ; j< 9 ;j++)` -- What happens when `j == 8`? Looks like an out-of-bounds access into an array to me. And no, this comment `//nothing is assign here` doesn't save you. – PaulMcKenzie Apr 02 '18 at 01:07

1 Answers1

1

When looking at this part of your code:

for ( int j = 0; j < 9; j++ ) {
    if ( check_if_valid(position.row+Lshape.Lrow[j],position.col+Lshape.Lcol[j]) /*&& check_empty(board,position)*/) {
        // code...
        if ( checkEmpty( board, hello ) {
            // code...
            j = -1;
            if ( isReady(position, board) == true ) { // == true not needed
                // code...
            }
        }
    }
    if ( j == 8 ) {
        // code...
        j = counter.top()
        // code...
        if ( isReady(position, board) == true ) { // == true not needed
            // code...
        }
    }
} // for loop

Think about what happens in the 1st nested if statement within the for loop when the condition is returned true. You are changing j to be -1.

Again in the 2nd if statement within the for loop if j==8 you again are changing j to be counter.top().

This behavior will cause infinite recursion of the for loop. Here is a simple example:

#include <iostream>
#include <iomanip>

int main() {

    int counter = 0;
    for ( int i = 0; i < 5; i++ ) {
        if ( i == 4 ) {
            i = 0;
        }
        ++counter;
        std::cout << "Count the recursion: " 
                  << std::setw( 2 ) << counter << " " << i << '\n';

        // just to stop the recursion
        if ( counter == 10 ) break;
    }

    std::cout << "\nPress any key and enter to quit.\n";
    std::cin.get();
    return 0;
}

The above program without the last if statement will simulate what is happening in your program. I only included that so as to stop the loop just to show the progression of the output.

I don't know if you intentionally want an infinite recursion of a for loop or not; but if you do you need to check your counter variable(s) in a debugger to make sure that they match the value needed to execute the statement involved in exiting the loop to stop the recursion. Just as I have shown in my small example above; without the condition of the counter being equal to 10. The loop would of continued on forever.

As a side note if you do intend to have an infinite loop; it is usually better to structure them in this manner this way it is more clear as to what you intended to do.

int counter = 0;
for ( ; ; ) {
    ++counter;

    // do some work;

   if ( counter == exit condition )  break;
}

or

int counter = 0;
for ( ; ; ) {
    // do some work;

    if work above is valid
       increment counter
    else
       break;
}

or you can use a while loop instead

counter = some value
while ( true ) {
   check counter for condition;

   do some work

   increment or set counter;
}
Francis Cugler
  • 7,788
  • 2
  • 28
  • 59