8 Arrayer Indexerade variabler, arrayer, vektorer Statistiska mått Sortering Rita polygoner Objektarrayer Starta program med argument Kap 8: Sid 2 I detta kapitel introduceras begreppet array, motsvarigheten till matematikens indicerade variabler (t.ex. x1, x2, … xi, … xn) Arrayer av heltal exemplifieras bland annat med sorteringsövningar och med exempel där man ritar polygoner. Vidare får du skapa arrayer av olika typer av objekt. Gör övningarna i tur och ordning. Avsnitten om statistiska mått och sortering kan eventuellt studeras vid senare tillfälle. Övningarna Rymdskepp, Asteroider och Tarning ligger som grund för kommande övningar. 265338161 © Ove Lundgren 2 Kap 8: Sid 3 Indexerade variabler, arrayer, vektorer Du deklarerar, som bekant, en vanlig primitiv variabel, t ex en heltalsvariabel, så här: int i; 17 i Du har då reserverat plats i minnet för ett heltal som vi refererar till som i. Variabeln i kan tilldelas heltal, t ex i = 17; Ibland behöver man arbeta med många variabler: 17 int i,j,k, m; i j k m = = = = 17; 3; 5; 21; i 3 j 5 k 21 m I matematiken arbetar du med variabler (x, y ,z,…) När vi behöver många variabler använder vi ofta indexerade variabler. Exempel: x1, x2, x3, x4, x5 … De ”nedsänkta” tecknen, 1,2, 3 … kallas index I de flesta programmeringsspråk kan vi arbeta med sådana indexerade, ”numrerade”, variabler. En uppsättning indexerade variabler kallas en array, ibland en vektor. Så här deklarerar man en heltalsarray, vi kallar den a, i Java: int a[] = new int[5]; a[0] Talet 5 inom klammer i högerledet dimensionerar arrayen, det vill säga talet anger att att arrayen ska ha 5 element. Med den här deklarationen reserveras plats för variablerna Varje enskild variabel i arrayen, t ex a[2] a[3] a[0], a[1], a[2], a[3] och a[4] (I matematiken skulle vi förmodligen skriva a[1] a0, a1, a2, a3 och a4 ) a[4] a[2] , kallas alltså ett element i arrayen. Observera att det första elementet i en java-array alltid har nummer 0 (noll) 265338161 © Ove Lundgren 3 Kap 8: Sid 4 När vi arbetar med indexerade variabler med många element orkar vi inte skriva ut varje element. I matematiken skriver vi kanske a0, a1, a2 … ai … a1000 Vi låter indexet representeras av en bokstav (oftast bokstaven i ) På samma sätt gör vi i dataprogram där arrayer används. Övning: Array Vi illustrerar det vi hittills har pratat om med ett litet konsolprogram. Vi utnyttjar Prompt.class som har enkla metoder för inmatning. (Vi utnyttjade det senast i kapitel 5) Skriv in programmet. Spara som ArrayTest.java i mappen X\java\Arraytester class ArrayTest { public static void main( String args[] ) { int a[] = new int[5]; // här deklareras o dimensioneras arrayen for( int i = 0 ; i < 5 ; i++ ) { a[i] = Prompt.heltal("Skriv tal nummer " + i); } System.out.println("Du matade in dessa tal:"); for(int i=0;i<5;i++) { System.out.println("Tal nummer " + i + " är " + a[i]); } } } Du ser hur det fungerar, eller hur? Vi deklarerar arrayen a med 5 element som kommer att heta a[0], a[1], a[2], a[3] och a[4] I den första for-loopen låter vi undan för undan variabeln i anta värdena 0, 1, 2, 3 och 4 Inne i for-loopen kan vi mata in ett värde till a[i], det vill säga till a[0] när loopen körs första varvet, sedan till a[1] och så vidare… I den andra for-loopen skriver vi ut de tal som matats in… Kompilera och kör. Mata in talen 32, 26, 4711, -99 och 13 (ENTER efter varje….) Efter sista inmatningen kommer programmet snällt att skriva ut talen igen… 265338161 © Ove Lundgren 32 a[0] a[1] 26 a[2] 4711 a[3] -99 a[4] 13 4 Kap 8: Sid 5 Lägg till dessa rader i programmet (efter den andra for-loopen i main-metoden): System.out.println("Baklänges:"); for(int i = 4 ; i >= 0 ; i-- ) { System.out.println("Tal nummer " + i + " är " + a[i]); } Inmatade tal skrivs ut baklänges. Vi har nu exemplifierat med heltalsarrayer. På samma sätt kan vi arbeta med arrayer av flyttal (double), tecken (char) och logiska värden (boolean). Vi kan även använda arrayer av strängar. Övning: Array of strings Gör en kopia av programmet ArrayTest. Kalla den ArrayTest2.java. Spara i X\java\Arraytester Ändra class-namnet till ArrayTest2 Deklarera a som en array of strings: String a[] = new String[5]; Ändra i första loopen så att man kan mata in strängar i stället för tal, så här: for(int i = 0 ; i < 5 ; i++ ) { a[i] = Prompt.strang("Skriv namn nummer " + i); } Byt ut ordet ”tal” mot ”namn” i alla ledtexter. Spara. Kompilera. Kör. Skriv in strängar i stället för tal, t ex namn ( Kalle, Stina, Olle, Pelle, Johan ) Övning: Slumpa tal Vi ska experimentera mer med heltalsarrayer. Om vi gör arrayerna större blir det arbetsamt att skriva in tal. Vi slumpar talen i stället. I programmet nedan slumpas 100 tal. Skriv in. Spara Slumpa.java i mappen X\java\Arraytester class Slumpa { public static void main( String args[] ) { int n = 100; int a[] = new int[n]; // Tal i intervallet 0 – 999 slumpas och skrivs ut på skärmen: for(int i = 0 ; i < n ; i++) { a[i] = (int)( 1000*Math.random() ); System.out.print(a[i]+" "); } } } Kompilera och provkör! 265338161 © Ove Lundgren 5 Kap 8: Sid 6 Statistiska mått Antag nu att vi har en mängd tal. De kanske är inmatade. De kanske är hämtade från en fil. (I vårt fall är talen slumpade till en array!) Hur gör man för att beräkna talens summa, medelvärde, max- och min-värde? Övning: Summa-medel-max-min Detta program är inledningsvis identiskt med föregående. Ett antal tal slumpas till en array och skrivs ut. Vi tänker oss att dessa tal är det statistiska material som vi ska bearbeta. Skriv in. Spara Statistik.java i mappen X\java\Arraytester. Kompilera. Provkör: class Statistik { public static void main( String args[] ) { int n = 100; int a[] = new int[n]; // Tal i intervallet 0 - 999 slumpas och skrivs ut på skärmen: for(int i=0;i<n;i++) { a[i] = (int)( 1000*Math.random() ); System.out.print(a[i]+" "); } int summa, max, min; double medel; summa = 0; max = -1; min = 1000; for(int i=0;i<n;i++) { summa = summa +a[i]; if (a[i]>max) max = a[i]; if (a[i]< min) min = a[i]; } medel = (double)summa/(double)n; System.out.println(" "); System.out.println("Summa = " + summa + " Medel = " + medel); System.out.println("Max = " + max + " Min = " + min); } } Variabeln summa är från början 0 Vi loopar genom arrayen och för varje varv adderar vi ett element: summa = summa + a[i]; Efter loopen ligger på så sätt talens summa i variabeln summa Om vi då delar med antalet tal, n, bör vi få medelvärdet. Observera att variabeln medel är flyttal. Variabeln max sätter vi före loopen till ett litet tal (det ska säkert finnas tal i arrayen som är större) Vi väljer max = -1 För varje element i arrayen kollar vi sedan: Om a[i] är störren än max, ja då blir a[i] det nya max-värdet! Det vill säga: if (a[i]>max) max = a[i]; När loopen är slut har vi arrayens största tal lagrad i variabeln max På ett helt analogt sätt finner vi arrayens minsta tal, min Observera att min sätts till ett stort tal före loopen. Det ska säkert finnas tal i arrayen som är mindre. Vi väljer min = 1000 Dessa metoder för att finna summa, medel, max och min är allmängiltiga för all programmering. 265338161 © Ove Lundgren 6 Kap 8: Sid 7 Sortering Arrayer har en mycket stor betydelse inom databehandling. De används för att hålla reda på stora datamängder, för att söka och sortera. Metoden sort() Java2 har en metod för sortering vid namn sort(). Det är en klassmetod i klassen Arrays i paketet java.util Övning: Testa Java2-metoden sort Testa gärna. I programmet Statistik - lägg till: import java.util.*; Skriv in dessa rader sist i main()-metoden: Arrays.sort(a); // här sker sker sorteringen System.out.println("Talen sorterade:"); for(int i=0;i<n;i++) { System.out.print(a[i]+" "); } Kompilera och kör (Java2) Skriv en egen sorteringsmetod Det finns många olika algoritmer för att sortera, mer eller mindre effektiva. Nästa övning visar ett sätt. Först något om hur man får variabelvärden att ”byta plats” (vilket behövs i alla sorteringsalgoritmer) Att låta två variabler byta värde (innehåll) Antag att du har följande: I variabeln x finns ett tal (t ex 17). I variabeln y finns ett annat tal (t ex 82) Vi vill byta plats så att talet i variabeln x hamnar i y, och talet i y hamnar i x. Vilka satser skriver vi då? 17 Försök med x = y; x y = x; 82 y Vad händer? x får först värdet 82 vilket är OK. Men i nästa sats får y värdet av x, vilket ju nu är 82. Båda varaiblerna får samma värde! Nytt försök: Inför en ”slaskvariabel”, s, för tillfällig lagring av ett tal. s = x; x = y; y = s; Nu fungerar bytet! s y x x 17 82 82 s y x © Ove Lundgren 17 17 82 265338161 17 82 17 Satser: y s 7 Kap 8: Sid 8 Övning: Sortera heltal Ta fram din klass, Matte (kapitel 2 och 7) och skriv in denna metod, sortera() public static int[] sortera(int[] a, int n) { int s; for(int i = 0; i < n-1 ; i++ ) { for(int j = i+1; j < n ; j++ ) { if (a[i] > a[j]) // om a[i] > a[j] byter de plats! { s = a[i]; a[i] = a[j]; a[j] = s; // s är slaskvariabel } } } return a; } Metoden har heltalsarrayen a och ett heltal, n (= antal elemenet i arrayen) som parametrar. s är ”slaskvariabeln” som används vid sorteringen Loopen är en så kallad nästlad loop: En ”yttre” for-loop med i som loopvariabel och en ”inre” med j som loopvariabel. I denna nästlade loop sker sorteringen: Looparna tillser att alla element i arrayen jämförs med alla andra element. Om ett element är större än ett annat låter man elementen byta plats. När hela arrayen gåtts igenom ligger talen sorterade… Sist i metoden returneras arrayen a, nu sorterad… Spara Matte.java och kompilera I programmet Statistik ovan – lägg till dessa rader sist i main()-metoden: Matte.sortera(a,n); // Sortering sker System.out.println("Talen sorterade:"); for(int i=0;i<n;i++) { System.out.print(a[i]+" "); } Spara – kompilera – kör… Anmärkning För att det hela ska fungera måste förstås programmet hitta klassen Matte : Filen Matte.class ska ligga i samma mapp som Statistik-programmet eller Filen Matte.class ska ligga i en mapp som ingår i din classpath-lista eller Om Matte.class ingår i ett paket (t.ex. mittpaket) ska du importera det paketet. 265338161 © Ove Lundgren 8 Kap 8: Sid 9 Rita polygoner När man vill skapa en array med få element kan man använda ett kort skrivsätt för att deklarera och dimensionera arrayen samt tilldela elementen värden - allt i ett enda svep. Vår heltalsarray, a, som vi träffade på tidigt i detta kapitel, skulle exempelvis kunna deklarerars, dimensioneras och ”fyllas på” så här: int a[] = { 32 , 26 , 4711 , -99 , 13 }; Vi ska utnyttja detta sätt att skapa arrayer i nedanstående övning. Övning: Polygoner I tidigare övningar har du lärt dig hur man ritar rektanglar och ovaler med hjälp av grafikobjketets metoder. Här kommer ännu en metod, drawPolygon() med vars hjälp vi ritar polygoner (månghörningar) Som argument ska metoden ha två arrayer och ett heltal. Den första arrayen ska innehålla x-koordinater för polygonens hörn. Den andra arrayen ska innehålla y-koordinater för polygonens hörn. Heltalet ska ange antalet hörn. Nedan deklarerar vi arrayerna x och y. Dessa används sedan som argument då metoden drawPolygon() anropas. import java.applet.*; import java.awt.*; public class Poly extends Applet { int x[] = { 100, 200, 150 }; int y[] = { 100, 120, 50 }; public void paint(Graphics g) { g.setColor(Color.red); g.drawPolygon( x, y, 3 ); } } Skriv av koden. Spara som Poly.java i mappen X\java\Polygon Kompilera. Skapa en html-fil som startar appleten. Kör! 150 , 50 En triangel visas… 100 , 100 200 , 120 Byt sedan ut metoden drawPolygon mot fillPolygon Triangeln visas fylld… Rita ytterligare polygoner med fler hörn… 265338161 © Ove Lundgren 9 Kap 8: Sid 10 Övning: Rymdskepp Skriv en klass, Rymdskepp, med följande egenskaper: Ett objekt, rs, instansieras med t.ex rs = new Rymdskepp(40,60); Det ska finnas en metod, public void setPosition(int x, int y){...} där man, vid anrop, kan ange koordinaterna för skeppets spets, t.ex. rs.setPosition(100,120); Det ska finnas en metod, public void visa(Graphics g){...} Då metoden anropas, t.ex. så här rs.visa(g); ska skeppet visas som en ljusgrå ( Color.lightGray) liksidig triangel som har basen 40 och höjden 60 pixels. Skeppets spets ligger i punkten (100,120) Från skeppets spets ska det vara en mörkgrå ( Color.darkGray ) linje i rät vinkel mot basen. Instansvaraibler: private int bredd, hojd, xpos, ypos ( xpos, ypos) hojd (xpos-bredd/2, ypos+hojd) (xpos+ bredd/2, ypos+hojd) bredd Spara Rymdskepp.java i mappen X\java\Asteroid Skriv också en applet, VisaRymdskepp, som instansierar och visar ett Rymdskepp-objekt mot svart bakgrund. Skriv också html-filen som visar appleten… Lösningsförslag på nästa sida… 265338161 © Ove Lundgren 10 Kap 8: Sid 11 // Rymdskepp.java import java.awt.*; public class Rymdskepp { private int xpos; private int ypos; private int bas; private int hojd; public Rymdskepp(int b, int h ) { bas = b; hojd = h; } public void setPosition(int x, int y) { xpos = x; ypos = y; } public void visa(Graphics g) { int x[] = { xpos, xpos-bas/2, xpos+bas/2}; int y[] = { ypos, ypos+hojd, ypos+hojd }; g.setColor(Color.lightGray); g.fillPolygon( x, y, 3 ); g.setColor(Color.darkGray); g.drawLine(xpos,ypos,xpos, ypos+hojd); } } // VisaRymdskepp.java import java.applet.*; import java.awt.*; public class VisaRymdskepp extends Applet { Rymdskepp r; public void init() { r =new Rymdskepp(40,60); r.setPosition( 200,200 ); setBackground(Color.black); } public void paint(Graphics g) { r.visa( g ); } } 265338161 © Ove Lundgren 11 Kap 8: Sid 12 Objektarrayer Precis som vi kan arbeta med arrayer bestående av primitiva variabler kan vi arbeta med arrayer av objekt. Vi exemplifierar med knappar: En ”ensam” knapp deklareras med och instansieras med Button minKnapp; minKnapp = new Button(”Tryck på mej!”); En array of buttons deklareras med (10 element) Button minKnapp[] = new Button[10]; Sen måste varje knappobjekt instansieras. Om möjligt lägger vi instansiering (och utplacering i appleten) i en loop: for(int i = 0 ; i < 10 ; i++) { minKnapp[i] = new Button("" + i); add( minKnapp[i] ); } Övning: Array of buttons A. Spara nedanstående program som ButtArr.java i mappen X\java\ButtArr Skriv också en html-fil (ButtArr.html) som anropar appleten. Kompilera och kör: import java.applet.Applet; import java.awt.*; public class ButtArr extends Applet { //deklarerar array of buttons: Button butt[] = new Button[10]; public void init() { for(int i = 0 ; i < 10 ; i++) { butt[i] = new Button(" " + i + " "); add( butt[i] ); } } } B. Ändra i koden och ändra appletens storlek så att knapparna ligger så här: 265338161 © Ove Lundgren 12 Kap 8: Sid 13 Övning: Veckodagsknappar I övningen nedan ska du göra en applet som visar sju knappar. Knapparna ska ha veckodagarnas namn. Skapa då en string-array med dagarnas namn så här: String s[] = { "Måndag" , "Tisdag" , "Onsdag" , "Torsdag" , "Fredag" , "Lördag" , "Söndag" }; Koden liknar för övrigt koden i föregående exempel. import java.applet.Applet; import java.awt.*; public class Dagknappar extends Applet { //deklarerar array of buttons: Button dagknapp[] = new Button[7]; String s[] = { "Måndag" , "Tisdag" , "Onsdag" , "Torsdag" , "Fredag" , "Lördag" , "Söndag" }; public void init() { for(int i = 0 ; i < 7 ; i++) { dagknapp[i] = new Button(s[i]); add( dagknapp[i] ); } } } Spara Dagknappar.java i 265338161 X\java\Dagknappar © Ove Lundgren 13 Kap 8: Sid 14 Övning: Asteroider I kapitel 4 skrev du klassen Asteroid. Ta fram filen Asteroid.java ! Vi lägger in ännu en konstruktor så att asteroidens storlek och läge slumpas fram. Ändra (början på) klassen Asteroid så att den ser ut så här: import java.awt.*; public class Asteroid { private int xpos, ypos, diam; private Color c1 = new Color(220,220,150 ); private Color c2 = new Color(255,255,190 ); public Asteroid() // ny konstruktor utan parametrar { diam = (int) ( Math.random()*20 )+ 10; // diametern blir 10 – 29 pix xpos = (int)(Math.random()*300); // placering i x-led 0 - 299 ypos = (int)(Math.random()*300); // placering i x-led 0 - 299 } public Asteroid( int d ) { diam = d; } // Metoderna setPosition() och visa() ska vara kvar oförändrade } Skriv en applet, VisaAsteroider.java som skapar en array av Asteroid-objekt. Lösningsförslag: // VisaAsteroider.java import java.applet.*; import java.awt.*; public class VisaAsteroider extends Applet { Asteroid ast[] = new Asteroid[10]; int a, b, s; public void init() { for(int i=0;i<10;i++) { ast[i]=new Asteroid(); } setBackground(Color.black); } public void paint(Graphics g) { for(int i=0; i<10; i++) ast[i].visa( g ); } } 265338161 © Ove Lundgren 14 Kap 8: Sid 15 Övning: Tarning Kommer du ihåg klassen Tarning (Kapitel 7) ? Skriv en applet, Yatzi.java, som instansierar fem stycken tärningsobjekt. När man trycker på en knapp ska tärningarna kastas och visa nya värden. Så här kan appleten se ut: import java.applet.*; import java.awt.*; import java.awt.event.*; public class Yatzi extends Applet implements ActionListener { Tarning t[] = new Tarning[5]; Button butt; int k; public void init() { for (int i = 0; i < 5; i++) { t[i]=new Tarning(40, 60*i + 40); } k = t[i].kasta(); butt = new Button("Kasta!"); butt.addActionListener(this); add(butt); } public void paint(Graphics g) { for(int i = 0;i<5;i++) t[i].visa(g); } public void actionPerformed(ActionEvent e) { for(int i = 0;i<5;i++) k = t[i].kasta(); repaint(); } } Spara – kompilera – provkör! 265338161 © Ove Lundgren 15 Kap 8: Sid 16 Starta program med argument Argumenten i main-metoden I kapitel 1 lärde du dig hur ett javaprogram ser ut. Det är en klass som innehåller metoden main. Så här: class MittProgram { public static void main( String args[] ) { // kod } } Vid kommandot (från DOS-prompten) java MittProgram sker anropet MittProgram.main(); varvid det som är definierat i main-metodens utförs… (Repetera gärna början på kapitel 1 och avsnittet om klassmetoder i kapitel 2) Som du ser är main-metoden definierad med en parameter, en array av typen String Det betyder att man "skicka med " argument (av typen String) när man startar ett javaprogram. Ovning: Testa programstart med argument A. Skriv in detta program, spara det som ArgsTest.java i X\java\Javagrunder och kompilera: class ArgsTest { public static void main( String args[] ) { String txt1, txt2; txt1 = args[0]; txt2 = args[1]; System.out.print( txt1 + " " + txt2 ); } } Vi har deklarerat två String-objekt, txt1 och txt2. Dessa får värdet av angivna argument och skriv ut. Starta konsolprogrammet från DOS-prompten så här: java ArgsTest Stina Olle Programmet skriver ut de angivna argumenten… 265338161 © Ove Lundgren 16 Kap 8: Sid 17 B. Skriv in, spara, kompilera följande program: class ArgsTest2 { public static void main( String args[] ) { int n = Integer.parseInt( args[1] ); for (int i=0; i < n; i++) System.out.println( args[0] ); } } Starta programmet med ( t ex ) java ArgsTest2 Kalle 10 Programmet skriver ut den angivna strängen angivet antal gånger… 265338161 © Ove Lundgren 17