java problem ArrayOutOfBoundsException

Permalänk
Medlem

java problem ArrayOutOfBoundsException

Ska göra ett memoryspel i java. Har kommit så långt att jag vill testa att lägga ut korten på spelplanen men det blir inte som jag vill. Först och främst visas bara en enda stor blå bakgrundsruta trots att jag matar in att jag vill ha två rader och två kolumner i fönstret. Jag antar att de ArrayOutOfBoundsExceptionsen jag får är det som orsakar det hela. Koden ser ut såhär, värdena för setSize satte jag bara på måfå då jag inte riktigt vet hur man ska göra för att anpassa storleken på fönstret efter hur många rader och kolumner man vill ha i spelet.

Här är koden hur som helst

import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; public class Memory extends JFrame { public Memory() { File bildmapp = new File("bildmapp"); File[] bilder = bildmapp.listFiles(); Kort[] k = new Kort[bilder.length]; String r = JOptionPane.showInputDialog("Ange antal rader: "); String c = JOptionPane.showInputDialog("Ange antal kolumner: "); Integer rad = Integer.parseInt(r); Integer kol = Integer.parseInt(c); setLayout(new GridLayout(rad,kol)); getContentPane().setBackground(Color.blue); setSize(350,200); setVisible(true); setDefaultCloseOperation(EXIT_ON_CLOSE); for(int i=0;i<bilder.length;i++){ Icon a=new ImageIcon("getPath(bilder[i])"); k[i]=new Kort(a); } this.nyttSpel(rad*kol,k); } public void nyttSpel(int n, Kort[] k){ Kort[] kFlt = new Kort[n]; Verktyg.slumpOrdning(k); for(int i=0;i<n/2;i++){ kFlt[i] = k[i]; } for(int i=0;i<n/2;i++){ Kort temp = kFlt[i]; temp.copy(); kFlt[i+n/2]=temp; } Verktyg.slumpOrdning(kFlt); for(int i=0;i<n;i++){ add(kFlt[i]); } } public static void main(String[] args){ Memory j = new Memory(); } }

Permalänk
Medlem
Skrivet av Cyrus#18:

Ska göra ett memoryspel i java. Har kommit så långt att jag vill testa att lägga ut korten på spelplanen men det blir inte som jag vill. Först och främst visas bara en enda stor blå bakgrundsruta trots att jag matar in att jag vill ha två rader och två kolumner i fönstret. Jag antar att de ArrayOutOfBoundsExceptionsen jag får är det som orsakar det hela. Koden ser ut såhär, värdena för setSize satte jag bara på måfå då jag inte riktigt vet hur man ska göra för att anpassa storleken på fönstret efter hur många rader och kolumner man vill ha i spelet.

Här är koden hur som helst

import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; public class Memory extends JFrame { public Memory() { File bildmapp = new File("bildmapp"); File[] bilder = bildmapp.listFiles(); Kort[] k = new Kort[bilder.length]; String r = JOptionPane.showInputDialog("Ange antal rader: "); String c = JOptionPane.showInputDialog("Ange antal kolumner: "); Integer rad = Integer.parseInt(r); Integer kol = Integer.parseInt(c); setLayout(new GridLayout(rad,kol)); getContentPane().setBackground(Color.blue); setSize(350,200); setVisible(true); setDefaultCloseOperation(EXIT_ON_CLOSE); for(int i=0;i<bilder.length;i++){ Icon a=new ImageIcon("getPath(bilder[i])"); k[i]=new Kort(a); } this.nyttSpel(rad*kol,k); } public void nyttSpel(int n, Kort[] k){ Kort[] kFlt = new Kort[n]; Verktyg.slumpOrdning(k); for(int i=0;i<n/2;i++){ kFlt[i] = k[i]; } for(int i=0;i<n/2;i++){ Kort temp = kFlt[i]; temp.copy(); kFlt[i+n/2]=temp; } Verktyg.slumpOrdning(kFlt); for(int i=0;i<n;i++){ add(kFlt[i]); } } public static void main(String[] args){ Memory j = new Memory(); } }

vet inte hur det ser ut, men får alltid k och kFlt lika mycket instanser i sig?kFlt blir ju rad*kol stor och k så stor som så många bilder det finns i din mapp, antar jag. står det inte vilken array som du försöker accessa när det händer?

jag tyder iaf felet som om du försökte hämta/sätta ett värde på något som är längre ut än arrayens storlek.

edit: kanske är här
kFlt[i+n/2]=temp;

proa skriv kFlt[i+(n/2)]=temp; istället, då sker uträkningen n/2 och sen adderas i, nu blir det i + n, svaret delat på 2, tror jag iaf

Visa signatur

Laptop - MacBook 2.0GHz, 4GB ram, Intel GMA 950
Stationär - i5 3570k @ 4ghz, 8gb ram, 120gb ssd + 2tb hdd, Windows 8 64bit, fractal design arc
Citera så jag hittar tillbaka :)

Permalänk
Medlem

Debugga och kolla vart du får ArrayOutOfBoundsException.
Det betyder ju att du förstöker komma åt ett värde med ett index som inte finns i arrayn.

Visa signatur

ηλί, ηλί, λαμά σαβαχθανί!?

Permalänk
Medlem

well tanken är att kFlt ska få ett par bilder slumpmässigt ifrån k så jag vet inte vad det skulle hjälpa om man vet att de har samma instanser eller inte.
Jag har aldrig behövt debugga innan så jag vet inte hur man använder det i JCreator Pro som jag sitter med, skulle vara snällt om man får hjälp med hur det fungerar. Just nu när jag debuggar får jag bara upp variabler och deras värden.

Permalänk
Medlem

Låt konstruktorn ta in antalet rader och kolumner som argument, en konstruktor ska inte läsa in indata från användaren själv.

Låt konstruktorn ta in en färdig-validerad kort-array också, att konstruktorn ska öppna filer på det där sättet blir bara krångligt (felhanteringen blir ganska omständig om du ska slänga in en massa try-catch i konstruktorn för att fånga allt som kan gå fel, iom. att konstruktorn inte kan returnera en felkod utan då måste du antingen slänga ett eget exception som säger att Memory konstruktorn misslyckades, eller sätta nån medlemsvariabel med en felkod... Tja, somsagt, undvik sånt i konstruktorn helt enkelt)..

Icon a=new ImageIcon("getPath(bilder[i])");

Gör nog inte vad du vill...

Hur många filer har du i bildmappen, om det är 0 eller 1 så förklarar det ju ArrayOutOfBoundsException iaf (eftersom du säger att du kör med rader=2,kolumner=2.. Vilket ger att n i nyttSpel är satt till 4, men Kort arrayen k bara har ett element..)

for(int i=0;i<n/2;i++){ kFlt[i] = k[i]; //om n är 4 så addresserar du för i=0,1.. Har du då bara en fil i bildmappen så finns inte k[1], vilket då kommer kasta exception }

Tror fö. inte att nyttSpel gör vad du vill..

//Vi antar att n=4 enl. tidigare for(int i=0;i<n/2;i++){ kFlt[i] = k[i]; } //här är kFlt[0]=k[0], kFlt[1]=k[1] for(int i=0;i<n/2;i++){ Kort temp = kFlt[i]; //temp kommer vara kFlt[0], kFlt[1] temp.copy(); //?? kFlt[i+n/2]=temp; //kFlt[2]=kFlt[0], kFlt[3]=kFlt[1] } //k[2],k[3] har aldrig addresserats ännu.. Verktyg.slumpOrdning(kFlt); for(int i=0;i<n;i++){ add(kFlt[i]); //motsvarar add(k[0]),add(k[1]),add(k[0]),add(k[1]) }

Visa signatur

The difference between stupidity and genius - the latter has limits

Permalänk
Medlem
Skrivet av Cyrus#18:

well tanken är att kFlt ska få ett par bilder slumpmässigt ifrån k så jag vet inte vad det skulle hjälpa om man vet att de har samma instanser eller inte.
Jag har aldrig behövt debugga innan så jag vet inte hur man använder det i JCreator Pro som jag sitter med, skulle vara snällt om man får hjälp med hur det fungerar. Just nu när jag debuggar får jag bara upp variabler och deras värden.

tänkte på denna raden

for(int i=0;i<n/2;i++){
kFlt[i] = k[i];
}

man säger att din n är 50, 50/2 är 25. då körs ju forloopen 25 gånger, men om det bara finns 20 bilder i din mapp, efter i är 19 kommer den arrayen ta slut, ellerhur?

Visa signatur

Laptop - MacBook 2.0GHz, 4GB ram, Intel GMA 950
Stationär - i5 3570k @ 4ghz, 8gb ram, 120gb ssd + 2tb hdd, Windows 8 64bit, fractal design arc
Citera så jag hittar tillbaka :)

Permalänk
Medlem

mappen jag hämtar bilderna ifrån innehåller 19 stycken bilder Zevon. Det du säger med att inte ha det i konstruktorn, är det jag som isf misstolkat min lärares tips? (ingen sarkasm, vill bara kolla om jag förstått honom rätt)

Citat:

Bilder

Varje kort skall ha en bild. Bilderna kan hämtas från nätet, där det finns flera webbplatser man kan leta på. För att göra programmet lite roligare kan man hämta hem rörliga (animerade) bilder. Välj bilder som är lagom stora så att de ryms på ett kort i spelet. Skapa en ny mapp (bibliotek) med namnet bildmapp på din dator och placera alla bilder du laddar ner i denna mapp. Obs! Lägg inga andra filer i mappen. Hämta hem fler bilder än vad som på en gång ryms på spelplanen. Då behöver inte samma bilder användas varje gång man spelar. Du måste åtminstone hämta hem så många bilder att det räcker till en spelplan med sex rader och sex kolumner.

För att läsa in de nedladdade bilderna till programmet kan man använda standardklassen File (som beskrivs i avsnitt 16.6 i kursboken). Man börjar med att skapa ett File-objekt som beskriver mappen med bilder:

File bildmapp = new File("bildmapp");

Därefter kan man skapa ett fält med File-objekt där varje objekt beskriver en bildfil:

File[] bilder = bildmapp.listFiles();

För vart och ett av elementen i fältet bilder kan man sedan anropa metoden getPath för att få reda på namnet på motsvarande bildfil. Filnamnen används när man skapar de ImageIcon-objekt som korten skall ha. Löp igenom alla element i fältet bilder och skapa ett Kort-objekt för varje fil. Använd ett fält k för att hålla reda på korten. Allt detta utförs lämpligen i konstruktorn för klassen Memory.

Permalänk
Medlem

Hmm, tja, din lärare verkar ju faktiskt tycka att det är en bra ide att lägga det i konstruktorn (dock borde nog alla hålla med om att dina JOptionPane rader inte ska ligga i konstruktorn), dock är det ju frågan om han föreslår att ni ska göra så pga. att det blir lättast för er eller om han verkligen anser att det är en bra lösning..

Jag hade iaf hellre löst problemet ungefär såhär:

public class Kort { //... public static Kort[] readCardsFromFolder(String folderName) { File folder = new File(folderName); File[] imageFiles = bildmapp.listFiles(); Kort[] cardArray = new Kort[images.length]; for(int i=0;i<images.length;i++) { ImageIcon img = new ImageIcon(imageFiles[i].getPath()); cardArray[i]=new Kort(img); } return cardArray; } //... }

Skriver koden i snabbsvarsfönstret så jag orkade inte lägga till någon felhantering, men ville mer bara visa på hur jag hade tänkt.. Du skulle ju kunna returnera null om det inte finns bilder i mappen eller så kan du ju kasta en exception (sen borde man väl också kontrollera att filerna i mappen faktiskt är bilder, och inte nått annat.. Torde väl bara vara att lägga en try-catch kring new ImageIcon(...) för att säkerställa att det bara är bilder som läggs i arrayen..

Du kan då sedan låta Memory ha konstruktorn:

public class Memory extends JFrame { private int rows; private int cols; private Kort[] cards; public class InsufficientCardsException extends Exception { public InsufficientCardsException() { super(); } } public Memory(int rows, int cols, Kort cards[]) throws InsufficientCardsException{ this.rows=rows; this.cols=cols; //Kasta exception om cards.length < rows*cols/2 if(cards.length<rows*cols/2) { throw new InsufficientCardsException(); } //Kanske även kasta nån exception om rows*cols inte är ett jämnt tal (memory på en 3x1 spelplan blir ju lite konstigt ex..) //... Resten av din konstruktor-kod } public void newGame() { //din nyttSpel funktion.. //Börja med att ta bort ev. tidigare tillaggda kort, slumpa ut nya kort, lägg till de nya korten } }

Din main kan sedan se ut typ såhär:

public static void main(String args[]) { //Bör finnas lite felhantering här också... int rows = Integer.parseInt(JOptionPane.showInputDialog("Ange antal rader: ")); int cols = Integer.parseInt(JOptionPane.showInputDialog("Ange antal kolumner: ")); Kort cards[] = Kort.readCardsFromFolder("bildmapp"); try { Memory memory = new Memory(rows,cols,cards); memory.newGame(); } catch(Memory.InsufficientCardsException e) { System.err.println("Not enough cards for such a large playingfield"); } }

Hmm, blev visst ett långt inlägg av otestad kod.. Hoppas att den inte är allt för trasig

Visa signatur

The difference between stupidity and genius - the latter has limits

Permalänk
Medlem

jag håller med om joptionpane raderna, vet inte riktigt vad jag tänkte. har suttit en del med uppgiften så är lite trött och gör lulliga fel. men ska nog tänka lite på det med hur jag ska forma om konstruktorn. jag såg också ett fel nu när jag jämförde och det var nog som du sa det där med alla bildobjekt jag fösöker skapa. det blir nog lite fel där. men ska kolla mer på det imorgon

Permalänk
Medlem

jag har löst problemet. problemet låg i min slumpgenerator. men nu har jag en ny fråga.
jag ska koppla en lyssnare till alla korten som läggs ut på planen. hur ska lösningsgången för en sådan lyssnare se ut? spelaren kommer nämligen själv bestämma antal kort på planen nämligen.
dessutom måste jag ju veta vilket kort som det klickas på för att sätta den synlig.

Permalänk
Medlem

Du gör ju lab 3 i TDA545

Läs lite i boken så ska du se att det går bra med lyssnarna.

Visa signatur

I'm Winston Wolfe. I solve problems.