5

I am a beginner in java. I have been working on an maze problem trying it solve it by recursion. I have written the code which seems to work on few inputs and not others. The input is a maze consisting of 0's and 1's. # is the start and @ is the exit.0 is wall and 1's are open.The output will be the hops from # to @. Though i am solving the problem by recursion,I must be going wrong with the logic. Please let me know where I am wrong.

Class practisenumwords

 import java.util.Scanner;

 class practisenumwords {
 public static void main(String[] args){
 Scanner in=new Scanner(System.in);
 int r=in.nextInt();
 int c=in.nextInt();
 maze maz=new maze(r,c);                    /*input in string copied to array*/
 char[] ch;                                        
 ch = "00000000111111101111011001101@#11100".toCharArray();  
 int l=0;
 for(int i=0;i<r;i++)
   {
    for(int j=0;j<c;j++)                /*initialising the maze elements*/
    {                               
     maz.m[i][j]=new cells();
     maz.m[i][j].c=ch[l];
     maz.m[i][j].row=i;
     maz.m[i][j].col=j;
     l++;
    }
  }
for(int i=0;i<r;i++)                             /*print the input maze */
  {
    for(int j=0;j<c;j++)
    {
    System.out.print(""+maz.m[i][j].c);
  }
  System.out.println();
}

maz.escape();
maz.find(maz.startx,maz.starty,maz.hops);
}
}

Class cells

class cells {
char c;
int row;
int col;
boolean done=false;                 /*initially all cells are unvisited*/ 
}

Class maze

class maze{                       
maze (int a,int b){                                
    rows=a;
    cols=b;
    m=new cells[rows][cols];
}
int rows;
int cols;
cells[][] m;
int startx,starty;
int hops=0;
void escape()
{
    for(int i=0;i<rows;i++)
    {
       for(int j=0;j<cols;j++)
       {
        if(m[i][j].c=='#') 
         {
               startx=i;
               starty=j;
               System.out.println(startx+" "+starty);
         }
       }
    }
}
void find(int x,int y,int h)
{    
    if   ((x+1<rows && m[x+1][y].c=='@'   &&  m[x+1][y].done!=true) 
        ||(x-1>=0   && m[x-1][y].c=='@'   &&  m[x-1][y].done!=true)
        ||(y+1<cols && m[x][y+1].c=='@'   &&  m[x][y+1].done!=true)   
        ||(y-1>=0   && m[x][y-1].c=='@'   &&  m[x][y-1].done!=true)){
        h++;
        System.out.println(h);   
         }
      else
       {  
        if(x-1>=0   &&  m[x-1][y].c=='1' && m[x-1][y].done!=true){   /*north cell*/
                    m[x][y].done=true;
                    h++;
                    find(x-1,y,h);
        }
        if(x+1<rows && m[x+1][y].c=='1'  && m[x+1][y].done!=true){   /*south cell*/
                     m[x][y].done=true;
                     h++;
                     find(x+1,y,h);
        }
        if(y+1<cols && m[x][y+1].c=='1'  && m[x][y+1].done!=true){   /*east cell*/
                    m[x][y].done=true;
                    h++;
                    find(x,y+1,h);
        }
        if(y-1>=0 && m[x][y-1].c=='1'    && m[x][y-1].done!=true){   /*west cell*/
                    m[x][y].done=true;
                    h++;
                    find(x,y-1,h);
        }
       }   
      }
    }

Now,i get the right output for the inputs as the 1 in program.

000000
001111
111011
110110
01101@
#11100

output- 12 (obtaining right output)

00@000
001111
111011
110110
011011
#11100

output- 7 (obtaining right output)

BUT NOT FOR OTHER INPUTS like

0 0 0 0 @ 0
0 1 0 1 1 0
1 1 1 1 0 1
0 1 0 1 0 0
0 0 # 1 1 1
0 1 1 0 0 1

correct output - 6 output obtained -7

Also the output changes with the order in which the adjacent cells are checked.

Yaroslav
  • 6,476
  • 10
  • 48
  • 89

3 Answers3

2

Honestly, I'd implement your recursive function a little differently:

And there's no need to check whether a bool value is != true, !boolValue is fine.

int find(int x,int y,int h)
{    
    int result = -1;
    if   ((x+1<rows && m[x+1][y].c=='@'   &&  !m[x+1][y].done) 
        ||(x-1>=0   && m[x-1][y].c=='@'   &&  !m[x-1][y].done)
        ||(y+1<cols && m[x][y+1].c=='@'   &&  !m[x][y+1].done)   
        ||(y-1>=0   && m[x][y-1].c=='@'   &&  !m[x][y-1].done)){   
        return h + 1;
         }
      else
       {

        if(x-1>=0   &&  m[x-1][y].c=='1' && !m[x-1][y].done){   /*north cell*/
                   m[x][y].done=true;

                   result = find(x-1,y,h + 1)
                   if (result > -1) {
                       return result; 
                   }
                   m[x][y].done=false;
        }

Implement the other three directions the same way, then result should still be -1 if no solution was found.

        return result;
       } 
Kevin Stricker
  • 17,178
  • 5
  • 45
  • 71
  • I made changes as int result=-1 and return (h+1) in place of return h . because that will be the last hop.and now It WORKS for all inputs!!! Thanks a lot for helping to check the dead ends.:) Not keeping track of the dead ends resulted in error. – Java beginner Oct 11 '12 at 06:04
0

In a fast reading I notice:

if(...) {
    ...
    h++;
    find(x-1,y,h);
}

For each if-block.

Inside second if-block h == h+2 when first if-condition is satisfied and the same goes for third and fourth if-block

Maybe you should write:

if(...) {
    ...
    // h++;
    find(x-1,y,h+1);
}
user1365836
  • 330
  • 3
  • 12
  • @user1365836- Sir i get the point,but i want the value of h incremented in the 'if blocks' because finally h will give me the total number of hops from #(start) to @(exit). Thats y i have incremented h and passed d same in the find() function. – Java beginner Oct 10 '12 at 15:16
  • Yes but you have to increment that value only if you'll go into that way. If you take that way and then it's wrong, you have not to increment. I wrote find(x-1, y, h+1) <-- h+1 not h – user1365836 Oct 12 '12 at 10:02
0
int find(int x, int y, int h) {
    if ((x + 1 < rows && m[x + 1][y].c == '@' && m[x + 1][y].done != true)
            || (x - 1 >= 0 && m[x - 1][y].c == '@' && m[x - 1][y].done != true)
            || (y + 1 < cols && m[x][y + 1].c == '@' && m[x][y + 1].done != true)
            || (y - 1 >= 0 && m[x][y - 1].c == '@' && m[x][y - 1].done != true)) {
        h++;
        finish = true;
        return h;
    } else {
        if (x - 1 >= 0 && m[x - 1][y].c == '1' && m[x - 1][y].done != true
                && !finish) { /* north cell */
            m[x][y].done = true;
            int temp = find(x - 1, y, h);
            if (temp != 0)
                h = temp + 1;
            return h;

        }
        if (x + 1 < rows && m[x + 1][y].c == '1'
                && m[x + 1][y].done != true && !finish) { /* south cell */
            m[x][y].done = true;
            int temp = find(x + 1, y, h);
            if (temp != 0)
                h = temp + 1;
            return h;

        }
        if (y + 1 < cols && m[x][y + 1].c == '1'
                && m[x][y + 1].done != true && !finish) { /* east cell */
            m[x][y].done = true;

            int temp = find(x, y + 1, h);
            if (temp != 0)
                h = temp + 1;
            return h;

        }
        if (y - 1 >= 0 && m[x][y - 1].c == '1' && m[x][y - 1].done != true
                && !finish) { /* west cell */
            m[x][y].done = true;

            int temp = find(x, y - 1, h);
            if (temp != 0) {
                h = temp + 1;
            }
            return h;
        }
        return 0;
    }
}

Also include a boolean finish = false; in your maze class. and also change the return of the main function

    maz.hops = maz.find(maz.startx, maz.starty, maz.hops);
    System.out.println(maz.hops);
ngoa
  • 720
  • 4
  • 14
  • yes included boolean finish in maze class and replaced the function with yours.But unable to obtain right output. – Java beginner Oct 10 '12 at 16:59
  • @ngoa- The same problem persists. It works fine for the inputs i have mentioned and returns the right value. BUT it does NOT work for those same inputs just as before.The only diff is that now it returns 0 instead of wrong answers. – Java beginner Oct 11 '12 at 05:23