1

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;
}
false
  • 10,264
  • 13
  • 101
  • 209
BlazS14
  • 13
  • 4

2 Answers2

1

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.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 1
    Reguarding point 3 (the indeces). With your fix, invalid values become valid, it's like considering a toroidal board. Shouldn't invalid indeces (out of the board) just be rejected? – Bob__ Jan 18 '18 at 20:59
  • 1
    @Bob__, that makes sense. When they are invalid, the item simply doesn't exist on the board. That's why the bold **Disclaimer** in the post :) – R Sahu Jan 18 '18 at 21:01
  • Thanks for the help. The main problem was, as you stated, the !=NULL. The program works just by fixing this statment to not allow any integers above or below the board size. There are probably some more erros as this code isnt the final version but mostly it should work. Thanks! – BlazS14 Jan 21 '18 at 14:42
0

Your problem is with the if conditions like

pos[xx+2][yy-1]==0&&pos[xx+2][yy-1]!=NULL

This is always false since NULL and 0 are equivalent in the context you are using them here. So you have x == 0 and x != 0 which is always false

pcarter
  • 1,516
  • 14
  • 21