尝试重写贪吃蛇游戏 - 蛇会吃到自己

3

我遇到了一个(对我来说至少是)非常奇怪的情况。
我正在尝试重写贪吃蛇,移动操作进行得很顺利,但是蛇在吃自己,虽然我删除了1个部分并添加了1个部分(x + 1 - 1 = x?),但蛇消失了,而Arraylist保持相同的大小(打印出来的)。

计算蛇位置的函数(我认为是引起问题的):

private void move() {
    System.out.println(position.size());
    Point toAdd = position.get(position.size() - 1);
    position.remove(0);
    if(dir == 1)
        toAdd.y -= 5;
    else if(dir == 2) 
        toAdd.x -= 5;
    else if(dir == 3)
        toAdd.x += 5;
    else if(dir == 4)
        toAdd.y += 5;

    if(toAdd.x < 0) toAdd.x = 150;
    else if(toAdd.x > 150) toAdd.x = 0;

    if(toAdd.y < 0) toAdd.y = 150;
    else if(toAdd.y > 150) toAdd.y = 0;
    position.add(toAdd);
}

但是,为了让它成为一个简短、自包含、正确的示例:
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.*;
import java.util.ArrayList;

class Snake extends JPanel implements Runnable {
    int x,y;
    boolean horizontal;
    ArrayList<Point> position = new ArrayList<Point>();
    byte dir = 3;

    public Snake(JFrame parent) {
        for(int i = 0; i < 5; i++)
            position.add(new Point(i*5 + 10, 10));

        parent.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                byte change = dir;
                switch (e.getKeyCode()) {
                    case KeyEvent.VK_DOWN:
                        change = 4;
                        break;
                    case KeyEvent.VK_UP:
                        change = 1;
                        break;
                    case KeyEvent.VK_LEFT:
                        change = 2;
                        break;
                    case KeyEvent.VK_RIGHT:
                        change = 3;
                        break;
                }

                changeDirection(change);
            }
        });
        System.out.println("starting thread");
        new Thread(this).start();
    }

    private void changeDirection(byte change) {
        if(change != dir && (change - 2 != dir || change + 2 != dir)) {
            dir = change;
        }
    }

    public void run() {
        for(int i = 0; i != -1; i++){
            try {
                move();
                this.repaint();
                Thread.sleep(1000);
            }
            catch (InterruptedException e) {
                System.out.println("INTERRUPTED");
            }
        }
    }

    private void move() {
        System.out.println(position.size());
        Point toAdd = position.get(position.size() - 1);
        position.remove(0);
        if(dir == 1)
            toAdd.y -= 5;
        else if(dir == 2) 
            toAdd.x -= 5;
        else if(dir == 3)
            toAdd.x += 5;
        else if(dir == 4)
            toAdd.y += 5;

        if(toAdd.x < 0) toAdd.x = 150;
        else if(toAdd.x > 150) toAdd.x = 0;

        if(toAdd.y < 0) toAdd.y = 150;
        else if(toAdd.y > 150) toAdd.y = 0;
        position.add(toAdd);
    }

    public void paintComponent(Graphics g) {
        g.clearRect(0,0,150,150);
        for(Point p : position)
            g.drawRect(p.x, p.y, 5, 5);
    }

    public static void main(String[] args) {
        Snake snake;
        JFrame f = new JFrame("Snake");
        f.setSize(150, 150);
        f.add((snake = new Snake(f)));
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setResizable(false);
        f.setVisible(true);
    }
}

移动是我尝试实现的第一件事,我还没有涉及到碰撞检测/食物,这不是问题所在。

我的问题是:

为什么蛇会缩小而ArrayList却不会?如何修复它,即停止蛇除了前面的部分外消失?


3
请问 @downvoter 可以解释一下吗? - 11684
2
有人能解释一下为什么这不是一个真正的问题吗?我认为最后一段非常明确,它并不难找到,也不会过于宽泛,可能只是“过于局限”,但那样的话,它将成为这里的许多问题之一,因为在SO上有更加局限的问题。 - 11684
1
我不会说这是修辞问题,也不会说它是不完整的 - 我甚至提供了一个 SSCCE - 当然,在当前形式下,只要有人愿意查看我的代码并找到无疑的错误,就可以合理地回答它。 - 11684
1个回答

6

好的。这很简单!

你正在更改已经存在于列表 position 中的点,并在最后将 相同的 点添加到该列表中。你最终会得到越来越多相同(按引用计)位置的元素。

你应该创建 Point 的新实例并将其添加到列表中。

Point lastPoint = position.get(position.size() - 1);
    Point toAdd = new Point(lastPoint.x, lastPoint.y);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接