5

兰顿蚂蚁的问题很简单。一只蚂蚁在一块有白色和黑色方块的板上行走。

  • 在一个白色方块处,向右转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];
    }
}
4

7 回答 7

5

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

于 2013-07-23T17:22:53.877 回答
3

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

我会考虑为、、和定义一个枚举NORTHSOUTHEASTWEST

于 2013-07-23T17:19:53.160 回答
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,无论出于何种原因。

于 2013-07-23T17:25:57.913 回答
1

考虑对,等使用枚举而不是字符串文字。NORTHSOUTH

枚举是类型安全的,因此如果您不小心键入SUOTH而不是SOUTH. 此外,enum可以安全地比较实例==(除了一些涉及序列化的奇怪边缘情况)。您现在比较字符串与==而不是equals现在的方式可能会导致一些潜在的问题,具体取决于哪里dirleftOrRight来自哪里。看一下这个答案,了解关于字符串的==vs的解释。equals

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

于 2013-07-23T17:19:04.727 回答
1

如果您的方向被存储为 dx,dy 位移,例如 {0, -1} 那么向左和向右转是:

  1. 交换 dx <=> dy

后跟以下之一:

2a. dx=-dx,或

2b。dy=-dy

(左右转)

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

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

于 2019-03-27T01:21:59.633 回答
0

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

于 2013-07-23T17:19:30.057 回答
0

我会使用枚举。如:

enum Directions {
    NORTH, 
    SOUTH, 
    EAST, 
    WEST
}

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

哦,而且,永远不要String. ==使用equals. 看这里的原因。

于 2013-07-23T17:19:38.377 回答