Showing posts with label MAZE. Show all posts
Showing posts with label MAZE. Show all posts

JAVA program to implement Eller's algorithm to generate random maze

Posted On // Leave a Comment

Algorithm:

    Eller's algorithm creates 'perfect' mazes, having only a single path between any two cells, one row at a time. The algorithm itself is incredibly fast, and far more memory efficient than other popular algorithms (such as Prim's and Kruskal's) requiring storage proportional to only a single row. This makes it possible to create mazes of indefinite length on systems with limited memory.

The algorithm is explained below:
  1. Create the first row. No cells will be members of any set

  2. Join any cells not members of a set to their own unique set

  3. Create right-walls, moving from left to right:
    1. Randomly decide to add a wall or not
      • If the current cell and the cell to the right are members of the same set, always create a wall between them. (This prevents loops)
      • If you decide not to add a wall, union the sets to which the current cell and the cell to the right are members.

  4. Create bottom-walls, moving from left to right:
    1. Randomly decide to add a wall or not. Make sure that each set has at least one cell without a bottom-wall (This prevents isolations)
      • If a cell is the only member of its set, do not create a bottom-wall
      • If a cell is the only member of its set without a bottom-wall, do not create a bottom-wall

  5. Decide to keep adding rows, or stop and complete the maze
    1. If you decide to add another row:
      1. Output the current row
      2. Remove all right walls
      3. Remove cells with a bottom-wall from their set
      4. Remove all bottom walls
      5. Continue from Step 2

    2. If you decide to complete the maze
      1. Add a bottom wall to every cell
      2. Moving from left to right:
        • If the current cell and the cell to the right are members of a different set:
          1. Remove the right wall
          2. Union the sets to which the current cell and cell to the right are members.
          3. Output the final row

CODE:

// a utility class to represent single cell
import java.util.*;

public class Cel{
 public boolean right,down;
 
 public List<Cel> set;
 
 public int x,y;
 
 Cel(int a,int b){
  
  x=a;
  
  y=b;
  
  right=false;
  
  down=true;
  
  set=null;
  
 }
 
}
// class to implement the algorithm
import java.util.*;



public class maze{
 
 static Random randomizer = new Random();
 
 static int size;
 
 static int[][] maze;
 
 static Scanner in = new Scanner(System.in);
 
 
 
 /*  Step 2: Grouping ungrouped cells to form new sets    */
 
 static Cel[] makeSet(Cel[] row) {
  
  for(int index = 0; index < row.length; ) {
   
   Cel cell = row[index++];
   
   if(cell.set == null) {
    
    List<Cel> list = new ArrayList<Cel>();
    
    list.add(cell);
    
    cell.set=list;
    
   }
   
  }
  
  return row;
  
 }
 
 /*********************************************************/
 
 
 
 /*  Step 3: Creating right walls                         */
 
 static Cel[] makeRightWalls(Cel[] row) {
  
  for(int i = 1; i < row.length; i++) {
   
   if(isContainsInList(row[i-1].set,row[i])) {
    
    row[i-1].right=true;
    
    continue;
    
   }
   
   if(randomizer.nextBoolean())
   
   row[i-1].right=true;
   
   else
    
   row=merge(row,i);
   
  }
  
  return row;
  
 }
 
 
 
 static Cel[] merge(Cel[] row,int i) {  //utility function
  
  List<Cel> currentList = row[i-1].set;
  
  List<Cel> nextList = row[i].set;
  
  for(Cel j : nextList) {
   
   currentList.add(j);
   
   j.set=currentList;
   
  }
  
  return row;
  
 }
 
 
 
 static boolean isContainsInList(List<Cel> set,Cel cell) {  //utility function
  
  for(Cel i : set) {
   
   if(i==cell)
   
   return true;
   
  }
  
  return false;
  
 }
 
 /*********************************************************/
 
 
 
 /*  Step 4: Creating down walls                          */
 
 static boolean isNotDone(List<Cel> set){    //utility function
  
  boolean rslt=true;
  
  for(Cel x:set)
  
  rslt=rslt&&x.down;
  
  return rslt;
  
 }
 
 
 
 static Cel[] makeDown(Cel[] row){
  
  for(int i=0;i<row.length;i++){
   
   for(Cel x:row[i].set)x.down=true;
   
   while(isNotDone(row[i].set)){
    
    do{
     
     row[i].set.get(randomizer.nextInt(row[i].set.size())).down=false;
     
    }while(randomizer.nextBoolean() || );
    
   }
   
  }
  
  return row;
  
 }
 
 /*********************************************************/
 
 
 
 /*  Driver function to execute the algorithm             */
 
 static public void driver(){
  
  System.out.print("Enter size: ");
  
  size=in.nextInt();
  
  maze=new int[2*size+1][2*size+1];
  
  Cel[] cur=new Cel[size];
  
  for(int i=0;i<size;i++)
  
  cur[i]=new Cel(0,i);
  
  for(int i=2;i<=2*size;i++)
  
  for(int j=2;j<=2*size;j++)
  
  maze[i][j]=0;
  
  for(int i=0;i<size;i++){
   
   cur=makeSet(cur);
   
   cur=makeRightWalls(cur);
   
   cur=makeDown(cur);
   
   if(i==size-1)
   
   cur=end(cur);
   
   printMaze(cur,i);
   
   if(i!=size-1)
   
   cur=genNextRow(cur);
   
  }
  
  //Creating upper and left boundary
  
  for(int i=0;i<=2*size;i++)
  
  maze[i][0]=maze[0][i]=maze[i][2*size]=maze[2*size][i]=1;
  
  for(int i=2;i<=2*size;i+=2)
  
  for(int j=2;j<=2*size;j+=2)
  
  maze[i][j]=1;
  
  for(int i=0;i<2*size+1;i++){
   
   System.out.println();
   
   for(int j=0;j<2*size+1;j++)
   
   System.out.print(maze[i][j]+" ");
   
  }
  
 }
 
 static Cel[] end(Cel[] row) {
  
  for(int i = 1; i < row.length; i++) {
   
   if(findPos(row[i-1].set,row[i]) == -1) {
    
    row[i-1].right=false;
    
    row=merge(row,i);
    
   }
   
  }
  
  return row;
  
 }
 
 
 
 static int findPos(List<Cel> set,Cel x){
  
  Cel[] tmpArray = new Cel[set.size()];
  
  tmpArray = set.toArray(tmpArray);
  
  for(int i=0;i<tmpArray.length;i++)
  
  if(tmpArray[i]==x)
  
  return i;
  
  return -1;
  
 }
 
 
 
 static Cel[] genNextRow(Cel[] pre){
  
  for(int i = 0; i < pre.length;i++ ) {
   
   pre[i].right=false;
   
   pre[i].x++;
   
   if(pre[i].down) {
    
    pre[i].set.remove(findPos(pre[i].set, pre[i]));
    
    pre[i].set=null;
    
    pre[i].down=false;
    
   }
   
  }
  
  return pre;
  
 }
 
 
 
 static void printMaze(Cel[] row,int rowPos){
  
  rowPos=2*rowPos+1;
  
  for(int i=0;i<row.length;i++){
   
   if(row[i].right)
   
   maze[rowPos][2*i+2]=1;
   
   if(row[i].down)
   
   maze[rowPos+1][2*i+1]=1;
   
  }
  
 }
 
 
 
}

// driver class to execute the algorithm
public class runMe{
 
 public static void main(String[] args) {
  
  maze t =new maze();
  
  maze.driver();
  
 }
 
}

SOURCE:  

[Read more]

JAVA program to help jerry find cheese

Posted On // Leave a Comment

ALGORITHM:

Jerry is hungry and needs cheese. Bur cheese is in a maze and jerry needs help to find the cheese.
The maze solving is a classic algorithm under backtracking and ai.The problem is to find a path for the rat to food in a maze.
The problem can be solved trying out different paths possible and find the right path,
This logic can be implemented by a simple recursive algorithm. Since the jerryis performed in stack the processes are done in LIFO manner so if we have to print instructions to jerry we will do the process as cheese finds jerry.
  1. Start with the target
  2. If the cell is not legal (if it is out of maze or the cell is a wall) return false
  3. If starting point has reached return true 
  4. else make the cell a wall(to avoid coming back to the same path from any other instant) and
  5. Take all the cells in  four direction and check whether the path can be reached through any of these cells and print opposite movement if the cell is a part of the path (eg if upper cell is part of path print DOWN)and return true and if not path backtrack and return false.These cells should chosen according to the distance to starting point from the current point.
  

The above maze is:
1 0 1 0 1
1 0 1 0 1
1 0 1 1 1
1 0 0 1 0
1 1 1 1 0
So the jerry should move down four times and right three times and up two times and right and then up two times.

CODE:

import java.util.Scanner;

public class Maze{
   
   
    static Scanner in = new Scanner(System.in);
    static int[][] maze;

    static boolean solveMaze(int x,int y,int tx,int ty,int b,int h){

        if(x>=0 && x<b && y>=0 && y<h && maze[x][y]==1){//Checking if current cell is legal
            maze[x][y]-=1;
            if(x==tx && y==ty)//checking if point has reached
                return true;
            boolean up,down,left,right;
            /*
             Calculating horizontal and vertical distances and moving according to it
            */
            int xDiff=tx-x;
            if(xDiff<0)
                xDiff*=-1;
            int yDiff=ty-y;
            if(yDiff<0)
                yDiff*=-1;
            if(xDiff<yDiff){
                if(tx<x){
                    up=solveMaze(x-1,y,tx,ty,b,h);
                    down=solveMaze(x+1,y,tx,ty,b,h);
                }
                else{
                    down=solveMaze(x+1,y,tx,ty,b,h);
                    up=solveMaze(x-1,y,tx,ty,b,h);
                }
                if(ty<y){
                    left=solveMaze(x,y-1,tx,ty,b,h);
                    right=solveMaze(x,y+1,tx,ty,b,h);
                }
                else{
                    right=solveMaze(x,y+1,tx,ty,b,h);
                    left=solveMaze(x,y-1,tx,ty,b,h);
                }
            }
            else{
                if(ty<y){
                    left=solveMaze(x,y-1,tx,ty,b,h);
                    right=solveMaze(x,y+1,tx,ty,b,h);
                }
                else{
                    right=solveMaze(x,y+1,tx,ty,b,h);
                    left=solveMaze(x,y-1,tx,ty,b,h);
                }
                if(tx<x){
                    up=solveMaze(x-1,y,tx,ty,b,h);
                    down=solveMaze(x+1,y,tx,ty,b,h);
                }
                else{
                    down=solveMaze(x+1,y,tx,ty,b,h);
                    up=solveMaze(x-1,y,tx,ty,b,h);
                }
            }
            //print opposite movement if the cell is a part of the path
            if(up||down||left||right){
                if(up)
                    System.out.println("DOWN");
                if(down)
                    System.out.println("UP");
                if(left)
                    System.out.println("RIGHT");
                if(right)
                    System.out.println("LEFT");
                return true;
            }
            maze[x][y]+=1;//backtrack
            return false;
        }
        return false;
    }
    public static void main(String[] args) {
        System.out.println("enter number of rows and columns ");
        System.out.print("Rows: ");
        int b = in.nextInt();
        System.out.print("Columns: ");
        int h = in.nextInt();
        maze=new int[b][h];
        System.out.println("enter maze 1 for path and 0 for wall");
        for(int i=0;i<b;i++)
            for(int j=0;j<h;j++)
                maze[i][j]=in.nextInt();
        System.out.print("Enter Jerry position\nX: ");
        int begx=in.nextInt();
        System.out.print("Y: ");
        int begy=in.nextInt();
        System.out.print("Enter cheese position\nX: ");
        int tarx=in.nextInt();
        System.out.print("Y: ");
        int tary=in.nextInt();
        if(!solveMaze(tarx,tary,begx,begy,b,h))
        System.out.println("no path");
    }
}

OUTPUT:

enter number of rows and columns
Rows: 5
Columns: 5
enter maze 1 for path and 0 for wall
1 0 1 0 1
1 0 1 0 1
1 0 1 1 1
1 0 0 1 0
1 1 1 1 0
Enter Jerry position
X: 0
Y: 0
Enter cheese position
X: 0
Y: 4

DOWN
DOWN
DOWN
DOWN
RIGHT
RIGHT
RIGHT
UP
UP
RIGHT
UP
UP
[Read more]