java.util.ConcurrentModificationException 与迭代器(字符移动)

标签 java arrays list

我正在编写一个游戏,以便当您按住 D 时角色向右移动,当您按住 S 时角色向左移动。该程序正常工作,但有一个异常(exception)。当我移动角色时(并且角色移动得非常好),java 不断抛出错误“java.util.ConcurrentModificationException”。我做了一些研究并了解到我不能添加到 ArrayList“键”并同时迭代它。话虽如此,我如何编辑代码才能让角色像现在一样无缝移动?据我所知,这是确保角色在按住按键时以相同稳定的速度移动的唯一方法,而不是快速移动、暂停,然后继续移动。

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);
    }
}

}

最佳答案

使用迭代器在这里是错误的模型:您实际上并没有迭代列表,您只是查看是否有元素,然后在有元素时对其进行处理。

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

您可以使用 queue.add(e.getKeyCode()) 添加关键代码,并使用 queue.poll() (或 queue.peek()),如果队列中没有任何内容,则返回 null 值(类似于 itr.hasNext() 为 false)。

关于java.util.ConcurrentModificationException 与迭代器(字符移动),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31465746/

相关文章:

java - 为什么两秒后控制台没有信息输出 --- Rxjava

java - 如果 setLayout 为 null,面板不显示任何内容

java - Java 中对象的实例,奇怪的行为

string - 如何从数字列表中获取字符串?

jQuery:淡入和淡出 li 并从最后 li 重新开始

java - 当数据更新时,VueJS DOM 不更新

c++ - 使用推力根据索引更改某些元素的值

c - 如何知道数组中有多少个模式段?

php - "Notice: Undefined variable"、 "Notice: Undefined index"、 "Warning: Undefined array key"和 "Notice: Undefined offset"使用 PHP

sql - 连接 R 列表中的键值对