Schleifen | Methoden |
- Anlegen eines Arrays
- Lottozahlen erstellen
- Array-Literale
- Mehrdimensional
- Referenz und ihre Konsequenz
- Videos
Würde man die Lottozahlen in sechs Variablen ablegen, ergäben sich folgende Aufgaben:
- 6 ganze Zahlen definieren: int z1, z2, z3, ... nicht schön
- 6 mal System.out.print ... doof
- Beim Ziehen auf doppelte prüfen ... richtig doof
Anlegen eines Arrays
Ein Array wird durch die eckigen Klammern spezifiziert. Eine Variable ist ein Array von int, wenn vor oder hinter der Variablen ein leeres Paar eckige Klammern definiert sind.int [] lotto;Die Variable enthält nicht selbst den Speicher des Arrays, sondern verweist nur auf den Speicher. In Java wird eine solche Variable eine Referenz genannt. Sie enthält nicht die Daten, sondern den Verweis auf Daten, die sich im Speicher befinden.
Noch weiß die Variable allerdings nichts von Speicher. Der muss mit dem Befehl new erst angelegt werden. Auf den Befehl folgt der Typ der Elementvariablen und in eckigen Klammern, wie viele Elemente benötigt werden. Im Falle von Lotto wird int verwendet und es sind 6 Zahlen.
int [] lotto = new int[6];
Damit existieren im Speicher sechs Speicherplätze für int, die über die Referenz lotto zugegriffen werden. Um ein einzelnes Feld zuzugreifen, wird hinter lotto ein rechteckiges Klammernpaar mit der Positionsnummer verwendet. Dabei ist zu berücksichtigen, dass die Zählung bei 0 beginnt und da es sechs Elemente sind, die höchste Position die Nummer 5 ist.
a[0] = 15; // Erstes Element wird mit 15 besetzt a[5] = 48; // Letztes Element wird mit 48 besetzt int zahl = a[5]; // Auslesen des letzten ElementsSollen alle Elemente des Lottofeldes mit Werten gefüllt werden, drängt sich die for-Schleife förmlich auf.
final int MAX = 6; int [] lotto = new int[MAX]; for (int i=0; i<MAX; i++) { lotto[i] = 1; }
Spezial-for für das Auslesen eines Arrays
Java verfügt über eine spezielle Variante der for-Schleife, mit der Arrays ausgelesen werden können. Dabei wird im Schleifenkopf einer Variablen des gleichen Typs wie einer Elementvariable nacheinander jedes Element der Schleife zugewiesen.final int MAX = 6; int [] lotto = new int[MAX]; for (int zahl : lotto) { System.out.println(zahl); }
Die Größe eines Arrays auslesen
Alle Arrays besitzen eine Instanzvariable namens length, mit der man deren Länge ermitteln kann.System.out.println(lotto.length);
Lottozahlen erstellen
Lottospielen macht viel mehr Spaß, wenn man die Zahlen selbst zieht. Dazu müssen die Zahlen mit Werten belegt werden, so dass es keine doppelten Zahlen gibt und anschließend sortiert werden.Zufall
Hier müssen wir einen kleinen Ausflug in die Zufallszahlenerzeugung machen. Die Bibliothek java.util stellt eine Klasse Random zur Verfügung. Von dieser muss ein Objekt mit dem Befehl new erzeugt werden. Darüber kann die Methode nextInt aufgerufen werden, die eine zufällige ganze Zahl liefert, die zwischen 0 und dem übergebenen Wert liegt. Da die Lottozahlen bei 1 beginnen, addieren wir eine 1 auf den Wert.java.util.Random zufall = new java.util.Random(); int[] lotto = new int[6]; for (int i=0; i<6; i++) { lotto[i] = zufall.nextInt(48) + 1; }
Doppelte vermeiden
Ärgerlicherweise kann es passieren, dass zufällig zwei gleiche Zahlen gezogen werden. Man könnte dies anschließend prüfen und dann eine neue Ziehung veranlassen. Das ist aber wenig effizient. Sinnvoller ist es, bei jeder gezogenen Zahl zu prüfen, ob diese Zahl in einer der vorigen Runden gezogen worden ist und dann nur diese eine Zahl noch einmal zu ziehen.Dazu wird in die Schleife eine weitere Schleife gebettet, die einen neuen Zähler immer von der 0 bis zur bisher letzten gezogenen Zahl läuft und darin die aktuell gezogene mit den vorigen Zahlen vergleicht.
Gibt es eine Gleichheit, wird der Index der äußeren Schleife herabgesetzt. Damit wird erreicht, dass die letzte Zahl noch einmal gezogen wird.
java.util.Random zufall = new java.util.Random(); int[] lotto = new int[6]; for (int i=0; i<6; i++) { lotto[i] = zufall.nextInt(48) + 1; for (int j=0; j<i; j++) { if (lotto[i]==lotto[j]) { // Doppelt! Letzte Zahl noch einmal ziehen j = 6; // innere Schleife abbrechen i--; // Ziehung wiederholen } } }
Sortieren
Nun liegen die Lottozahlen unsortiert vor. Die wohl einfachste Form des Sortierens ist es, von links nach rechts durchzugehen und zu vergleichen, ob die linke kleiner als die rechte ist. Ist das nicht der Fall, werden die beiden getauscht.
for (int i = 0; i < 5; i++) { if (lotto[i] > lotto[i + 1]) { int tausch = lotto[i]; lotto[i] = lotto[i + 1]; lotto[i + 1] = tausch; } }
Leider reicht ein einziger Durchlauf nicht. Es wird zwar besser, aber noch nicht vollständig sortiert. Ein Durchlauf gewährleistet aber immerhin, dass das höchste Element anschließend ganz rechts ist. Versuchen wir es damit, dass wir die Schleife sechs Mal durchlaufen.
for (int j = 0; j < 6; j++) { for (int i = 0; i < 5; i++) { if (lotto[i] > lotto[i + 1]) { int tausch = lotto[i]; lotto[i] = lotto[i + 1]; lotto[i + 1] = tausch; } } }
Ist das optimal? Bestimmt nicht. Als erstes erinnern wir uns, dass bei einem inneren Durchlauf die größte Zahl immer nach rechts außen wandert. Dann müssen wir die rechteste Zahl nicht mehr vergleichen.
In der zweiten Runde muss man die rechten beiden Werte nicht mehr vergleichen, in der dritten Runde die rechten drei und so weiter.
Wir erreichen das, indem wir die Endbedingung der inneren Schleife von konstant 5 auf 5-j setzen.
for (int j = 0; j < 6; j++) { for (int i = 0; i < 5-j; i++) { if (lotto[i] > lotto[i + 1]) { int tausch = lotto[i]; lotto[i] = lotto[i + 1]; lotto[i + 1] = tausch; } } }
In der sechsten Runde wird die innere Schleife gar nicht mehr durchstarten, da 5-5 ja 0 ergibt. Also reduzieren wir die Grenze der äußeren Schleife von 6 auf 5.
for (int j = 0; j < 5; j++) { for (int i = 0; i < 5-j; i++) { if (lotto[i] > lotto[i + 1]) { int tausch = lotto[i]; lotto[i] = lotto[i + 1]; lotto[i + 1] = tausch; } } }
Bibliotheksaufruf
Die einfachere Variante ist es, die Sortierfunktion aus der Bibliothek java.util zu verwenden, die für Arrays zur Verfügung steht.java.util.Arrays.sort(lotto);
Array-Literale
Sie können auch ohne new arbeiten, wenn Sie das Array mit einem Literal vorbelegen. Ein Literal für ein Array besteht aus dessen Elementliteralen, die kommasepariert in einem geschweiften Klammernpaar stehen. Falls Ihnen bestimmte Lottozahlen besonders gut gefallen, könnten Sie sie so anlegen:int [] lotto = { 1, 4, 9, 16, 25, 36 };Natürlich müssen es nicht zwingend ganze Zahlen sein. Das folgende Beispiel zeigt, wie ein Kartenspiel simuliert wird. Dazu wird ein Array von 32 int-Werten angelegt, die für ein Skatblatt stehen. Gefüllt wird es mit den Zahlen von 0 bis 31.
Teilt man eine solche Zahl durch 4, erhält man einen Wert zwischen 0 und 7, den man den Kartenwerten 7, 8, 9, 10, B, D, K und A zuordnen kann. Verwendet man die Modulo-Rechnung erhält man einen Wert zwischen 0 und 3, der jeweils einer Kartenfarbe zugeordnet werden kann.
Um diese Karten benutzerfreundlich anzuzeigen, kann man jeweils ein Array von char anlegen, dass die Symbole enthält. Leider ist die 10 zweistellig, darum verwenden wir hier ein Z. Da Kreuz und Karo beide mit K anfangen, verwenden wir Treff statt Kreuz, das mit T anfängt.
public class Kartenspiel { public static void main(String[] args) { int[] blatt = new int[32]; char[] farbe = {'T', 'P', 'H', 'K' }; char[] wert = {'A', 'K', 'D', 'B', 'Z', '9', '8', '7'}; for (int i=0; i<32; i++) { blatt[i] = i; } for (int karte : blatt) { System.out.print(farbe [karte%4]); System.out.print(wert[karte/4]); System.out.print(" "); } } }Wenn Sie das Programm ausführen erhalten Sie folgende Ausgabe:
TA PA HA KA TK PK HK KK TD PD HD KD TB PB HB KB TZ PZ HZ KZ T9 P9 H9 K9 T8 P8 H8 K8 T7 P7 H7 K7Sie können nun das Skatblatt mischen und auf drei 10-er Arrays verteilen, diese wieder sortieren und haben den Beginn eines kleinen Skatprogramms.
Mehrdimensional
Arrays können auch mehrdimensional sein, hier am Beispiel eines Spielfelds. Vor Spielbeginn soll das Spielfeld mit Pluszeichen gefüllt werden. Während des Spiels soll ein Spieler Felder ändern können. Hier wird es simuliert, indem die 4. Position von oben und die 6. Position von links mit einem X markiert wird.char[][] spielfeld = new char[7][9]; for (int i=0; i<7; i++) { for (int j=0; j<9; j++) { spielfeld[i][j] = '+'; } } spielfeld[3][5] = 'X'; for (char[]zeile : spielfeld) { for (char feld : zeile) { System.out.print(" "+feld); } System.out.println(); }Die Ausgabe des Programms sieht folgendermaßen aus:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + X + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Referenz und ihre Konsequenz
Eine Array-Variable enthält nicht die Daten des Arrays, sondern nur eine Referenz auf die Daten. Das hat Konsequenzen:- Sobald man eine Referenzvariable kopiert,
wird nicht etwa ein Duplikat der Daten angefertigt, sondern eine zweite
Referenz auf die gleichen Daten. Das folgende Listing zeigt dies:
class arrayRef { public static void main (String[] arg) { int a[] = { 1,2,3,4,5}; int b[] = a; // b referenziert auf a b[2] = 25; // auch a[2] wird veraendert! // Zeig das Array: for (int i=0; i<5; i++) { System.out.print( i ); System.out.print( " " ); System.out.print( a[i] ); System.out.print( " " ); System.out.println( b[i] ); } } }
Kopie eines Arrays
Eine Array-Kopie erzeugt man, indem man ein neues Array mit new anlegt und die Elemente des alten Arrays in das neue Array in einer Schleife kopiert.final int LAENGE = 4; int[] a = new int[LAENGE]; a[2] = 4; int[] b = new int[LAENGE]; // Speicher für Kopie anlegen for (int i=0; i<LAENGE; i++) { b[i] = a[i]; // Werte kopieren } a[2] = 33; // Test, ob b eine Kopie ist System.out.println(b[2]); // b ist unverändert 4
Alternativ verwendet man clone:int b[] = a.clone(); // b referenziert auf einer Kopie von a
- Das Gleiche gilt für die Abfrage auf Gleichheit.
Wird der == Operator verwendet, wird geprüft, ob beide Variablen auf
denselben Datensatz referenzieren.
Will man also feststellen, ob der gleiche Inhalt in beiden Arrays steht, schreibt man eine Schleife.
Die Methode equals hilft hier wenig, weil auch sie die Referenzen prüft. Allerdings bietet java.util.Arrays noch eine passende Lösung für die Arrays primitiver Typen.
if (java.util.Arrays.equals(lotto, b)) {
Videos
Teil 1: Anlegen und Umgang mit einem Array
Teil 2: Kopieren von Arrays
Teil 3: Lottozahlen mit Zufall
Teil 4: Mehrdimensionale Arrays
Schleifen | Methoden |