Knight's Tour C++ 使用堆栈

Posted

技术标签:

【中文标题】Knight\'s Tour C++ 使用堆栈【英文标题】:Knight's Tour C++ using stackKnight's Tour C++ 使用堆栈 【发布时间】:2018-04-02 00:54:30 【问题描述】:

我目前正在使用 Stack 来存储我的移动在 c++ 中的 Knight tour Chessboard 游戏。我遇到了一个奇怪的循环,它不会结束程序。有人可以帮我写代码吗?

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

我刚刚创建的一些部分用于调试并查看每个函数的工作方式,因此请忽略这些部分。 循环总是在继续,似乎永远不会结束。我试图跟踪堆栈中的数据,但这对我来说似乎是合理的。

任何帮助将不胜感激。

【问题讨论】:

我自己没有在调试器中弹出这个,我注意到你在循环中改变了 j 的值——这很有可能导致问题,所以这是一个集中精力的好地方. 小测验:为什么在每个递归调用中通过引用传递position,以及为什么你认为每个递归调用都需要知道它的父位置,更重要的是,只有完全修改它并用递归调用想要进行的任何移动覆盖它。当你弄清楚你的问题的答案时,你就会找出你的错误。 这不是免费的调试服务。你真的应该学会使用调试器来调试你自己的程序,因为当你将来有错误时,不会有人愿意为你做。您也可以尝试打印出变量的值或创建minimal, complete, and verifiable example。 idownvotedbecau.se/nodebugging @sean 我的 J 循环似乎很复杂,但是我确实确保在游戏完成后退出程序。到目前为止,我仍然找不到我的错误。 for (int j = 0 ; j&lt; 9 ;j++) -- 当j == 8 时会发生什么?对我来说,看起来像是对数组的越界访问。不,这条评论//nothing is assign here 不会救你。 【参考方案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

想想当条件返回 true 时,for 循环中的第一个 st 嵌套 if 语句会发生什么。您正在将 j 更改为 -1

再次在 for 循环中的第二个nd if 语句中,如果 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;

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;

【讨论】:

以上是关于Knight's Tour C++ 使用堆栈的主要内容,如果未能解决你的问题,请参考以下文章

Knight's tour backtrack 实现选择步长数组

Knight's tour-回溯(无法解决奇怪的棋盘尺寸)

使用 c++ 偶尔检测到 *** 堆栈粉碎***

在 C++ 中使用链表进行堆栈

如何在 C++ 中使用堆栈 [关闭]

如何使用 C# 从 C++ 应用程序获取调用堆栈?