java.util.ConcurrentModificationException with iterator(character movement)

时间:2015-07-16 22:38:37

标签: java arrays list

我对游戏进行编码,这样当你按住D时,角色向右移动,当你按住S时,角色向左移动。程序正常运行,但有一个例外。当我移动角色(并且角色移动得很好)时,java会不断抛出错误" java.util.ConcurrentModificationException"。我做了一些研究,并了解到我无法添加到ArrayList" keys"并在同一时间迭代它。话虽如此,我如何编辑代码仍然让角色像现在一样无缝移动?这是我所知道的唯一方法,以确保角色在按住键的同时以相同的稳定速度移动,而不是快速移动,暂停,然后继续运动。

package LevelEditor;

import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferStrategy;
import java.util.ArrayList;
import java.util.Iterator;


public class LevelEditor extends Canvas implements KeyListener, Runnable, MouseListener, MouseMotionListener{

private Object[][] grid = new Object[50][50];

private Graphics bufferGraphics = null; //The graphics for the back buffer
private BufferStrategy bufferStrategy = null;

private Thread thread;

private boolean running;

private int selectedBlock = 0;

private int mouseX;
private int mouseY;

private int playerX;
private int playerY;

private ArrayList<Integer> keys = new ArrayList<Integer>();
Iterator itr;

Player player1;

public LevelEditor(Dimension size){
    //Constructor
    this.setPreferredSize(size);
    this.addKeyListener(this);
    this.thread = new Thread(this);
    this.addMouseListener(this);
    this.addMouseMotionListener(this);
    running = true;
    mouseX = 0;
    mouseY = 0;
    playerX = 0;
    playerY = 0;
    itr = keys.iterator();


}



public void paint(Graphics g){
    if (bufferStrategy == null){
        this.createBufferStrategy(2);
        bufferStrategy = this.getBufferStrategy();
        bufferGraphics = bufferStrategy.getDrawGraphics();
        player1 = new Player(playerX, playerY);
        this.thread.start();
    }
}

@Override
public void run() {
    //This is what runs when level editor is running
    while (running){
        //Program's logic
        DoLogic();
        Draw();
        DrawBackbufferToScreen();

        Thread.currentThread();
        try{
            Thread.sleep(10);
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }
}


public void DoLogic(){

}

public void Draw(){
    //clear secondary screen
    bufferGraphics = bufferStrategy.getDrawGraphics();
    try{
        bufferGraphics.clearRect(0, 0, this.getSize().width, this.getSize().height);

        //this is where everything will be drawn to back buffer
        for (int x = 0; x < grid.length; x++){
            for(int y = 0; y < grid[x].length; y++){
                Object o = grid[x][y];
                if (o instanceof Block){
                    Block blocktoDraw = (Block)o;
                    blocktoDraw.draw(bufferGraphics);
                }
            }
        }

        Block.getBlock(selectedBlock, mouseX, mouseY).draw(bufferGraphics);
        player1.draw(bufferGraphics);

        for (Integer x  : keys){
            if(x == 68 && itr.hasNext()){
                playerX += 5;
                player1.updatePlayer(playerX, playerY);
                player1.draw(bufferGraphics);
                itr.next();
                itr.remove();


            }
            if (x == 65 && itr.hasNext()){
                playerX -= 5;
                player1.updatePlayer(playerX, playerY);
                player1.draw(bufferGraphics);
                itr.next();
                itr.remove();
            }
        }




    }
    catch(Exception e){
        e.printStackTrace();
    }
    finally{
        bufferGraphics.dispose();
    }
}


public void DrawBackbufferToScreen(){
    bufferStrategy.show();
    Toolkit.getDefaultToolkit().sync();
}


@Override
public void mouseReleased(MouseEvent e) {
    int mouseX = e.getX();
    int mouseY = e.getY();

    mouseX = (mouseX / 25);
    mouseY = (mouseY / 25);

    if (e.getModifiers() == 16){
        grid[mouseX][mouseY] = Block.getBlock(selectedBlock, mouseX, mouseY);
    }
    else if (e.getModifiers() == 4){
        grid[mouseX][mouseY] = Block.getBlock(100, mouseX, mouseY);
    }


}

@Override
public void keyTyped(KeyEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void keyReleased(KeyEvent e) {
    keys.clear();

}

@Override
public void keyPressed(KeyEvent e) {

    keys.add(e.getKeyCode());

}


public void mouseMoved(MouseEvent e) {
    this.mouseX = e.getX() / 25;
    this.mouseY = e.getY() / 25;

}



@Override
public void mouseClicked(MouseEvent e) {
    // TODO Auto-generated method stub

}



@Override
public void mousePressed(MouseEvent e) {
    // TODO Auto-generated method stub

}



@Override
public void mouseEntered(MouseEvent e) {
    // TODO Auto-generated method stub

}



@Override
public void mouseExited(MouseEvent e) {
    // TODO Auto-generated method stub

}



@Override
public void mouseDragged(MouseEvent e) {
    int mouseX = e.getX();
    int mouseY = e.getY();

    mouseX = (mouseX / 25);
    mouseY = (mouseY / 25);


    if(e.MOUSE_DRAGGED == 506 && e.getModifiers() == 16){
        grid[mouseX][mouseY] = Block.getBlock(selectedBlock, mouseX, mouseY);
    }
    else if (e.MOUSE_DRAGGED == 506 && e.getModifiers() == 4){
        grid[mouseX][mouseY] = Block.getBlock(100, mouseX, mouseY);
    }
}

}

1 个答案:

答案 0 :(得分:1)

在这里使用Iterator是错误的模型:你实际上并没有遍历列表,你只是想看看你是否有一个元素,然后如果你有东西就处理它。

更合适的是使用队列 - 特别是某种并发队列,例如java.util.concurrent.BlockingQueue,因为您正在修改它并在不同的线程中读取它。

您可以使用queue.add(e.getKeyCode())将密钥代码添加到其中,然后使用queue.poll()(或queue.peek())将其删除,如果队列中没有任何内容,则会返回空值(类似于itr.hasNext()是假的。