2

嗨,我正在开发一个蛇游戏。创建我正在使用的蛇ArrayList。移动蛇时出现以下错误:“java.lang.IndexOutOfBoundsException:索引:3,大小:3”。下面是我的程序。在Snake.update()方法上我有问题。

游戏.java:

 import javax.swing.JFrame;

 @SuppressWarnings("serial")
   public class Game extends JFrame {
  public Game(){
    add(new GamePanel());
    setTitle("Game Test3");
    setVisible(true);
    setAlwaysOnTop(true);
    setLocationRelativeTo(null);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    pack();
  }

  public static void main(String[] args) {
    new Game();
  }
}  

游戏面板.java:

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics2D;
    import java.awt.Image;
    import java.awt.RenderingHints;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;

    import javax.swing.JPanel;

    @SuppressWarnings("serial")
    public class GamePanel extends JPanel implements Runnable, KeyListener {
public static int width = 300;
public static int height = 400;
private Thread thread;
private Image image;
private Graphics2D g;

private Food food;
private Snake snake;

public GamePanel() {
    setPreferredSize(new Dimension(width, height));
    setFocusable(true);
}

public void addNotify() {
    super.addNotify();
    if (thread == null) {
        thread = new Thread(this);
        thread.start();
    }
    addKeyListener(this);
}

public void run() {
    image = createImage(width, height);
    g = (Graphics2D) image.getGraphics();
    RenderingHints reneringHints = new RenderingHints(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
    g.setRenderingHints(reneringHints);

    food = new Food();
    snake = new Snake();
    while (true) {
        gameRender();
        gameUpdate();
        gameDraw();
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

private void gameDraw() {
    Graphics2D g2 = (Graphics2D) getGraphics();
    g2.drawImage(image, 0, 0, this);
    g2.dispose();
}

private void gameRender() {
    g.setColor(Color.black);
    g.fillRect(0, 0, width, height);

    // food drawing
    food.draw(g);
    // snake drawing
    snake.draw(g);
}

private void gameUpdate() {
    food.update();
    snake.update();
}

public void keyPressed(KeyEvent e) {
    int key = e.getKeyCode();
    if (key == KeyEvent.VK_LEFT) {
          snake.setLeft(true);
    }
    if (key == KeyEvent.VK_RIGHT) {
        snake.setRight(true);
    }
    if (key == KeyEvent.VK_UP) {
        snake.setUp(true);
    }
    if (key == KeyEvent.VK_DOWN) {
        snake.setDown(true);
    }
}

public void keyReleased(KeyEvent e) {
    int key = e.getKeyCode();
    if (key == KeyEvent.VK_LEFT) {
          snake.setLeft(false);
    }
    if (key == KeyEvent.VK_RIGHT) {
        snake.setRight(false);
    }
    if (key == KeyEvent.VK_UP) {
        snake.setUp(false);
    }
    if (key == KeyEvent.VK_DOWN) {
        snake.setDown(false);
    }
}

public void keyTyped(KeyEvent e) {
}

  }

//蛇身

  import java.awt.Color;
  import java.awt.Graphics2D;
  import java.awt.Rectangle;
  import java.util.ArrayList;

 public class Snake {
private int x;
private int y;
private int r;

int body;
Rectangle rectangle;
ArrayList<Rectangle> rc = new ArrayList<Rectangle>();
private boolean left;
private boolean right;
private boolean up;
private boolean down;

public Snake() {
    x = 150;
    y = 150;
    r = 4;
    body = 3;
    for (int i = 0; i < body; i++) {
        rc.add(new Rectangle(x - i * r * 3, y, r * 3, r * 3));
    }
}

public void draw(Graphics2D g) {

    for (int i = 0; i < body; i++) {
        if (i == 0) {
            g.setColor(Color.red);
        } else {
            g.setColor(Color.green);
        }
        g.fillOval(rc.get(i).x, rc.get(i).y, rc.get(i).width,
                rc.get(i).height);
    }
}

public void update() {
    for (int i = body; i > 0; i--) {
        rc.set(i, rc.get(i - 1));
    }
    if (left) {
        rc.get(0).x -= 1;
        System.out.println("vbnv");
    }
    if (right) {
        rc.get(0).x += 1;
    }
    if (up) {
        rc.get(0).y -= 1;
    }
    if (down) {
        rc.get(0).y += 1;
    }
}

public void setLeft(boolean b) {
    left = b;
}

public void setRight(boolean b) {
    right = b;
}

public void setUp(boolean b) {
    up = b;
}

public void setDown(boolean b) {
    down = b;
}

   }
4

3 回答 3

3

无需阅读代码,我就可以知道您正在尝试获取不存在的元素。阅读异常消息,它告诉您ArrayList由三个元素组成(这意味着最后一个元素的索引为 2),而您尝试获取索引为 3 的元素。

更新:是的,问题在这里:

for (int i = body; i > 0; i--) {
    rc.set(i, rc.get(i - 1));
}

body等于 3,并且rc在构造函数调用的大小为 3 之后。set方法用指定的索引替换已经存在的元素(参见文档),但索引为 3 的元素不存在。这就是异常的原因。

于 2013-10-09T07:09:50.210 回答
1

你的问题在这个循环中:

for (int i = body; i > 0; i--) {
    rc.set(i, rc.get(i - 1));
}

在围绕此循环的第一次迭代中,您将调用:

rc.set(3, <someValue>);

3 不是长度为 3 的列表中的有效索引。最大的有效索引是 2。

于 2013-10-09T07:10:36.147 回答
1
for (int i = body; i > 0; i--)

在 thisfor中, i 被分配了 body 的值(即 3),看起来你ArrayList rc只有 3 个元素。因此,当您尝试使用 访问索引 3 时rc.set(3, something),它会给出IndexOutOfBoundsException.

永远记住,无论是Arrays还是ArrayList,它们中可访问的最大可能索引始终是array.length - 1ArrayList.size() - 1

于 2013-10-09T07:10:57.413 回答