Langton蚂蚁算法

时间:2013-07-23 17:16:02

标签: java

Langton's Ant的问题很简单。一只蚂蚁走在白板和黑色方块的板上。

  • 在白色方块,向右转90°,翻转方块的颜色,向前移动一个单位
  • 在黑色正方形,向左转90°,翻转正方形的颜色,向前移动一个单位

当“游戏”开始时,棋盘全是白色的。

我已经实施了模拟但是有一个非常丑陋的步行和转弯解决方案我需要帮助改进。现在步行如下:

if (dir == "NORTH") {
    // Walk up
} else if (dir == "EAST") {
    // Walk right
} else if (dir == "SOUTH") {
    // Walk down
} else if (dir == "WEST") {
    // Walk left
}           

改变方向的功能:

private void turn(String leftOrRight){
    if(dir == "NORTH" && lor == "RIGHT" ){
        dir = "EAST";
    } else if (dir == "NORTH" && leftOrRight == "LEFT" ){
        dir = "WEST";
    } else if (dir == "EAST" && leftOrRight == "RIGHT" ){
        dir = "SOUTH";
    } else if (dir == "EAST" && leftOrRight == "LEFT" ){
        dir = "NORTH";
    } else if (dir == "SOUTH" && leftOrRight == "RIGHT" ){
        dir = "WEST";
    } else if (dir == "SOUTH" && leftOrRight == "LEFT" ){
        dir = "EAST";
    } else if (dir == "WEST" && leftOrRight == "RIGHT" ){
        dir = "NORTH";
    } else if (dir == "WEST" && leftOrRight == "LEFT" ){
        dir = "SOUTH";
    }
}

我曾考虑使用int而不是字符串,但不太确定我应该怎么做。任何帮助或提示都表示赞赏。


编辑:现在我改变了一些。我创建了一个具有变量

的Ant类
int x, int y, Direction dir

使用以下方法运行它:

private void runAnt(Ant ant) {
    int x = ant.getX();
    int y = ant.getY();

    // Check rule 1
    if (matrix[x][y] == true) {
        matrix[x][y] = false;
        w.setDot(x, y, Color.WHITE);
        ant.setDirection(ant.getDirection().right());

    // Check rule 2
    } else if (matrix[x][y] == false) {
        matrix[x][y] = true;
        w.setDot(x, y, Color.BLACK);
        ant.setDirection(ant.getDirection().left());
    }

    // Moves one unit forward according to direction.
    if (ant.getDirection().equals(Direction.N)) {
        ant.setY((ant.getY() - 1 + wSize) % wSize);

    } else if (ant.getDirection().equals(Direction.E)) {
        ant.setX((ant.getX() + 1) % wSize);

    } else if (ant.getDirection().equals(Direction.S)) {
        ant.setY((ant.getY() + 1) % wSize);

    } else if (ant.getDirection().equals(Direction.W)) {
        ant.setX((ant.getX() - 1 + wSize) % wSize);
    }
}

我的第一个枚举:

public static enum Direction {
    N, E, S, W;
    private static Direction[] vals = values();

    public Direction right() {
        return vals[(this.ordinal() + 1) % vals.length];
    }

    public Direction left() {
        return vals[(this.ordinal() + vals.length - 1) % vals.length];
    }
}

7 个答案:

答案 0 :(得分:5)

使用带有next()prev()函数的枚举进行组合,如in this answer所述。然后右转只是next()来电,左转是prev()来电。

答案 1 :(得分:3)

当您使用==比较Java中的String时,您不会得到您期望的结果。改为使用equals方法。

我会考虑为NORTHSOUTHEASTWEST定义enum

答案 2 :(得分:2)

为每个方向分配一个int(顺时针方向):

NORTH = 0;
EAST = 1;
SOUTH = 2;
WEST = 3;

将左侧指定为-1;正确为1:

LEFT = -1;
RIGHT = 1;

然后你可以有一个简单的功能来改变方向:

private void turn(int leftOrRight){
    dir = (dir + leftOrRight) % 4;
}

假设您不想出于任何原因使用enums

答案 3 :(得分:1)

考虑为NORTHSOUTH等使用enum代替字符串文字。

枚举是类型安全的,因此如果您不小心键入SUOTH而不是SOUTH,编译器会发出警告。此外,enum个实例可以安全地与==进行比较(除非涉及序列化的一些奇怪的边缘情况)。您现在将字符串与==而不是equals进行比较的方式可能会导致一些潜在的问题,具体取决于dirleftOrRight的来源。 Take a look at this answer for an explanation of == vs equals on strings.

switch构造支持字符串,枚举和整数,因此您也可以考虑使用它而不是if / else分支来使代码更清晰。

答案 4 :(得分:1)

如果您的方向以dx,dy位移存储,例如{0,-1} 然后向左和向右转:

  1. 交换dx <=> dy

后跟一个:

2a。 dx = -dx或

2b。 dy = -dy

(左右旋转)

没有案例陈述,因此它简单有效。只需x + = dx,y + = dy向前移动-并使用所示的交换/求反技巧即可旋转。

为什么不必要地使事情复杂化:/

答案 5 :(得分:0)

我觉得通过使用bitmasking可以获得优雅的解决方案。如果你这样做,那么所有的转弯操作都可以通过简单的位操作来完成。这里有一个非常棒的使用位掩码的教程: http://www.vipan.com/htdocs/bitwisehelp.html

例如,如果您将方向表示为4位数并转换为简单布尔值,则可以在单个if / else语句中执行此操作:

if (leftOrRight == 0){
    //right shift one bit
}
else if (leftOrRight == 1){
    //left shift one bit
}

或者你可以让你的左/右指示器为1或-1,并在每个转弯处左右移动指示器。

答案 6 :(得分:0)

我会使用枚举。如:

enum Directions {
    NORTH, 
    SOUTH, 
    EAST, 
    WEST
}

如果您使用Java 6,您也可以使用它。

哦,还有,从不String==进行比较。使用equals。查看原因here