蛇游戏:蛇段的定位错误

时间:2018-09-23 10:50:47

标签: java

我正在写蛇游戏,所以我制作了一个SnakeLogic类来表示蛇的逻辑模型。

实现如下:蛇由段组成,每个段保持其起始位置,长度和运动方向。这是Segment类(SnakeLogic的内部类)的完整代码:

protected class Segment{

    public Point location;
    public SnakeDirection dir;
    public int length;

    public Segment(Point l, SnakeDirection dir,int length){
        location=l;
        this.dir=dir;
        this.length=length;
    }

}

段以LinkedList保留:

private LinkedList<Segment> nodes; 

更改方向后,新的句段将添加到LinkedList的开头:

public void setDirection(SnakeDirection dir){
    //gets location and direction of first segment
    Point head = nodes.getFirst().location;
    SnakeDirection currentDir = nodes.getFirst().dir;
    //if direction isn't changed, return
    if (currentDir == dir) return;
    //ignores directions that are opposite to current one.
    switch(currentDir){
        case LEFT:
            if (dir==SnakeDirection.RIGHT) return;
            break;
        case RIGHT:
            if (dir==SnakeDirection.LEFT) return;
            break;
        case UP:
            if (dir==SnakeDirection.DOWN) return;
            break;
        case DOWN:
            if (dir==SnakeDirection.UP) return;
            break;
    }
    //adds new segment with 0 length,current first segment's location 
    //and given direction
    nodes.addFirst(new Segment(head,dir,0));
}

方法Next()计算蛇的运动。根据运动方向,第一段的位置会改变;如果蛇包含多于一个的段,则第一个段的长度增加给定值(stepSize),而最后一个段的长度减少该值。如果最后一段的长度小于等于0,则删除最后一段(如果长度小于零,则从当前最后一段减去剩余部分)。

public void Next() {
    SnakeDirection headDir = nodes.getFirst().dir;

    switch(headDir){
        case LEFT:
            nodes.getFirst().location.x-=stepSize;
            break;
        case RIGHT:
            nodes.getFirst().location.x+=stepSize;
            break;
        case UP:
            nodes.getFirst().location.y-=stepSize;
            break;
        case DOWN:
            nodes.getFirst().location.y+=stepSize;
            break;
    }

    if (nodes.size()>1){

        nodes.getFirst().length+=stepSize;
        int newLength = nodes.getLast().length-stepSize;

        if (newLength<=0){
            nodes.removeLast();
            nodes.getLast().length-=newLength;
        }
        else{
            nodes.getLast().length=newLength;
        }

    }
}

当我开始对其进行测试时,我发现由于某些奇怪的原因,其他段的位置会随第一个段的位置而改变,此时它们必须保持在原位。看起来像这样:

enter image description here

其他一切似乎都正常。我的代码有什么问题?

2 个答案:

答案 0 :(得分:0)

没有MCVE不可能知道问题出在哪里,但是设计似乎过于复杂。代替使用线段,而使用点。

假设您的观点是

class Point {
    int x, y;
    // getters/setters if you want
}

然后用点和方向列表表示蛇:

class Snake {
    List<Point> body = new LinkedList<>();
    Point head; // easier to separate the head, but you can do with including it in the list
    Direction dir;
}

您可以向其中添加next()方法以计算蛇的表示形式:

void next() {
    int temp1x = head.x;
    int temp1y = head.y;
    switch(dir) {
        case LEFT:
            head.x -= stepSize;
            break;
        //...
    }
    int temp2x, temp2y;
    for (Point point : points) {
        temp2x = point.x;
        temp2y = point.y;
        point.x = temp1x;
        point.y = temp1y;
        temp1x = temp2x;
        temp1y = temp2y;
    }
}

我将留给您简化实施(如果扩展Point类以允许它,则可以使用int而不是单独的x和y Point

注释:

  • LinkedList确实是列表实现的不错选择。
  • 方法名称以小写字母(next而不是Next开头。

答案 1 :(得分:0)

创建新的细分时,您将传递第一个细分的位置对象,而不是该位置的COPY。因此,您所有的细分对象都共享非常相同的位置对象。如果您在新段中对其进行修改,则由于它是同一对象,因此也会在所有其他段中对其进行修改。 (当您传递对象时,您将传递对象的引用,而不是对象的值。) 因此,代替此行:

Point head = nodes.getFirst().location;

使用此:

Point head = new Point(nodes.getFirst().location);