【问题标题】:Langton's Ant Algorithm兰顿的蚂蚁算法
【发布时间】:2023-03-27 17:39:01
【问题描述】:

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";
    }
}

我考虑过使用整数而不是字符串,但不太确定我应该怎么做。感谢您提供任何帮助或提示。


编辑:现在我改变了一些。我创建了一个有变量的 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];
    }
}

【问题讨论】:

  • 也可以尝试使用布尔值isMovingLeft。这将使切换更容易。
  • 使用enum 或常量,使用大量类似的文字很可怕且容易出错。

标签: java


【解决方案1】:

将枚举与next()prev() 函数结合使用,如in this answer 所述。然后右转只是一个next() 呼叫,左转是一个prev() 呼叫。

【讨论】:

  • +1,我只是在写同样的答案!可能会将next()prev() 重命名为left()right()
  • 感谢您的回答。我尝试使用您的示例。你能检查我的更新,看看我是否在正确的轨道上?
  • 我觉得不错。您正确处理了负数的索引:-)
【解决方案2】:

当您在 Java 中使用 == 比较 Strings 时,您不会得到预期的结果。请改用equals 方法。

我会考虑为NORTHSOUTHEASTWEST 定义一个enum

【讨论】:

  • 检查我的更新。这是你的意思吗?还有其他可以更智能的方式完成的事情吗?
  • @Goatcat 我没试过运行它,但看起来确实好多了。
【解决方案3】:

为每个方向分配一个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

【讨论】:

  • 这基本上不是位掩码吗?
  • 有点,但如果您不了解位移,则更容易理解。
  • 很公平。似乎有道理。我仍然认为这比枚举更优雅,但我想它不那么典型。
  • 这与@JimGarrison 的回答基本相同,但类型安全性较低,因为它使用的是整数而不是枚举。
  • 没错,我赞成他的。从 OP 中文字的使用来看,我认为类型安全并不是一个大问题,并采用了最简单易懂的答案。
【解决方案4】:

考虑使用enum 而不是NORTHSOUTH 等的字符串字面值。

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

switch 构造都支持字符串、枚举和整数,因此您也可以考虑使用它来代替 if/else 分支,以使代码更简洁。

【讨论】:

    【解决方案5】:

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

    1. 交换 dx dy

    后跟:

    2a。 dx=-dx,或

    2b。 dy=-dy

    (左右转)

    没有case语句,所以简单高效。只需 x+=dx, y+=dy 向前移动 - 并使用所示的交换/否定技巧来旋转。

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

    【讨论】:

    • 很高兴您找到了有效的解决方案!
    【解决方案6】:

    我觉得这里有一个优雅的解决方案,即使用位掩码。如果你这样做,那么你所有的转弯操作都可以用简单的位操作来完成。这里有一个关于使用位掩码的非常棒的教程: 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,并且每次转弯时都由您的指示器左移。

    【讨论】:

    • Java 没有 4 位数字,因此移位或实际旋转有点难看。但是在使用 32 位 int 时它可以正常工作:ideone.com/htgs2A(哎呀,旋转应该在某些时候反转)
    【解决方案7】:

    我会使用枚举。如:

    enum Directions {
        NORTH, 
        SOUTH, 
        EAST, 
        WEST
    }
    

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

    哦,还有,永远不要比较 String==。使用equals。见原因here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多