Skip to main content
Added some more examples
Source Link
Solonl
  • 131
  • 2

Completely move this to the JFrame view implementation. So code like this, can be easily moved to the view layer. Instead keep a list of marked Position objects and pass them to the view.

World.Color c = w.getCellColor(this.getX(), this.getY());

This will make your code view independent.

Completely move this to the JFrame view implementation.

Completely move this to the JFrame view implementation. So code like this, can be easily moved to the view layer. Instead keep a list of marked Position objects and pass them to the view.

World.Color c = w.getCellColor(this.getX(), this.getY());

This will make your code view independent.

Source Link
Solonl
  • 131
  • 2

There is a working example of the Langton's ant on github:

https://github.com/douma/langtons-ant-java

Use value objects to separate concerns and to make the code more readable

This implementation uses value objects for the ant's degree rotation and the position. Using value objects will improve the readability of your code.

Instead of writing

public Ant(int positionX, int positionY, Direction direction) {
    this.positionX = positionX;
    this.positionY = positionY;
    this.direction = direction;     
}

You could write:

public Ant(Position position, Direction direction) {
    this.position = position;
    this.direction = direction;     
}

Where Position is simply an immutable value object:

public class Position
{
    int x, y;

    Position(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    public Position left()
    {
        return new Position(this.x - 1, this.y);
    }

    public Position right()
    {
        return new Position(this.x + 1, this.y);
    }

    public Position up()
    {
        return new Position(this.x, this.y + 1);
    }

    public Position down()
    {
        return new Position(this.x, this.y - 1);
    }

    public int x()
    {
        return this.x;
    }

    public int y()
    {
        return this.y;
    }

    public String toString()
    {
        return "["+this.x+","+this.y+"]";
    }
}

My advice is to also write some tests if you have not done so. Creating smaller classes makes your implementation easier to test and testing is really beneficial for this specific logic.

Code is hard to read, encapsulate logic and use clear names

By encapsulating the logic more into separate classes, your code becomes more readable. Code like this is hard to read:

public void step(World w) {
    World.Color c = w.getCellColor(this.getX(), this.getY());
    this.direction = (World.Color.WHITE == c) ? this.direction.right()
                                              : this.direction.left();
    w.setCellColor(this.getX(), this.getY(), c.inverse());
    this.x += this.direction.deltaX;
    this.y += this.direction.deltaY;
    this.steps++;
}

Instead, look at the code below from the example it is almost the same as the business rules written in words:

public void moveAnt() throws Exception
{
    for(int x = 0; x < this.length; x++) {
        Position position = this.ant.position();
        if(this.isMarked(position)) {
            this.ant.forwardLeft();
            this.unmark(position);
        } else {
            this.ant.forwardRight();
            this.mark(position);
        }
    }
}

Business rules:

  • 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

Avoid using rendering logic in the code.

Completely move this to the JFrame view implementation.