Avatar billede bootie Nybegynder
07. januar 2002 - 07:33 Der er 54 kommentarer og
1 løsning

ArrayIndexOutOfBoundsException

Een af mine vectorer laver en ArrayIndexOutOfBoundsException...
Hvordan pokker kommer jeg lige uden om den?

    public void detectCollision()
    {
        for ( int i = 0; i < bullets.size(); i++)
        {
            for ( int k = 0; k < enemies.size(); k++)
            {
                Koordinater bullet = (Koordinater)bullets.get(i);
                xPosB = bullet.getX();
                yPosB = bullet.getY();
               
                Enemy enemy = (Enemy)enemies.get(k);
                xPosE = enemy.getX();
                yPosE = enemy.getY();
                starClass = enemy.getStarClass();
               
                if ((yPosB < yPosE + starClass + 2) && (yPosB > yPosE - 6))
                {   
                    if ((xPosB < xPosE + starClass + 2) && (xPosB > xPosE - 6))
                    {
                        enemies.remove(enemy);
                        counter++;       
                    }   
                }
            }
        }                   
    }
   
Avatar billede bootie Nybegynder
07. januar 2002 - 07:34 #1
Hele fejlen beskrevet

java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 45     at java.util.Vector.get(Vector.java:699)     at CollisionDetector.detectCollision(CollisionDetector.java:44)     at CollisionDetector.run(CollisionDetector.java:34)     at java.lang.Thread.run(Thread.java:484)
Avatar billede disky Nybegynder
07. januar 2002 - 08:40 #2
hvad står der i linie 45 ?
Avatar billede bootie Nybegynder
07. januar 2002 - 09:05 #3
    xPosB = bullet.getX();
Men det er ikke altid der står range: 45
Avatar billede bootie Nybegynder
07. januar 2002 - 09:08 #4
Nu så den FX sådan nu:
java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 404     at java.util.Vector.get(Vector.java:699)     at CollisionDetector.detectCollision(CollisionDetector.java:48)     at CollisionDetector.run(CollisionDetector.java:34)     at java.lang.Thread.run(Thread.java:484)
Avatar billede carstenknudsen Nybegynder
07. januar 2002 - 09:52 #5
Jeg tror dit problem er at du fjerner en fjende, men så
kører din fjende løkke videre uændret. Efter at have fjernet
en fjende skal du bruge k--; så tror jeg det funker.
Avatar billede erikjacobsen Ekspert
07. januar 2002 - 10:02 #6
Sker der noget med bullets i en anden tråd, så antallet ændrer sig mens du
checker?

Du skal også lige huske k-- som anført, så du ikke springer nogen over. Men det
kan ikke gíve indexfejl at glemme.

Og så kan du gøre det lidt mere effektivt - og overskueligt:

    public void detectCollision()
    {
      for ( int i = 0; i < bullets.size(); i++)
      {
        Koordinater bullet = (Koordinater)bullets.get(i);
        xPosB = bullet.getX();
        yPosB = bullet.getY();
        for ( int k = 0; k < enemies.size(); k++)
        {
                                 
            Enemy enemy = (Enemy)enemies.get(k);
            xPosE = enemy.getX();
            yPosE = enemy.getY();
            starClass = enemy.getStarClass();
                                 
            if ((yPosB < yPosE + starClass + 2) && (yPosB > yPosE - 6))
            {   
                if ((xPosB < xPosE + starClass + 2) && (xPosB > xPosE - 6))
                {
                  enemies.remove(enemy);
                  k--;
                  counter++;       
                }   
            }
          }
      }                   
  }
                     
Avatar billede carstenknudsen Nybegynder
07. januar 2002 - 10:11 #7
Kunne du have at den samme enemy er tilføjet flere gange,
i så fald er enemies.remove(enemy) ikke god, brug i stedet
enemies.remove(k).
Avatar billede bootie Nybegynder
07. januar 2002 - 10:16 #8
Jeg har jo fat i this.enemy så det er lige meget.

Jeg satte tråden til at køre lidt langsommere istedet...
Det syntes at have løst problemmet.. for now at least
Avatar billede bootie Nybegynder
07. januar 2002 - 10:17 #9
Her er hele klassen:

import java.util.*;

public class CollisionDetector implements Runnable
{
    public CollisionDetector(Vector bullets, Vector enemies)
    {
        this.bullets = bullets;
        this.enemies = enemies;
    }
   
    public void start()
    {
        if (collisionDetector == null)
        {
            collisionDetector = new Thread(this);
            collisionDetector.start();
        }
    }
   
    public void run()
    {
        while (true)
        { 
            try
            {
                collisionDetector.sleep(20);
            }
            catch(Exception e)
            {
            }
           
            detectCollision();
        } 
    }
   
    public synchronized void detectCollision()
    {
        for ( int i = 0; i < bullets.size(); i++)
        {
            for ( int k = 0; k < enemies.size(); k++)
            {
                Koordinater bullet = (Koordinater)bullets.get(i);
                xPosB = bullet.getX();
                yPosB = bullet.getY();
               
                Enemy enemy = (Enemy)enemies.get(k);
                xPosE = enemy.getX();
                yPosE = enemy.getY();
                starClass = enemy.getStarClass();
               
                if ((yPosB < yPosE + starClass + 2) && (yPosB > yPosE - 6))
                {   
                    if ((xPosB < xPosE + starClass + 2) && (xPosB > xPosE - 6))
                    {
                        enemies.remove(enemy);
                        counter++;       
                    }   
                }
            }
        }                   
    }
   
    private int xPosB;
    private int yPosB;
    private int xPosE;
    private int yPosE;
    private int starClass;
    private Vector bullets;
    private Vector enemies;
    private Thread collisionDetector;
    public int counter;
}
Avatar billede erikjacobsen Ekspert
07. januar 2002 - 10:24 #10
Du tror ikke det kan have noget med ordet \"synchronized\" at gøre ?? :)
Avatar billede bootie Nybegynder
07. januar 2002 - 10:25 #11
Nej, den er først kommet på EFTER fejlen begyndte at komme. Men hjulpet har den heller ikke..
Avatar billede disky Nybegynder
07. januar 2002 - 10:26 #12
Prøv at bruge en iterator istedet for for løkken.

En iterator tager hensyn til ændringer i Vector.

Avatar billede erikjacobsen Ekspert
07. januar 2002 - 10:26 #13
Men, nu læser jeg hvad du skriver, din \"synchronized\" løser jo ikke dit
problem, hvis der sker ændringer i dine Vector-er andet sted, mens du
checker.
Avatar billede bootie Nybegynder
07. januar 2002 - 10:29 #14
Ja, det gør der vel egentlig...
Tag en kigger på
www.be-reminded.dk/myshooter
Der kan i se hele appletten.
Jeg tager jo egentlig nogle kugler og enemies ud når de rammer siden..
Det skulle jeg bare putter i den samme metode og lukker eller noget... Så kan det være den er der
Avatar billede carstenknudsen Nybegynder
07. januar 2002 - 10:33 #15
Vector er allerede synkroniseret.
Avatar billede greybeard Nybegynder
07. januar 2002 - 10:51 #16
Hvis man går ud fra at en bullet kun kan ramme én enemy, så skulle et break statement kunne løse dit problem, samtidig med at din kode bliver en anelse hurtigere.

enemies.remove(enemy);
counter++;
break;



Avatar billede bootie Nybegynder
07. januar 2002 - 21:24 #17
Kan man breakke ud af en for løkke?
Avatar billede greybeard Nybegynder
07. januar 2002 - 21:30 #18
Ja
Avatar billede greybeard Nybegynder
07. januar 2002 - 21:32 #19
Du kan også lave break til en label, hvis du f.eks. vil ud af to løkker på en gang.
Avatar billede bootie Nybegynder
07. januar 2002 - 21:37 #20
Jeg har prøved at omstrukturere klassen lidt...
Men så blev det meget værre...

    public synchronized void detectCollision()
    {

        for ( int i = 0; i < bullets.size(); i++)
        {
            for ( int k = 0; k < enemies.size(); k++)
            {
           
                counterI = i;
                counterK = k;
                removeBullet = false;
                removeEnemy = false;
       
                Koordinater bullet = (Koordinater)bullets.get(i);
                xPosB = bullet.getX();
                yPosB = bullet.getY();
               
                Enemy enemy = (Enemy)enemies.get(k);
                xPosE = enemy.getX();
                yPosE = enemy.getY();
                starClass = enemy.getStarClass();
               
                rectBullet = new Rectangle(xPosB, yPosB, 4, 4);
                rectEnemy = new Rectangle(xPosE, yPosE, starClass + 2, starClass + 2);
               
                if (rectEnemy.intersects(rectBullet))
                {   
                    removeBullet = true;
                    removeEnemy = true;
                }

               
                if (yPosE > appletHeight)
                {           
                    removeEnemy = true;
                    targetsMissed++;               
                }
               
                if ((xPosB >= appletWidth) || (xPosB <= 0) || yPosB <= 0)
                    removeBullet = true;
               
                if (removeBullet)
                {
                    bullets.remove(i);
                   
                   
                }
                   
                if (removeEnemy)
                {
                    enemies.remove(k);
                   
                }
                       
               
                //noget intersect istedet...
               
               
            }
        }                   
    }

Men det ved jeg ikke om der er noget der kan finde rundt i
Avatar billede bootie Nybegynder
07. januar 2002 - 21:45 #21
Hvordan breaker jeg lige til en lable sagde du?
Avatar billede greybeard Nybegynder
07. januar 2002 - 21:59 #22
Her er din yderste løkke labelled slut.
Derfor afbryder break slut den yderste og dermed også den inderste løkke;
Hvis du fjerner slut, vil den yderste løøke køre ti gange, som den skal,
mens den inderste aldrig når mere end en tur.

public class BreakTest {
   
    public static void main( String[] argv ){
        slut:
        for ( int i = 0 ; i < 10 ; i++ ) {
            for ( int j = 0 ; j < 10 ; j++ ){
                System.out.println( \"\"+ i +\", \" + j );
                break slut;
            }
        }
    }
}
Avatar billede disky Nybegynder
08. januar 2002 - 08:16 #23
EEEWWW

Brug af labels er godt nok noget afskyeligt noget at gøre.

Lav en boolean istedet for som du checker på.

Eller i ovenstående eksempel brug en \'return\'
Avatar billede greybeard Nybegynder
08. januar 2002 - 08:24 #24
disky >> kan du give mig en fornuftig grund til at ovenstående er afskyeligt, eller er bare religionskrig?
Avatar billede bootie Nybegynder
08. januar 2002 - 08:28 #25
Jeg laver mig sgu bare en ny collision klasse eller noget.
Og så laver jeg 2 arrays istedet hvor der kun kan være så og så mange elementer i.
Så kan det da være jeg slipper for den lorte arrayIndexOutOfBoundsErrorException..
Avatar billede disky Nybegynder
08. januar 2002 - 08:29 #26
Labels er noget man brugte i Basic.

Jeg kan ikke mindes jeg på noget tidspunkt i prof. software source kode har set labels anvendt.


Problemmet med breaks er at man pludseligt ikke længere har et logisk flow i programmerne, det er jo en form for GOTO som man ALDRIG bruger.

Prøv at lav et \'Nassi schneidermann diagram\' over dit eksempel.
Avatar billede bootie Nybegynder
08. januar 2002 - 08:31 #27
\'Nassi schneidermann diagram\'
Wut is that?
Avatar billede greybeard Nybegynder
08. januar 2002 - 08:35 #28
Du misser noget her. Der er ikke spor af goto i det eksempel. Der er nogle nestede loops, hvoraf det yderste er navngivet. Når break kaldes med en label, fortæller man bare hvilken kontrolstruktur, der skal udføres break på.
Hvis det havde været noget der lignede goto, ville løkken jo bare have startet forfra.
Avatar billede greybeard Nybegynder
08. januar 2002 - 08:41 #29
Disky >> Når du siger at du aldrig har set labels brugt i prof. software, betyder det så at du aldrig har det et stykke assembler kode :-))
Avatar billede disky Nybegynder
09. januar 2002 - 09:52 #30
jeg skrev en form for Goto ikke at det var en Goto

Jeg startede faktisk med Assembler udvikling, men her snakker vi højniveau sprog. :-)
Avatar billede erikjacobsen Ekspert
09. januar 2002 - 10:17 #31
Hvis jeg må tillade mig at støtte disky, vil jeg da lige forklare hvorfor
jeg også mener goto, break, og returns, der ikke står til sidst i en
metode generelt set er dumme. Man skal nemlig kunne formulere invarianter
flere steder i sine metoder, dvs. \"små\" logiske udtryk, der fortæller hvad der gælder på
et givet sted i metoden. Det er ikke altid man gider formulere dem direkte,
men har man ikke programmeret med dem i tankerne får man den
spaghettikode, der ofte ses i de kodestumper, der vælter ud af spørgsmålene
på eksperten.dk.

Skal man så bruge goto-lignende tingester må de ikke overskride de steder man
har sine invarianter, for så ryger logikken i metoden, og dermed bliver den sikkert
forkert.

Eksempel:

  public int sum(int a, int b) {
    // Prebetingelse a>0 og b>0
    int a1=a;
    int b1=b;
    while (a1<>0) {
      // Invariant: a+b=a1+b1
      a1--; b1++;
    }
    // Invariant: a1=0 og a+b=a1+b1, dvs. a+b=b1
    // Postbetingelse: b1=a+b
    return b1;
  }

Ja, et dumt lille eksempel, men bare for at illustrere. Jeg har \"bevist\" at
ved at lægge én til og trække én fra tilstrækkeligt mange gange, kan man
addere tal.
 
Avatar billede disky Nybegynder
09. januar 2002 - 10:20 #32
erikjacobsen:

Jeg takker og bukker :)

Forresten hvad er din holdning til \'continue\' ? Den er også en af de grimme ikke ?
Avatar billede greybeard Nybegynder
09. januar 2002 - 11:51 #33
Uenigheden fra min side går mere på firkantede holdninger.
Fordi der kan findes (mange) eksempler på at en given fremgangsmåde kan give probelmer eller uoverskuelighed, er det ikke nødvendigvis det samme som at den fremgangmåde ikke kan være velegnet i andre tilfælde.
Hvad jeg mener er at fordi det gentagne gange har vist sig at give problemer at transportere mursten i en bus, er det vel ikke ensbetydende med at man skal lade være med at bruge den til passagerer.

Efter følgende gøres det samme to gange.
1. gang som disky foreslår, ved at checke en boolean.
2. gang med break label.
Begge dele giver præcis samme resultat og samme programflow, men der er et fuldstændig unødvendigt overhead ved at checke en boolsk værdi i samme gennemløb.

Hvis man så påstår at den metode, der gør arbejdet på den mest besværlige måde, er den bedste, fordi det andet \"gør man bare ikke\", så er og bliver det et religionsspørgsmål, og ikke andet.
Samtidig er I jo fortalere for at man bruger Javas indbyggede metoder, fordi de pr. definition er de bedste. Break to label er også en del af Java. Det hænger ikke rigtig sammen.

public class BreakTest {
   
    public static void main( String[] argv ){
        boolean fundet = false;
        for ( int i = 0 ; i < 10 && !fundet ; i++ ) {
            for ( int j = 0 ; j < 10 && !fundet ; j++ ){
                System.out.println( \"\"+ i +\", \" + j );
                if (i == 2 && j == 5){
                    fundet = true;
                }
            }
        }
                slut:
        for ( int i = 0 ; i < 10 ; i++ ) {
            for ( int j = 0 ; j < 10 ; j++ ){
                System.out.println( \"\"+ i +\", \" + j );
                    if (i == 2 && j == 5){
                        break slut;
                    }
            }
        }
    }
}

Som et kuriosum kan nævnes at i C#, som Anders Hejlsberg er primus motor bag, har man genindført goto:-))
Avatar billede greybeard Nybegynder
09. januar 2002 - 11:53 #34
ups: samme gennemløb >> samtlige gennemløb
Avatar billede disky Nybegynder
09. januar 2002 - 11:57 #35
Det beviser jo bare et C# er noget hø.

Ham Anders har jeg nu ikke meget til overs for, specielt ikke hvis han har sagt goto skal med igen.

der findes ikke så meget som 1 god grund til at bruge goto.


Angående dine to metoder, jeg fortrækker helt klart den øverste, da labels IMHO ikke høre hjemme i høj niveau sprog.

Prøv at lav sådanne et diagram som jeg sagde så ser du hvorfor.
Avatar billede greybeard Nybegynder
09. januar 2002 - 12:00 #36
Beklager, jeg er ateist :-))
Avatar billede disky Nybegynder
09. januar 2002 - 12:02 #37
men du har ret det er smag og behag.
Avatar billede greybeard Nybegynder
09. januar 2002 - 12:02 #38
Iøvrigt ville jeg, hvis jeg skulle lave et sådant diagram formulere betingelsen:
j < 10 && break not called
Avatar billede disky Nybegynder
09. januar 2002 - 12:10 #39
ja og din \'break not called\' er en if sætning. Spm svarer til check på en boolean :-)
Avatar billede greybeard Nybegynder
09. januar 2002 - 12:15 #40
Præcis, det er det jeg har argumenteret for hele tiden:-))
Avatar billede disky Nybegynder
09. januar 2002 - 12:19 #41
Øh hvad ?

Du har argumenteret for at bruge en label. pludselig retter du din betingelse til at indeholde en if for at kunne tegne et diagram (det med det mystiske navn) så bruger du jo heller ikke en label længere, men den metode jeg foreslog.

Forklar venligst
Avatar billede greybeard Nybegynder
09. januar 2002 - 12:22 #42
I og med at diagrammet er pseudokode, og programflowet passer med diagrammet, så gør jeg.
Avatar billede disky Nybegynder
09. januar 2002 - 12:24 #43
man kan ikke lave labels i nassi schneidermann diagrammer.
Avatar billede greybeard Nybegynder
09. januar 2002 - 12:31 #44
Du bliver ved med at hænge dig i labels. Og du bliver ved med at omtale dem som om det var noget i forbindelse med goto.
Prøv at sætte en label et tilfældigt sted i koden, og se om du kan få programflowet til at fortsætte der ved hjælp af break.
Det giver en compileringfejl.
Det eneste du kan med break og label at at afbryde udførelsen af en nestet kontrolstruktur - igen - fuldstændigt equivalent med at checke på en boolean, men uden det ekstra arbejde.
Avatar billede disky Nybegynder
09. januar 2002 - 12:33 #45
det vil jeg nu ikke give dig ret i.

De labels fremmer bestemt heller ikke læsbarheden af koden.

Men begge dele er jo en smagssag så lad os stoppe her :)
Avatar billede greybeard Nybegynder
09. januar 2002 - 12:35 #46
Det er jeg til gengæld helt enig i:-))
Avatar billede disky Nybegynder
09. januar 2002 - 12:36 #47
hehe :)
Avatar billede mortenezentia Nybegynder
09. januar 2002 - 12:48 #48
Til det oprindelige spørgsmål :

forslag til løsning - lav endnu en vector (\"removalvector\") til at holde de fjender som skal fjernes/dø. Istedet for at fjerne dem inde i dit collision-check, så tilføj dem til din removalvector. Efter dit collisions-check fjerner du så de elementer i removalvectoren fra enemies-vectoren
Avatar billede erikjacobsen Ekspert
09. januar 2002 - 13:16 #49
Inden vi stopper helt, så lad mig lige præcisere at jeg godt synes man kan
bruge break, continue \"i det små\", altså mellem mine mere eller mindre
eksplicitte invarianter. Er der en for-løkke på ganske få linier, hvor for og break
står \"tilstrækkelig tæt\" på hinanden, og det ligner en velkendt konstruktion, så
man isoleret set kan se hvad der sker, så ok med mig. Break til en navngiven label,
fordi man skal ud af en løkke et trin længere ude er nok over grænsen til hvad
jeg vil synes om.

Og så er jeg iøvrigt hamrende ligeglad med effektivitet. Programkoden skal
både være korrekt, og kunne ses at være korrekt. Det andet princip kender vi
alt for godt: blå skærm.
Avatar billede disky Nybegynder
09. januar 2002 - 13:18 #50
erik:

Det du tænker på kunne være ok er det f.eks.

while(iter.hasNext())
{
  data=iter.next();
  count++;
  if(count<10) continue;

  //lav et eller andet

}
Avatar billede erikjacobsen Ekspert
09. januar 2002 - 13:50 #51
Jah, disky, i dette tilfælde gør det ikke nogen forskel efter whileløkken, for
det eneste man ved gælder der er !iter.hasNext(). Skulle man standse på
count, bør den være med i betingelsen, så man nemt kan se hvad der gælder
efter løkken. Igen: det er ikke altid man skriver det, men man bør tænke det.
Generelt:

  while (BETINGELSE) {  alt muligt uden break; }
  // Nu gælder med garanti: !BETINGELSE
Avatar billede disky Nybegynder
09. januar 2002 - 13:52 #52
fint så er vi enige :)
Avatar billede erikjacobsen Ekspert
09. januar 2002 - 13:54 #53
(Undskyld bootie: det er både charmen OG ulempen ved eksperten.dk,
når et spørgsmål går ud af en tangent. Du burde måske - hvis du har
mere at spørge om - lave et friskt spørgsmål)
Avatar billede bootie Nybegynder
09. januar 2002 - 22:09 #54
erik: Det gør da ikke noget. Jeg er selv født up med at break og continue og labels ikke er så smarte at bruge umiddelbart. Så jeg er bare med på en lytter :)
Man er jo aldrig for gammel til at lære nye trix
Avatar billede bootie Nybegynder
29. august 2002 - 01:31 #55
Problemet blev ikke løst
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester