Open In App

Rat in a Maze | Backtracking using Stack

Improve
Improve
Like Article
Like
Save
Share
Report

PrerequisitesRecursion, Backtracking and Stack Data Structure.

A Maze is given as N*M binary matrix of blocks and there is a rat initially at (0, 0) ie. maze[0][0] and the rat wants to eat food which is present at some given block in the maze (fx, fy). In a maze matrix, 0 means that the block is a dead end and 1 means that the block can be used in the path from source to destination. The rat can move in any direction (not diagonally) to any block provided the block is not a dead end. 

The task is to check if there exists any path so that the rat can reach the food or not. It is not needed to print the path.

Examples

Input : maze[4][5] = {
            {1, 0, 1, 1, 0},
            {1, 1, 1, 0, 1},
            {0, 1, 0, 1, 1},
            {1, 1, 1, 1, 1}
        }
        fx = 2, fy=3
Output : Path Found!
The path can be: (0, 0) -> (1, 0) -> (1, 1) -> (2, 1) -> (3, 1) -> (3, 2)  -> (3, 3) -> (2, 3)  

This is the famous Rat in a Maze problem asked in many interviews that can be solved using Recursion and Backtracking. We already have discussed a Backtracking solution to this problem using recursion in Rat in a Maze | Backtracking-2. In this an iterative solution using stack is discussed.
In the previous article, Recursion uses a call stack to keep the store each recursive call and then pop as the function ends. We will eliminate recursion by using our own stack to do the same thing.

A node structure is used to store the (i, j) coordinates and directions explored from this node and which direction to try out next. 

Structure Used: 

  1. X : x coordinate of the node 
  2. Y : y coordinate of the node 
  3. dir : This variable will be used to tell which all directions we have tried and which to choose next. We will try all the directions in anti-clockwise manner starting from Up. Initially it will be assigned 0. 
    • If dir=0 try Up direction.
    • If dir=1 try left direction.
    • If dir=2 try down direction.
    • If dir=3 try right direction.

Initially, we will push a node with indexes i=0, j=0 and dir=0 into the stack. We will move to all the direction of the topmost node one by one in an anti-clockwise manner and each time as we try out a new path we will push that node (block of the maze) in the stack. We will increase dir variable of the topmost node each time so that we can try a new direction each time unless all the directions are explored ie. dir=4. If dir equals to 4 we will pop that node from the stack that means we are retracting one step back to the path where we came from.

We will also maintain a visited matrix which will maintain which blocks of the maze are already used in the path or in other words present in the stack. While trying out any direction we will also check if the block of the maze is not a dead end and is not out of the maze too.

We will do this while either the topmost node coordinates become equal to the food’s coordinates that means we have reached the food or the stack becomes empty which means that there is no possible path to reach the food.

Below is the implementation of the above approach: 

C++

// CPP program to solve Rat in a maze
// problem with backtracking using stack
 
#include <cstring>
#include <iostream>
#include <stack>
 
using namespace std;
 
#define N 4
#define M 5
 
class node {
public:
    int x, y;
    int dir;
 
    node(int i, int j)
    {
        x = i;
        y = j;
         
        // Initially direction
        // set to 0
        dir = 0;
    }
};
 
// maze of n*m matrix
int n = N, m = M;
 
// Coordinates of food
int fx, fy;
bool visited[N][M];
 
bool isReachable(int maze[N][M])
{
    // Initially starting at (0, 0).
    int i = 0, j = 0;
     
    stack<node> s;
     
    node temp(i, j);
     
    s.push(temp);
 
    while (!s.empty()) {
 
        // Pop the top node and move to the
        // left, right, top, down or retract
        // back according the value of node's
        // dir variable.
        temp = s.top();
        int d = temp.dir;
        i = temp.x, j = temp.y;
 
        // Increment the direction and
        // push the node in the stack again.
        temp.dir++;
        s.pop();
        s.push(temp);
 
        // If we reach the Food coordinates
        // return true
        if (i == fx and j == fy) {
            return true;
        }
 
        // Checking the Up direction.
        if (d == 0) {
            if (i - 1 >= 0 and maze[i - 1][j] and
                                    visited[i - 1][j]) {
                node temp1(i - 1, j);
                visited[i - 1][j] = false;
                s.push(temp1);
            }
        }
 
        // Checking the left direction
        else if (d == 1) {
            if (j - 1 >= 0 and maze[i][j - 1] and
                                    visited[i][j - 1]) {
                node temp1(i, j - 1);
                visited[i][j - 1] = false;
                s.push(temp1);
            }
        }
 
        // Checking the down direction
        else if (d == 2) {
            if (i + 1 < n and maze[i + 1][j] and
                                    visited[i + 1][j]) {
                node temp1(i + 1, j);
                visited[i + 1][j] = false;
                s.push(temp1);
            }
        }
        // Checking the right direction
        else if (d == 3) {
            if (j + 1 < m and maze[i][j + 1] and
                                    visited[i][j + 1]) {
                node temp1(i, j + 1);
                visited[i][j + 1] = false;
                s.push(temp1);
            }
        }
 
        // If none of the direction can take
        // the rat to the Food, retract back
        // to the path where the rat came from.
        else {
            visited[temp.x][temp.y] = true;
            s.pop();
        }
    }
 
    // If the stack is empty and
    // no path is found return false.
    return false;
}
 
// Driver code
int main()
{
    // Initially setting the visited
    // array to true (unvisited)
    memset(visited, true, sizeof(visited));
     
    // Maze matrix
    int maze[N][M] = {
        { 1, 0, 1, 1, 0 },
        { 1, 1, 1, 0, 1 },
        { 0, 1, 0, 1, 1 },
        { 1, 1, 1, 1, 1 }
    };
 
    // Food coordinates
    fx = 2;
    fy = 3;
 
    if (isReachable(maze)) {
        cout << "Path Found!" << '\n';
    }
    else
        cout << "No Path Found!" << '\n';
         
    return 0;
}

                    

Java

// Java program to solve Rat in a maze
// problem with backtracking using stack
import java.util.Stack;
 
class Node
{
    private int x, y;
    private int dir;
 
    public Node(int i, int j)
    {
        this.x = i;
        this.y = j;
         
        // default value for direction set to 0 (Up)
        this.dir = 0;
    }
 
    public int getX()
    {
        return x;
    }
 
    public void setX(int x)
    {
        this.x = x;
    }
 
    public int getY()
    {
        return y;
    }
 
    public void setY(int y)
    {
        this.y = y;
    }
 
    public int getDir()
    {
        return dir;
    }
 
    public void setDir(int dir)
    {
        this.dir = dir;
    }
}
 
public class RatInMaze
{
    private static final int N = 4;
    private static final int M = 5;
 
    // maze of n*m matrix
    int n = N, m = M;
 
    private static boolean[][] visited = new boolean[N][M];
 
        // Driver code
    public static void main(String[] args)
    {
        // Initially setting the visited
        // array to true (unvisited)
        setVisited(true);
 
        // Maze matrix
        int maze[][] = {{ 1, 0, 1, 1, 0 },
                        { 1, 1, 1, 0, 1 },
                        { 0, 1, 0, 1, 1 },
                        { 1, 1, 1, 1, 1 } };
 
        if (isReachable(maze))
        {
            System.out.println("Path Found!\n");
        }
        else
            System.out.println("No Path Found!\n");
    }
 
    private static void setVisited(boolean b)
    {
        for (int i = 0; i < visited.length; i++)
        {
            for (int j = 0; j < visited[i].length; j++)
            {
                visited[i][j] = b;
            }
        }
 
    }
 
    private static boolean isReachable(int maze[][])
    {
        // Initially starting at (0, 0).
        int i = 0, j = 0;
         
        // Food coordinates
        // Coordinates of food
        int fx, fy;
        fx = 2;
        fy = 3;
 
        Stack<Node> s = new Stack<Node>();
 
        Node temp = new Node(i, j);
 
        s.push(temp);
 
        while (!s.empty())
        {
 
            // Pop the top node and move to the
            // left, right, top, down or retract
            // back according the value of node's
            // dir variable.
            temp = s.peek();
            int d = temp.getDir();
            i = temp.getX();
            j = temp.getY();
 
            // Increment the direction and
            // push the node in the stack again.
            temp.setDir(temp.getDir() + 1);
            s.pop();
            s.push(temp);
 
            // If we reach the Food coordinates
            // return true
            if (i == fx && j == fy)
            {
                return true;
            }
 
            if (d == 0)
            {
                // Checking the Up direction.
                if (i - 1 >= 0 && maze[i - 1][j] == 1 &&
                                        visited[i - 1][j])
                {
                    Node temp1 = new Node(i - 1, j);
                    visited[i - 1][j] = false;
                    s.push(temp1);
                }
            }
            else if (d == 1)
            {
                // Checking the left direction
                if (j - 1 >= 0 && maze[i][j - 1] == 1 &&
                                        visited[i][j - 1])
                {
                    Node temp1 = new Node(i, j - 1);
                    visited[i][j - 1] = false;
                    s.push(temp1);
                }
            }
            else if (d == 2)
            {
                // Checking the down direction
                if (i + 1 < N && maze[i + 1][j] == 1 &&
                                        visited[i + 1][j])
                {
                    Node temp1 = new Node(i + 1, j);
                    visited[i + 1][j] = false;
                    s.push(temp1);
                }
            }
            else if (d == 3)
            {
                // Checking the right direction
                if (j + 1 < M && maze[i][j + 1] == 1 &&
                                        visited[i][j + 1])
                {
                    Node temp1 = new Node(i, j + 1);
                    visited[i][j + 1] = false;
                    s.push(temp1);
                }
            }
 
            // If none of the direction can take
            // the rat to the Food, retract back
            // to the path where the rat came from.
            else
            {
                visited[temp.getX()][temp.getY()] = true;
                s.pop();
            }
        }
 
        // If the stack is empty and
        // no path is found return false.
        return false;
    }
}
 
// This code is contributed by nirajtechi

                    

C#

// C# program to solve Rat in a maze
// problem with backtracking using stack
using System;
using System.Collections.Generic;
 
public class Node
{
    private int x, y;
    private int dir;
 
    public Node(int i, int j)
    {
        this.x = i;
        this.y = j;
         
        // default value for direction set to 0 (Up)
        this.dir = 0;
    }
 
    public int getX()
    {
        return x;
    }
    public void setX(int x)
    {
        this.x = x;
    }
    public int getY()
    {
        return y;
    }
    public void setY(int y)
    {
        this.y = y;
    }
    public int getDir()
    {
        return dir;
    }
    public void setDir(int dir)
    {
        this.dir = dir;
    }
}
 
public class RatInMaze
{
    private static readonly int N = 4;
    private static readonly int M = 5;
 
    // maze of n*m matrix
    int n = N, m = M;
 
    private static bool [,]visited = new bool[N,M];
 
        // Driver code
    public static void Main(String[] args)
    {
        // Initially setting the visited
        // array to true (unvisited)
        setVisited(true);
 
        // Maze matrix
        int [,]maze = {{ 1, 0, 1, 1, 0 },
                        { 1, 1, 1, 0, 1 },
                        { 0, 1, 0, 1, 1 },
                        { 1, 1, 1, 1, 1 } };
 
        if (isReachable(maze))
        {
            Console.WriteLine("Path Found!\n");
        }
        else
            Console.WriteLine("No Path Found!\n");
    }
 
    private static void setVisited(bool b)
    {
        for (int i = 0; i < visited.GetLength(0); i++)
        {
            for (int j = 0; j < visited.GetLength(0); j++)
            {
                visited[i,j] = b;
            }
        }
 
    }
 
    private static bool isReachable(int [,]maze)
    {
        // Initially starting at (0, 0).
        int i = 0, j = 0;
         
        // Food coordinates
        // Coordinates of food
        int fx, fy;
        fx = 2;
        fy = 3;
 
        Stack<Node> s = new Stack<Node>();
 
        Node temp = new Node(i, j);
 
        s.Push(temp);
 
        while (s.Count!=0)
        {
 
            // Pop the top node and move to the
            // left, right, top, down or retract
            // back according the value of node's
            // dir variable.
            temp = s.Peek();
            int d = temp.getDir();
            i = temp.getX();
            j = temp.getY();
 
            // Increment the direction and
            // push the node in the stack again.
            temp.setDir(temp.getDir() + 1);
            s.Pop();
            s.Push(temp);
 
            // If we reach the Food coordinates
            // return true
            if (i == fx && j == fy)
            {
                return true;
            }
 
            if (d == 0)
            {
                // Checking the Up direction.
                if (i - 1 >= 0 && maze[i - 1,j] == 1 &&
                                        visited[i - 1,j])
                {
                    Node temp1 = new Node(i - 1, j);
                    visited[i - 1,j] = false;
                    s.Push(temp1);
                }
            }
            else if (d == 1)
            {
                // Checking the left direction
                if (j - 1 >= 0 && maze[i,j - 1] == 1 &&
                                        visited[i,j - 1])
                {
                    Node temp1 = new Node(i, j - 1);
                    visited[i,j - 1] = false;
                    s.Push(temp1);
                }
            }
            else if (d == 2)
            {
                // Checking the down direction
                if (i + 1 < N && maze[i + 1,j] == 1 &&
                                        visited[i + 1,j])
                {
                    Node temp1 = new Node(i + 1, j);
                    visited[i + 1,j] = false;
                    s.Push(temp1);
                }
            }
            else if (d == 3)
            {
                // Checking the right direction
                if (j + 1 < M && maze[i,j + 1] == 1 &&
                                        visited[i,j + 1])
                {
                    Node temp1 = new Node(i, j + 1);
                    visited[i,j + 1] = false;
                    s.Push(temp1);
                }
            }
 
            // If none of the direction can take
            // the rat to the Food, retract back
            // to the path where the rat came from.
            else
            {
                visited[temp.getX(),temp.getY()] = true;
                s.Pop();
            }
        }
 
        // If the stack is empty and
        // no path is found return false.
        return false;
    }
}
 
// This code contributed by Rajput-Ji

                    

Python3

# Python3 program to solve Rat in a maze
# problem with backtracking using stack
 
N=4
M=5
 
class node:
    def __init__(self,i,j):
        self.x=i
        self.y=j
        self.dirn=0
 
# maze of n*m matrix
n = N; m = M
 
# Coordinates of food
fx=0; fy=0
visited=[[True]*N for _ in range(M)]
 
def isReachable(maze):
 
    # Initially starting at (0, 0).
    i = 0; j = 0
     
    s=[]
     
    temp=node(i, j)
     
    s.append(temp)
 
    while s:
 
        # Pop the top node and move to the
        # left, right, top, down or retract
        # back according the value of node's
        # dirn variable.
        temp = s.pop()
        d = temp.dirn
        i = temp.x; j = temp.y
 
        # Increment the direction and
        # push the node in the stack again.
        temp.dirn+=1
        s.append(temp)
 
        # If we reach the Food coordinates
        # return true
        if (i == fx and j == fy):
            return True
 
 
        # Checking the Up direction.
        if (d == 0):
            if (i - 1 >= 0 and maze[i - 1][j] and visited[i - 1][j]):
                temp1=node(i - 1, j)
                visited[i - 1][j] = False
                s.append(temp1)
             
 
        # Checking the left direction
        elif (d == 1):
            if(j - 1 >= 0 and maze[i][j - 1] and visited[i][j - 1]):
                temp1=node(i, j - 1)
                visited[i][j - 1] = False
                s.append(temp1)
 
 
        # Checking the down direction
        elif (d == 2):
            if(i + 1 < n and maze[i + 1][j] and visited[i + 1][j]):
                temp1=node(i + 1, j)
                visited[i + 1][j] = False
                s.append(temp1)
             
         
        # Checking the right direction
        elif (d == 3):
            if (j + 1 < m and maze[i][j + 1] and visited[i][j + 1]):
                temp1=node(i, j + 1)
                visited[i][j + 1] = False
                s.append(temp1)
 
        # If none of the direction can take
        # the rat to the Food, retract back
        # to the path where the rat came from.
        else:
            visited[temp.x][temp.y] = True
            s.pop()
 
 
    # If the stack is empty and
    # no path is found return false.
    return False
 
# Driver code
if __name__ == '__main__':
 
    # Initially setting the visited
    # array to true (unvisited)
     
    # Maze matrix
    maze = [
        [ 1, 0, 1, 1, 0 ],
        [ 1, 1, 1, 0, 1 ],
        [ 0, 1, 0, 1, 1 ],
        [ 1, 1, 1, 1, 1 ]
    ]
 
    # Food coordinates
    fx = 2
    fy = 3
 
    if (isReachable(maze)):
        print("Path Found!")
    else:
        print("No Path Found!")

                    

Javascript

<script>
 
// JavaScript program to solve Rat in a maze
// problem with backtracking using stack
 
const N = 4
const M = 5
 
class node{
    constructor(i, j){
        this.x = i
        this.y = j
        this.dirn = 0
   }
}
 
// maze of n*m matrix
let n = N, m = M
 
// Coordinates of food
let fx = 0, fy = 0
let visited = new Array(N);
for(let i = 0; i < N; i++){
   visited[i] = new Array(M).fill(true);
}
 
function isReachable(maze){
 
    // Initially starting at (0, 0).
    let i = 0, j = 0
    let s=[]
    let temp=new node(i, j)
    s.push(temp)
 
    while(s.length>0){
 
        // Pop the top node && move to the
        // left, right, top, down or retract
        // back according the value of node's
        // dirn variable.
        temp = s[s.length - 1]
      s.pop()
        let d = temp.dirn
        i = temp.x, j = temp.y
 
        // Increment the direction &&
        // push the node in the stack again.
        temp.dirn+=1
        s.push(temp)
 
        // If we reach the Food coordinates
        // return true
        if (i == fx && j == fy)
            return true
 
 
        // Checking the Up direction.
        if (d == 0){
            if (i - 1 >= 0 && maze[i - 1][j] && visited[i - 1][j]){
                let temp1=new node(i - 1, j)
                visited[i - 1][j] = false
                s.push(temp1)
         }
      }
             
        // Checking the left direction
        else if (d == 1){
            if(j - 1 >= 0 && maze[i][j - 1] && visited[i][j - 1]){
                let temp1=new node(i, j - 1)
                visited[i][j - 1] = false
                s.push(temp1)
         }
      }
 
        // Checking the down direction
        else if (d == 2){
            if(i + 1 < n && maze[i + 1][j] && visited[i + 1][j]){
                let temp1=new node(i + 1, j)
                visited[i + 1][j] = false
                s.push(temp1)
         }
      }
             
        // Checking the right direction
        else if (d == 3){
            if (j + 1 < m && maze[i][j + 1] && visited[i][j + 1]){
                let temp1=new node(i, j + 1)
                visited[i][j + 1] = false
                s.push(temp1)
         }
      }
 
        // If none of the direction can take
        // the rat to the Food, retract back
        // to the path where the rat came from.
        else{
            visited[temp.x][temp.y] = true
            s.pop()
      }
   }
 
    // If the stack is empty &&
    // no path is found return false.
    return false
}
 
// Driver code
 
// Initially setting the visited
// array to true (unvisited)
 
// Maze matrix
let maze = [
        [ 1, 0, 1, 1, 0 ],
        [ 1, 1, 1, 0, 1 ],
        [ 0, 1, 0, 1, 1 ],
        [ 1, 1, 1, 1, 1 ]
]
 
// Food coordinates
fx = 2
fy = 3
 
if (isReachable(maze))
    document.write("Path Found!","</br>")
else
    document.write("No Path Found!","</br>")
 
// This code is contributed by shinjanpatra
 
</script>

                    

Output
Path Found!

Note: We can also print the path by just popping the nodes out of the stacks and then print them in reverse order.

Complexity Analysis:

  • Time Complexity : O(2 ^ {N * M}     )
  • Auxiliary Space: O(N*M     ). 


Last Updated : 01 Sep, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads