Knight's Tour C ++ с использованием стека

В настоящее время я работаю над игрой Knight tour Chessboard на C ++, используя Stack для хранения моего хода. Я обнаружил странный цикл, который не завершает программу. Кто-нибудь может мне помочь с кодом?

#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;
}

Некоторая часть, которую я только что создал, чтобы отладить и посмотреть, как работает каждая функция, игнорируйте эту часть. Цикл всегда продолжается и, кажется, никогда не заканчивается. Я пытался отслеживать данные в стеке, но мне это кажется разумным.

Любая помощь будет оценена.


person sophadeth rithya    schedule 02.04.2018    source источник
comment
Сам не вставляя это в отладчике, я заметил, что вы меняете значение j в цикле - есть большая вероятность, что это вызывает проблемы, так что это хорошее место для сосредоточения ваших усилий.   -  person Sean    schedule 02.04.2018
comment
Популярная викторина: почему вы передаете position по ссылке при каждом рекурсивном вызове и почему вы думаете, что каждый рекурсивный вызов должен знать свою родительскую позицию и, что более важно, только для полного изменения < / i> и перезапишите его любым ходом, который требуется выполнить рекурсивному вызову. Когда вы выясните ответ на свой вопрос, вы выясните свою ошибку.   -  person Sam Varshavchik    schedule 02.04.2018
comment
Это не бесплатная служба отладки. Вам действительно следует научиться использовать отладчик для отладки ваших собственных программ, так как никто не собирается делать это за вас, когда у вас будут ошибки в будущем. Вы также можете попробовать распечатать значения переменных или создать минимальный, полный и проверяемый пример. idownvotedbecau.se/nodebugging   -  person BessieTheCookie    schedule 02.04.2018
comment
@sean мой J-цикл кажется сложным, но я обязательно выхожу из программы после завершения игры. Я все еще не могу найти свою ошибку.   -  person sophadeth rithya    schedule 02.04.2018
comment
for (int j = 0 ; j< 9 ;j++) - Что происходит, когда j == 8? Мне кажется, что это доступ к массиву за пределами установленного режима. И нет, этот комментарий //nothing is assign here вас не спасает.   -  person PaulMcKenzie    schedule 02.04.2018


Ответы (1)


Глядя на эту часть вашего кода:

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

Подумайте, что происходит в 1 вложенном операторе if st внутри цикла for, когда условие возвращается true. Вы меняете j на -1.

Снова во втором операторе nd if внутри цикла for, если j==8 вы снова меняете j на counter.top().

Такое поведение вызовет бесконечную рекурсию цикла for. Вот простой пример:

#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;
}

Вышеупомянутая программа без последнего оператора if будет имитировать то, что происходит в вашей программе. Я включил это только для того, чтобы остановить цикл, просто чтобы показать прогресс вывода.

Я не знаю, хотите ли вы намеренно бесконечную рекурсию цикла for или нет; но если вам нужно, вам нужно проверить переменные счетчика в отладчике, чтобы убедиться, что они соответствуют значению, необходимому для выполнения оператора, участвующего в выходе из цикла, чтобы остановить рекурсию. Так же, как я показал в моем небольшом примере выше; без условия, чтобы счетчик был равен 10. Цикл бы продолжался вечно.

В качестве примечания, если вы действительно намереваетесь создать бесконечный цикл; обычно лучше структурировать их таким образом, чтобы было более ясно, что вы собираетесь делать.

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;
}

или вместо этого вы можете использовать цикл while

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

   do some work

   increment or set counter;
}
person Francis Cugler    schedule 02.04.2018