자바 쓰레드 리스트 관련 질문 부탁드립니다.
조회수 952회
지금 awt를 이용해서 공 5개를 튕긴후에 공끼리 서로 충돌할 때 마다, 두개로 쪼개져서 튕기고, 그러다가 크기가 1픽셀 이하 일때 사라지는 프로그램 코딩중인데... 이 시간까지 해도 해결이 되지가 않네요 ㅠㅠ import java.awt.*;
import java.awt.event.*;
import java.math.*;
import java.util.ArrayList;
public class BounceThread extends Frame implements ActionListener {
private Canvas canvas;
ArrayList<Ball> threadList = new ArrayList<Ball>();
public BounceThread(String title) {
super(title);
canvas = new Canvas();
add("Center", canvas);
Panel p = new Panel();
Button s = new Button("Start");
Button c = new Button("Close");
p.add(s); p.add(c);
s.addActionListener(this);
c.addActionListener(this);
add("South", p); }
public void actionPerformed(ActionEvent evt) {
if (evt.getActionCommand() == "Start") {
for(int i=0;i<5;i++) {
threadList.add(new Ball(canvas,200,150,20,i*(Math.PI/5)));
//threadList.add(k);
threadList.get(i).start();
}
}
else if (evt.getActionCommand() == "Close")
System.exit(0); }
public static void main(String[] args) {
// TODO Auto-generated method stub
Frame f = new BounceThread("Bounce Thread");
f.setSize(400, 300);
WindowDestroyer listener = new WindowDestroyer();
f.addWindowListener(listener);
f.setVisible(true);
}
class Ball extends Thread{
private Canvas box;
int check;
boolean runable=true;
private int XSIZE;
private int YSIZE;
private double dx = 2;
private double dy;
double radian;
private int x ;
private int y ;
//Graphics g;
public Ball(Canvas c,int x, int y, int X, double n) {
box = canvas;
this.x= x;
this.y= y;
this.XSIZE= X;
this.YSIZE= X;
//this.check=m;
this.radian=n;
this.dy = dx*Math.tan(n);
if(n>=Math.PI/2 && n<3*Math.PI/2){
this.dx = -this.dx;
}
}
public void draw() {
Graphics g = box.getGraphics();
g.fillOval(x, y, XSIZE, YSIZE);
g.dispose();
}
public void move() {
Graphics g = box.getGraphics();
g = box.getGraphics();
g.setColor(Color.white);
g.fillOval(x, y, XSIZE, YSIZE);
x += dx; y += dy;
Dimension d = box.getSize();
if (x < 0) { x = 0; dx = -dx; }
if (x + XSIZE >= d.width) { x = d.width - XSIZE; dx = -dx;}
if (y < 0) { y = 0; dy = -dy; }
if (y + YSIZE >= d.height) {y = d.height - YSIZE; dy = -dy; }
for(int i=0;i<threadList.size();i++) {
Ball x=threadList.get(i);
if(this.collide(x))
{
if(i!=threadList.indexOf(this)) {
System.out.println(threadList.indexOf(this)+" "+"size="+threadList.size()+" "+"i="+i);
this.split(this,x);
}
}
}
g.setColor(Color.black);
g.fillOval(x, y, XSIZE, XSIZE);
g.dispose(); }
public boolean collide(Ball ball){
int distanceX = this.x - ball.x;
int distanceY = this.y - ball.y;
double distance = Math.sqrt((distanceX * distanceX) + (distanceY * distanceY));
if(distance <= (this.XSIZE + ball.XSIZE)/2){
double distanceXPrime = (this.x + this.dx) - (ball.x + ball.dx);
double distanceYPrime = (this.y + this.dy) - (ball.y + ball.dy);
double distancePrime = Math.sqrt(distanceXPrime * distanceXPrime + distanceYPrime * distanceYPrime);
if(distance > distancePrime){
return true;
}
}
return false;
}
//@SuppressWarnings("deprecation")
public void splitTwo(Ball ball, double rad){
double subtractedRadOfBall = rad - Math.PI/4;
double addedRadOfBall = rad + Math.PI/4;
//반지름이 1보다 크면 기존 원은 사라지고 작은원 둘로 나뉜다.
if(ball.XSIZE/2>1){
//ball.runable=false;
Ball new1 = new Ball(box,ball.x,ball.y,ball.XSIZE/2, subtractedRadOfBall);
//balist[check].start();
Ball new2 = new Ball(box,ball.x,ball.y,ball.XSIZE/2, addedRadOfBall);
//balist[l].start();
ball.interrupt();
threadList.remove(threadList.get(threadList.indexOf(this)));
//System.out.println(threadList.indexOf(ball)+"what "+"size="+threadList.size());
threadList.add(new1);
threadList.add(new2);
new1.start();
new2.start();
}
//반지름이 1보다 작으면 사라진다.
else{
ball.interrupt();
threadList.remove(threadList.get(threadList.indexOf(this)));
//ball.runable = false;
}
}
public void split(Ball ballOne, Ball ballTwo){
//ballOne 과 ballTwo의 충돌 이후 진행 방향을 벡터로 계산하였다.
double newRadOfBallOne = (ballOne.XSIZE/2*Math.sin(ballOne.radian)-ballTwo.y+ballOne.y)/(ballOne.XSIZE/2*Math.cos(ballOne.radian)-ballTwo.x+ballOne.x);
double newRadOfBallTwo = (ballTwo.XSIZE/2*Math.sin(ballTwo.radian)-ballOne.y+ballTwo.y)/(ballTwo.XSIZE/2*Math.cos(ballTwo.radian)-ballOne.x+ballTwo.x);
splitTwo(ballOne, newRadOfBallOne);
//System.out.println(threadList.indexOf(ballOne)+"what "+"size="+threadList.size());
splitTwo(ballTwo, newRadOfBallTwo);
}
public void run() {
draw();
while(!Thread.currentThread().isInterrupted()) {
this.move();
try { Thread.sleep(20); }
catch(InterruptedException e) {}
}
}
}
}
public class WindowDestroyer extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
이런 코드인데 Exception in thread "Thread-35" java.lang.ArrayIndexOutOfBoundsException: -1 at java.util.ArrayList.elementData(Unknown Source) at java.util.ArrayList.get(Unknown Source) at BounceThread$Ball.splitTwo(BounceThread.java:131) at BounceThread$Ball.split(BounceThread.java:156) at BounceThread$Ball.move(BounceThread.java:95) at BounceThread$Ball.run(BounceThread.java:162)
이런식으로 자꾸 인덱스 범위를 넘었다는 에러가 뜨는데 도대체 이유를 모르겠습니다.. 고수님들 부탁드립니다 ㅠㅠ
-
(•́ ✖ •̀)
알 수 없는 사용자
1 답변
-
소스를 정확하게 파악하진 못했지만 일단
splitTwo()
함수 안에서if (){ threadList.remove(threadList.get(threadList.indexOf(this))); } else { threadList.remove(threadList.get(threadList.indexOf(this))); }
이렇게 remove 하려는 코드가 두개 있는데요. indexOf함수는 찾으려는 요소가 없으면 -1을 반환합니다. -1이 리턴되었는데 remove하려고 하니
ArrayIndexOutOfBoundsException
이 발생하는것입니다. 빠르게 에러를 막으려면 indexOf리턴값이 -1이거나 threadList.size()보다 더 크면 remove하지 않도록 조건을 넣으면 에러는 발생하지 않을것입니다.자바코드 참고
/** * Returns the index of the first occurrence of the specified element * in this list, or -1 if this list does not contain the element. * More formally, returns the lowest index <tt>i</tt> such that * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, * or -1 if there is no such index. */ public int indexOf(Object o) { if (o == null) { for (int i = 0; i < size; i++) if (elementData[i]==null) return i; } else { for (int i = 0; i < size; i++) if (o.equals(elementData[i])) return i; } return -1; }
-
(•́ ✖ •̀)
알 수 없는 사용자
-
댓글 입력