Langton's Ant : Java Program Code explain

Langton’ s ant   work on two principle
At a white square, turn 90° right, flip the color of the square, move forward one unit
At a black square, turn 90° left, flip the color of the square, move forward one unit

In other words we can define langtons ant as the two dimensional  turing machine which has simple predefined rules but very complex emergent behaviour .
The theory of langtons ant was invented by the Chris Langton in 1986 . In that time he made it possible to run on a black and white square lattice .
The important thing about the langtons ant is that during the initial moves that is around first few hundreds 
moves the pattern is often symmetric . But  after few hundreds ,  the irregular patterns of white and black squares appear . Here we are not able to see the difference as we are using just 10 x 10 grid .So they follow pseudo random path till  ten thousands  starts .Now , when grid starts getting bigger than ten thousands than 
it starts building a recurrent highway pattern of 104 steps that repeat indefinitely .

Its  a very simple program , here we move endlessly in the defined grid .   This program ends when the cursor moves out of the grid .
We start with   the ant  facing north in the grid and  is in the white square .  So after applying the principle it
heads to the east direction and turn the white square black . Now similarly again applying Langtons principle
on the new position which has black square and east direction . So it will turn that into south direction and change the previous occupied square into white .
Here we consider the grid of 10x10 . If you want to better observe the trend then you can run it on 100x100. No matter the size of the grid the pattern almost remain the same for the langtons ant .
Below we created the four classes . 
First is LangtonsAnt.java , this file creates the grid and as well as checks whether the square is white or black . Then we move onto the Simulation.java where we check the direction of the ant if the ant is in north direction and in white square then turn it into east , and also we create the clone of the grid so that we can save the state of the object for the next time .So mainly direction is decided and clone is created in the Simulation.java file .


You can see the grid below when the langtons ant starts :



start langtons ant java program













Below image shows the langtons ant final stage , Remember that the langtons ant algorithm only stops when the grid becomes out of range , otherwise it keeps on running .


end langtons ant java program code














The code includes four java files

package langton;
import simulation.Ant;
import simulation.Grid;
import simulation.Simulation;
import core.Direction;
/**
*
* LangtonAnt class
*
* @author Subham
*
*/
public class LangtonAnt {
    /**
    * Main method.
    *
    * You do not need to modify this method.
    */
    public static void main(String[] args) {
        // create a simulation with given parameters
        Simulation sim = new Simulation(10, 10, 5, 5, Direction.NORTH, 10);
        // while the simulation is not finished
        while (!sim.isCompleted()) {
            // get current board
            
            Grid board = sim.cloneCurrentGrid();
            // get current ant
            Ant ant = sim.cloneCurrentAnt();
            // print out the ant and board
            System.out.print("+");
            for (int j = 0; j < board.getWidth(); ++j) {
                System.out.print("-");
            }
            System.out.println("+");
            for (int i = 0; i < board.getHeight(); ++i) {
                System.out.print("|");
                for (int j = 0; j < board.getWidth(); ++j) {
                    if (i ==ant.getIPos() &&  j == ant.getJPos()) {
                        switch (ant.getDirection()) {
                            case NORTH:
                            System.out.print("^");
                            break;
                            case SOUTH:
                            System.out.print("v");
                            break;
                            case EAST:
                            System.out.print(">");
                            break;
                            case WEST:
                            System.out.print("<");
                            break;
                        }
                        } else {
                        if (board.isWhite(i, j)) {
                            System.out.print(" ");
                            } else {
                            System.out.print("*");
                        }
                    }
                }
                System.out.println("|");
            }
            
            System.out.print("+");
            for (int j = 0; j < board.getWidth(); ++j) {
                System.out.print("-");
            }
            System.out.println("+");
            
            /*
            * make the computer wait 150 ms to make it easier to view the ant's
            * progression
            */
            try {
                Thread.sleep(150);
                } catch (InterruptedException e) {
                // do nothing
            }
            
            // execute a step
            sim.executeStep();
            // buffer to make it easier to read
            System.out.println();
        }
    }
}

Ant.java

package simulation;
import core.Direction;

/**
*
* Ant class
*
* @author Subham
*
*/
public class Ant implements Cloneable {
    
    int iPos;
    int jPos;
    Direction direction;
    Ant ant;
    
    public Ant(int iPos, int jPos, Direction direction){
        // TODO fill in this constructor
        this.iPos=iPos;
        this.jPos=jPos;
        this.direction=direction;
        
    }
    
    
    
    public int getIPos() {
        return iPos;
    }
    
    
    
    protected void setIPos(int iPos)  {
        this.iPos = iPos;
    }
    
    
    
    public int getJPos() {
        return jPos;
    }
    
    
    
    protected void setJPos(int jPos){
        this.jPos = jPos;
    }
    
    
    public Direction getDirection() {
        return direction;
    }
    
    protected void setDirection(Direction direction) {
        // TODO fill in this method
        this.direction=direction;
    }
    
    @Override
    public String toString() {
        return "Ant [iPos=" + iPos + ", jPos=" + jPos + ", direction="
        + direction + ", ant=" + ant + "]";
    }
    
    
    
    public Ant clone()
    {
        
        try {
            ant= (Ant)super.clone();
        }
        catch (CloneNotSupportedException e) {
            // This should never happen
            System.out.println("maa chud gayi ant main ");
        }
        return ant;
    }
}

Grid.java
package simulation;
import java.util.Arrays;
/**
*
* Grid class
*
* @author Subham
*
*/
public class Grid implements Cloneable {
    
    boolean[][] grid;
    int height;
    int width;
    Grid  gri;
    
    /**
    * Constructor for the grid.
    *
    * Initial state is that the every cell in the grid is white
    *
    * @param height - height of the grid
    * @param width - width of the grid
    */
    public Grid(int height, int width) {
        this.height=height;
        this.width=width;
        grid=new boolean[height][width];
        for(int i=0;i < height;i++)
        { for(int j=0;j < width;j++)
            {
                grid[i][j]=true;
            }
        }
    }
    
    public boolean[][] getGrid() {
        return grid;
    }
    
    public void setGrid(boolean[][] grid) {
        this.grid = grid;
    }
    
    public int getHeight() {
        return height;
    }
    
    public int getWidth() {
        return width;
    }
    
    public boolean isWhite(int i, int j) {
        // TODO fill in this method
        return grid[i][j];
    }
    
    
    
    protected void setWhite(int i, int j) {
        // TODO fill in this method
        if(i < height && j < width)
        grid[i][j]=true;
        
    }
    
    protected void setBlack(int i, int j) {
        // TODO fill in this method
        if(i < height && j < width)
        grid[i][j]=false;
    }
    
    @Override
    public Grid clone() {
        try {
            gri= (Grid)super.clone();
        }
        catch (CloneNotSupportedException e) {
            // This should never happen
        }
        return gri;
    }
    
    @Override
    public String toString() {
        return "Grid [grid=" + Arrays.toString(grid) + ", height=" + height
        + ", width=" + width + ", gri=" + gri + "]";
    }
}
Simulation.java
package simulation;
import core.Direction;
/**
*
* Simulation class
*
* @author Subham
*
*/
public class Simulation implements Cloneable{
    
    /**
    * Initialize instance variables in this constructor
    *
    * @param height - the height of the grid
    * @param width - the width of the grid
    * @param antStartI - the original I coordinate of the ant
    * @param antStartJ - the original J coordinate of the ant
    * @param originalDirection - the original direction the ant is facing
    */
    
    int hei;
    int wid;
    int antStaI;
    int antStaJ;
    Direction oriDir;
    int maxTim;
    Ant ant;
    Grid grid;
    Ant a;
    Grid g;
    public Simulation(int height, int width, int antStartI, int antStartJ,
    Direction originalDirection, int maxTimeSteps) {
        // TODO fill in this constructor
        this.hei=height;
        this.wid=width;
        this.antStaI=antStartI;
        this.antStaJ=antStartJ;
        this.oriDir=originalDirection;
        this.maxTim=maxTimeSteps;
        this.ant=new Ant(antStartI,antStartJ,originalDirection);
        this.grid=new Grid(height,width);
        
    }
    
    /**
    * Execute a time step for the simulation.
    *
    * The ant must:
    * * move forward 1 space
    * - if this movement would cause it to move off the grid,
    * the simulation is completed.
    * * rotate depending on the state of the cell the ant is occupying
    * - if the cell is white, rotate left
    * - otherwise, rotate right
    * * change the state of the cell the ant is currently occupying
    * - if the cell is white, it becomes black
    * - otherwise, it becomes white
    *
    * NOTE: this method should do nothing if the simulation is completed.
    */
    public void executeStep() {
        // TODO fill in this method
        int i= ant.getIPos();
        int j=ant.getJPos();
        if(grid.isWhite(ant.getIPos(), ant.getJPos()))
        {
            grid.setBlack(i, j);
            switch (ant.getDirection()) {
                case NORTH:
                {
                    ant.setDirection(Direction.EAST);
                    ant.setJPos(++j);
                    break;
                }
                case SOUTH:
                {
                    ant.setDirection(Direction.WEST);
                    ant.setJPos(--j);
                    break;
                }
                case EAST:
                {
                    ant.setDirection(Direction.SOUTH);
                    ant.setIPos(++i);
                    break;
                }
                case WEST:
                {
                    ant.setDirection(Direction.NORTH);
                    ant.setIPos(--i);
                    break;
                }
            }
        }
        else
        {
            grid.setWhite(i, j);
            switch (ant.getDirection()) {
                case NORTH:
                {
                    ant.setDirection(Direction.WEST);
                    ant.setJPos(--j);
                    break;
                }
                case SOUTH:
                {
                    ant.setDirection(Direction.EAST);
                    ant.setJPos(++j);
                    break;
                }
                case EAST:
                {
                    ant.setDirection(Direction.NORTH);
                    ant.setIPos(--i);
                    break;
                }
                case WEST:
                {
                    ant.setDirection(Direction.SOUTH);
                    ant.setIPos(++i);
                    break;
                }
            }
        }
        
        
    }
    
    /**
    * Method to check if the simulation is completed.
    *
    * The simulation is completed if and only if:
    * * it has reached the maximum time steps allowed
    * * the ant has moved off the grid
    *
    * @return true - the simulation is completed
    * @return false - the simulation is not completed
    */
    public boolean isCompleted() {
        // TODO fill in this method
        if(ant.getIPos() >=maxTim || ant.getJPos()>=maxTim)
        return true;
        else
        return false;
        
    }
    
    /**
    * Method to return a copy of the current grid.
    *
    * You should always return a copy of an object if you do not
    * want your base object to be changed by any code calling this method.
    *
    * @return a clone of the grid.
    */
    public Grid cloneCurrentGrid() {
        // TODO fill in this method
        
        g= grid.clone();
        return g;
    }
    
    /**
    * Method to return a copy of the current ant.
    *
    * You should always return a copy of an object if you do not
    * want your base ect to be changed by any code calling this method.
    *
    * NOTE: Do not canche this value, return a new object for every call.
    *
    * @return a clone of the ant.
    */
    public Ant cloneCurrentAnt() {
        // TODO fill in this method
        
        a = ant.clone();
        return a;
    }
}
Direction.java
package core;
public enum Direction {
    NORTH, SOUTH, EAST, WEST;
}

About The Author

Subham Mittal has worked in Oracle for 3 years.
Enjoyed this post? Never miss out on future posts by subscribing JavaHungry