Search code examples
c++knights-tour

Knights tour c++ recursive


im trying to do the knights tour in c++ with a recursive function but this program just exits without executing the function more than once. The main concept is just brute forcing the way with one function that finds a way by jumping to any open place and trying to go to the next one. If it block itself in it should just return false and try the next option and so on. Am i just totally off with this method or am i just missing something?

#include <iostream>
#include <math.h>
#include <numeric>
#include <cstdlib>
#include <ctime>
#include <string.h>
#include <stdio.h>
#include <sstream>
#include <fstream>
#include <limits>
using namespace std;

struct sah{

   int pos[8][8] = {{0}};           //fill whole board with 0
   int x;
   int y;
   int fre=64;                      //number of free spaces on board

   bool free (int xx,int yy);

};

bool sah::free (int xx,int yy)
{

   pos[xx][yy]=1;
   for(int a=0;a!=8;a++){
      for(int b=0;b!=8;b++){
         cout<<pos[a][b]<<" ";  
      }
      cout<<endl;
   }

   if(pos[xx+2][yy-1]==0&&pos[xx+2][yy-1]!=NULL&&free(xx+2,yy-1)!=false)
      cout<<"hai";
   else if(pos[xx-2][yy-1]==0&&pos[xx-2][yy-1]!=NULL&&free(xx-2,yy-1)!=false)
      cout<<"hai";      
   else if(pos[xx+2][yy+1]==0&&pos[xx+2][yy+1]!=NULL&&free(xx+2,yy+1)!=false)
      cout<<"hai";      
   else if(pos[xx-2][yy+1]==0&&pos[xx-2][yy+1]!=NULL&&free(xx-2,yy+1)!=false)
      cout<<"hai";      
   else if(pos[xx+1][yy-2]==0&&pos[xx+1][yy-2]!=NULL&&free(xx+1,yy-2)!=false)
      cout<<"hai";      
   else if(pos[xx-1][yy-2]==0&&pos[xx-1][yy-2]!=NULL&&free(xx-1,yy-2)!=false)
      cout<<"hai";      
   else if(pos[xx+1][yy+2]==0&&pos[xx+1][yy+2]!=NULL&&free(xx+1,yy+2)!=false)
      cout<<"hai";  
   else if(pos[xx-1][yy+2]==0&&pos[xx-1][yy+2]!=NULL&&free(xx-1,yy+2)!=false)
      cout<<"hai";  
   else{
      pos[xx][yy]=0;
      cout<<"kek"<<xx<<yy;
      return false;
   }

   for(int n=0;n!=8;n++){
      for(int i=0;i!=8;i++){
         if(pos[n][i]==1)
            fre=fre-1;  
      }
   }
   cout<<fre<<" ";


}

int main(int argc, char** argv) {

   sah chess;
   chess.x=0;
   chess.y=0;
   if(chess.free(chess.x,chess.y)!=false)
      cout<<"end";

}

Output:

1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
kek00

For anyone that is interested in the final working code/solution here is the end version. it is still just a brute force approach and far from optimal but it may help:

#include <iostream>
using namespace std;

struct chess{

    int pos[8][8] = {{0}};          //fill whole board with 0
    int x;
    int y;
    int all=0;
    int fre=64;                     //number of free spaces on board

    bool free (int xx,int yy);

};

bool chess::free (int xx,int yy)
{
    all++;

pos[xx][yy]=1;
    for(int n=0;n!=8;n++){
        for(int i=0;i!=8;i++){
            if(pos[n][i]==1)
            fre=fre-1;  
        }
    }
    cout<<endl<<endl;
    for(int a=0;a!=8;a++){
        for(int b=0;b!=8;b++){
            cout<<pos[a][b]<<" ";   
        }
        cout<<endl;
    }
    cout<<endl;

    if(pos[xx+2][yy-1]==0&&yy-1>0&&xx+2<9&&free(xx+2,yy-1)!=false)
    cout<<"success";
    else if(pos[xx-2][yy-1]==0&&xx-2>0&&yy-1>0&&free(xx-2,yy-1)!=false)
    cout<<"success";        
    else if(pos[xx+2][yy+1]==0&&yy+1<9&&xx+2<9&&free(xx+2,yy+1)!=false)
    cout<<"success";        
    else if(pos[xx-2][yy+1]==0&&yy+1<9&&xx-2>0&&free(xx-2,yy+1)!=false)
    cout<<"success";        
    else if(pos[xx+1][yy-2]==0&&xx+1<9&&yy-2>0&&free(xx+1,yy-2)!=false)
    cout<<"success";        
    else if(pos[xx-1][yy-2]==0&&xx-1>0&&yy-2>0&&free(xx-1,yy-2)!=false)
    cout<<"success";        
    else if(pos[xx+1][yy+2]==0&&yy+2<9&&xx+1<9&&free(xx+1,yy+2)!=false)
    cout<<"success";    
    else if(pos[xx-1][yy+2]==0&&yy+2<9&&xx-1>0&&free(xx-1,yy+2)!=false)
    cout<<"success";    
    else{
            if(fre==0)
            return true;
            pos[xx][yy]=0;
            cout<<"   "<<xx<<","<<yy;
            return false;
    }
}

int main(int argc, char** argv) {

    chess knight;
    knight.x=0;
    knight.y=0;
    if(knight.free(knight.x,knight.y)==true)
    cout<<endl<<endl<<endl<<knight.all;
    return 0;
}

Solution

  • I noticed the following errors in your code.

    1. sha::free does not have a return statement before the closing }. That is cause for undefined behavior.

      It's not clear to me whether the return value should be false or true when the function reaches that point.

    2. You are using pos[xx+2][yy-1] != NULL. It seems like you are trying to compare with a pointer but pos[xx+2][yy-1] is not a pointer. It is an integer. It's not clear from your post what your intention is for that.

    3. You are accessing pos using invalid indices, such as pos[xx+2][yy-1] and pos[xx-2][yy-1, which is again cause for undefined behavior.

      If xx is 6 or greater, xx+2 is an invalid index. If yy is 0, yy-1 is an invalid index.

      I suggest the following fixes for the indices.

      xx+2 needs to be (xx+2)%8.
      yy-1 needs to be (yy-1+8)%8.

      xx+1, xx-1, xx-1, yy+1, yy+2, and yy-2 need to be similarly changed.

      You may want to use a function to encapsulate the logic.

      E.g.

      int plusIndex(x, n) { return (x+n)%8; }
      int minusIndex(x, n) { return (x-n+8)%8; }
      

      and then use:

      // Don't use this
      // if( pos[xx+2][yy-1]==0 &&pos[xx+2][yy-1]!=NULL && free(xx+2,yy-1)!=false )
      
      // Use this.
      if ( pos[plusIndex(xx, 2)][minusIndex(yy, 1)] != 0 &&
           ...
      
    4. You are passing invalid indices in the recursive calls to free. When you use

      free(xx+2,yy-1)
      

      either or both of them could be invalid indices. Instead, use

      free(plusIndex(xx, 2), minusIndex(yy, 1))
      

    Disclaimer

    The above changes don't address any algorithmic errors in your posted code.