Chalupa
Chalupa

Reputation: 367

Knight's tour in java (recursive)

I am writing the code for a classic Knight's tour, my code seems to be mostly doing the right thing but it still gives me "not possible" for possible boards and i can't figure out why. (ex: it fails for for a table with 3 rows, 4 columns, starting at row 1, column 3). I start at index 0 when counting rows and columns. I don't think it's backtracking properly. Can anyone help point out my error? Thank you

import java.util.*;
public class KnightGame 
{
    private int rows;
    private int cols;
    private int [][] array;

    public void initializeArray()
    {
        array = new int [rows][cols];
    }

    public boolean fill (int x, int y, int n)
    {
        if ( x < 0 || x >= rows || y<0 || y >= cols )  //outside of board
            return false;
        else if (array[x][y] != 0)   //location has been visited, array element occupied
            return false;
        else if ( n == (rows * cols))       //have visited all locations
            return true;
        else 
        {   
            array[x][y] = n;
            if ( fill(x+1, y-2, n+1) || fill(x-2, y+1, n+1) || fill(x+1, y+2, n+1)
               || fill(x+2, y+1, n+1) || fill(x-2, y-1, n+1) || fill(x-1, y-2, n+1) || 
               fill(x-1, y+2, n+1) || fill(x+2, y-1, n+1)) 
                return true;
            else
                return false;               
        }
    }

    public static void main (String [] args)
    {   
         KnightGame game = new KnightGame();
        int [] st = new int [2];
        int startx, starty;
        Scanner keyIn = new Scanner (System.in); 

        System.out.println("Enter number of rows: ");
        game.rows=keyIn.nextInt();

        System.out.println("Enter number of columns: ");
         game.cols = keyIn.nextInt();

        game.initializeArray();

        System.out.println("Enter starting location: ");
         for (int i=0; i<2; i++)
         {
             st[i] = keyIn.nextInt();
         }

         startx = st[0];
         starty = st[1];

         //testing for correct starting values
         System.out.println("starting values: " + startx + " " + starty);       

        if (game.fill(startx, starty, 1))
        {
            for (int i=0; i<game.rows; i++)
                {
                  for (int j=0; j<game.cols; j++)
                  {
                     System.out.print(game.array[i][j] + " "); 
                  } 
                }
        }

        else
            System.out.println("Board could not be completed!");

    }

}

Upvotes: 1

Views: 1559

Answers (2)

j_v_wow_d
j_v_wow_d

Reputation: 511

The problem is that when the backtracking is happening your code is not resetting the position to 0 and the next time around in another pass it gets confused thinking it was there, but that spot should have been reset. Here is a code snippet with the fix:

else 
{   
    array[x][y] = n;
    if ( fill(x+1, y-2, n+1) || fill(x-2, y+1, n+1) || fill(x+1, y+2, n+1)
       || fill(x+2, y+1, n+1) || fill(x-2, y-1, n+1) || fill(x-1, y-2, n+1) || 
       fill(x-1, y+2, n+1) || fill(x+2, y-1, n+1)) 
        return true;
    else {
        array[x][y] = 0;//NEED THIS LINE
        return false; 
    }              
}

Upvotes: 1

samgak
samgak

Reputation: 24417

You're not clearing the squares on the board when you backtrack. So if you recurse down one potential path, fail and then try another path, the squares are still marked from the first attempt so the second attempt fails too, even though it might have been possible.

        array[x][y] = n;
        if ( fill(x+1, y-2, n+1) || fill(x-2, y+1, n+1) || fill(x+1, y+2, n+1)
           || fill(x+2, y+1, n+1) || fill(x-2, y-1, n+1) || fill(x-1, y-2, n+1) || 
           fill(x-1, y+2, n+1) || fill(x+2, y-1, n+1)) 
            return true;
        else
        {
            array[x][y] = 0; // <- add this line
            return false; 
        }

Upvotes: 3

Related Questions