7. Felder

7. Felder

Definition:

  • Ein Array(Feld) ist ein Javaobjekt, das aus Elementen eines gemeinsamen Basistyps zusammengesetzt ist.
  • Der Zugriff auf ein Feld erfolgt immer über den Index des Feldes
  • In Java beginnen Felder mit n Elementen mit dem Index [0] und enden mit dem Index [n-1]

Felder sind Javaobjekte und werden im Freispeicher (Heap) verwaltet, da Felder variable Größen haben. Aus diesem Grund können sie nicht statisch auf dem Stack (Stapel) angelegt werden. Anbei die Speichersicht, die ähnlich zu Strings ist. Das abgebildete Diagramm zeigt ein Feld mit Platz für 6 Ganzzahlen:

Felder sind häufig verwendete Datenstrukturen da man sehr einfach mit Schleifen über den Index alle Feldelemente erreichen kann.

Der Zugriff auf Feldelemente erfolgt über eine Syntax mit Verwendung von rechteckigen [index] Klammern wie man im folgenden Beispiel sehen kann:

int[] d1 = { 1000, 100, 10};
int a = d1[2]; // Auslesen von 10 aus Position 2
d1[0]= 99; // Zuweisen des Werts 99 auf Position 0

Weitere Quellen

Oracle Tutorial: Arrays (in Englisch)

Stefan Schneider Mon, 08/23/2010 - 19:51

7.1 Eindimensionale Felder

7.1 Eindimensionale Felder

Das Definieren und Erzeugen von eindimensionalen Feldern erfolgt nach ähnlichen Prinzipien wie die Verwaltung von Strings.

Es gibt hier zwei Varianten.

Anlegen und befüllen mit new() Operator

Die Deklaration anhand eines Feldes von Ganzzahlen mit Hilfe des new() Operators in 3 Schritten:

int[] array1;

Hiermit wurde nur die Referenz auf ein (zukünftiges) Feld von Ganzzahlen angelegt. Siehe unten: Mit Hilfe des new() Operators wird ein leeres Feld angelegt. Nach dem Anlegen des Feldes kann man die Größe des Feldes mit dem Attribut length abfragen.:

array1 = new int[6];
int s = array1.length;

Das Definieren der Variablen array1 und das Aufrufen des new() Operators hätte auch in einem Schritt erfolgen können

int[] array1 = new int[6];

Jetzt kann das Feld mit Werten belegt werden. Zum Beispiel mit Vielfachen der Zahl 17:

for ( int i=0; i<s; i++) {array1[i]  = i*17;}

Aufzählende Wertzuweisung

Java erlaubt auch die 3 Schritte von oben in einer einzigen Operation auszuführen. Hier können alle Werte als Aufzählung innerhalb von geschweiften Klammern direkt zugewiesen werden:

int[] array1 = {0,17,34,51,68,85};

Belegen mit einem festen Wert

Die Methode fill() erlaubt das belegen eines Feldes mit einem festen Wert

array.fill(-1);

Hier werden alle Elemente eines Feldes mit dem Wert -1 belegt.

 Zuweisungen zwischen Arrayvariablen

Arrayvariablen verhalten sich wie Referenzen bezüglich Zuweisungen. Das Zuweisen des Nullwerts löscht die Referenz auf ein Feld(Array). Es ist dann ein Kandidat zum Löschen falls keine andere Referenz auf das Feld vorhanden ist. Das folgende Beispiel zeigt eine Zuweisung zwischen den Feldvariablen.

int[] array1 = {0,17,34,51,68,85};
int[] array2 = array1;
if (array1[2] == array2[2]) 
   System.out.println("Dieser Text sollte " +
      "ausgedruckt werden!");

Beide Variablen array1 und array2 zeigen auf dasselbe Feld

Durch das Zuweisen des null Werts werden die Referenzen gelöscht. Das Feld bleibt bestehen. Es wird jedoch gelöscht, wenn es keine andere Referenz mehr auf das Feld gibt.

array1 = null;
array2 = null;

Kopieren von Feldern

Das naive Kopieren von Feldern mit vollständiger Replikation kann man mit der erweiterten Notation der for Schleife leicht selbst implementieren:

int[] array1 = {0,17,34,51,68,85};
int[] array2 = new int[array1.length];
for (int i=0; i<array1.length; i++) 
   {array2[i]= array1[i];}

Alle Elemente des Felds werden einzelnen kopiert. Die erweiterte Notation erlaubt es die Anweisung ohne explizite Verwendung der Feldgröße anzugeben. Das Ergebnis hat eine Speicherstruktur wie folgt:

Eine effizientere Möglichkeit bildet die Methode System.arraycopy() aus der System Klasse. Diese Methode hat die folgende Signatur:

public static void arraycopy(Object src,
                             int srcPos,
                             Object dest,
                             int destPos,
                             int length)

Sie erlaubt:

  • von einem Feld src ab der Position srcPos
  • in ein Feld dest an die Position destPos
  • die Anzahl length Objekte zu kopieren

Das oben aufgeführte Beispiel würde wie folgt mit der Methode arrayCopy() implementiert:

int[] array1 = {0,17,34,51,68,85};
int[] array2 = new int[array1.length];
System.arrayCopy(array1,0,array2,0,array1.length);

Ausnahmen und Fehler bei Arbeiten mit Arrays (Feldern)

Beim Lesen und Manipulieren von Feldern können unterschiedliche Fehler auftreten. Sie können beim Über- oder Unterlauf eines Feldes auftreten oder bei dem Versuch Typen zuzuweisen die das Feld nicht erlaubt. Die folgenden Ausnahmen (Exceptions) können auftreten: 

 

Stefan Schneider Mon, 10/11/2010 - 12:57

Anonymous (not verified)

Thu, 11/26/2015 - 19:48

Fehlt hier bei dem Anlegen in 3 Schritten bei der for-Schleife, wo steht: {array[i] = i*17} nicht die 1 hinter array? Damit man sich auf das array1, welches deklariert wurde bezieht?

LG

7.2 Felder als Parameter von Methoden

7.2 Felder als Parameter von Methoden

Felder(Arrays) können wie Basistypen oder Referenzen als Übergabe- und Rückgabeparameter von Methoden verwendet werden.

Ein typisches Beispiel ist:

public static void main(String[] args) {
    ...
      if (args != null)
       if (args.length > 2 ) {
           tag   = Integer.parseInt(args[0]);
           monat = Integer.parseInt(args[1]);
           jahr = Integer.parseInt(args[2]);
           ...
        }

Die beim Programmstart mitgegebenen Argumente werden in Form eines Feldes von Zeichenketten übergeben. Man erkennt beim Beispiel oben, dass im Quellcode eine Reihe von Fehlerfällen geprüft werden bevor die Anwendung auf das "unbekannte" Feld zugreift und die Zeichenketten in Zahlen verwandelt:

  • args ist eventuell ein null Zeiger
  • die Anzahl der Argumente ist unbekannt. Nur wenn mehr als zwei Elemente im Feld sind werden die ersten 3 Elemente ausgelesen.

Hierbei ist wichtig, dass die Felder nach dem gleichen Konzept wie Referenzen übergeben werden:

  • Call by Reference: Das Feld wird nicht dupliziert. Es steht der Methode nicht unbedingt exklusiv zur Verfügung. Es wird nur eine Referenz übergeben.

Entsprechend können Felder auch als Rückgabeparameter dienen. Der Rückgabeparameter muss mit Typ und rechteckiger Klammer genannt werden. Hier int[]:

public static int[] createRandom(int size, int range) {
   int[] array1 = new int[size];
   for (int i=0; i<size;i++) 
       array1[i] = (int)(Math.random()*range);
   return array1;

Methoden mit variabler Argumentenanzahl

Es gibt Anwendungsfälle bei bei denen es wünschenswert ist eine variable Anzahl von Parameter zu benutzen. Seit Java 5 muss man hier nicht mehr ein Feld übergeben. Für sogenannte "varargs" Methoden gibt es ein "..." Konstrukt (drei Punkte) mit dem man die variable Anzahl der Parameter eines bestimmten Typs deklarieren kann. 

Anbei das Beispiel einer Methode, die die Namen von Haustieren entgegen nimmt:

public void hausTiereMelden(String ... tierNamen) {
   for ( String t : tierNamen) System.out.println("Haustier: " +t);
}
public static void test () {
   hausTiereMelden("Waldi","Bello","Rufus");
   hausTiereMelden("Mikesh", "Napoleon");
   hausTiereMelden(); // Keine Parameter!
}

Hinweis: "varargs" Methoden dürfen auch ganz ohne Parameter aufgerufen werden. Die Implementierung der Methode muss daher auch mit einer null Belegung umgehen können!

Stefan Schneider Mon, 10/11/2010 - 15:49

Das Ergebnis von Math.random() liegt immer im Intervall von 0-1. Multipliziert man es bekommt man ein Ergbnis im Bereich 0 bis range. Durch das Casten auf (int) werden dann die Nachkommastellen abgeschnitten.

7.3 Mehrdimensionale Felder

7.3 Mehrdimensionale Felder

Eindimensionale Felder entsprechen Listen mit einem wahlfreien Zugriff. Java erlaubt auch die Benutzung von zwei- und mehrdimensionalen Feldern.

Zweidimensionale Felder

Ein zweidimensionales Feld besteht entsprechend aus Zeilen und Spalten. Die Java Syntax hierzu ist eine Konkatenierung von eckigen Klammern. Zur Erzeugung eines Feldes mit 3 Zeilen und 6 Spalten nutzt man die folgende Notation:

int[][] array1 = new int[3][6];

Hiermit ergibt sich eine Speicherstruktur die aus einem Spaltenfeld besteht welches alle Zeilenfelder enthält um eine zweidimensionale Struktur aufzuspannen. Man kann hier jetzt 3*6=18 Werte speichern:

 

Das Setzen und Lesen von Werten geschieht wie folgt:

int k = 222;
array1[2][5]= k;
int n = array1[0][0];

Aufzählende Initialisierung mehrdimensionaler Felder

Auch bei mehrdimensionalen Feldern ist eine aufzählende Initialisierung möglich:

int[][] array1 = {{1,2,3,4,5,6},{5,10,15,20,25,30},{10,20,30,40,50,60}}

Hiermit ergibt sich eine zweidimensionale Tabelle mit der folgenden Belegung:

Bestimmung der Größe mehrdimensionaler Felder

Das Attribut length erlaubt auch bei mehrdimensionalen Feldern die Bestimmung der Größe. Hier liefert das Attribut jedoch nicht die Gesamtgröße der Datenstruktur sondern nur die Größe einer bestimmten Dimension.

int d =array1.length;

liefert im oben gezeigten Beispiel eine 3 für die erste Dimension, die Zeilen.

int d = array1[2].length;

gibt eine 6 zurück. Da die dritte Zeile 6 Elemente hat.

Anmerkung: Höher dimensionale Felder haben nicht unbedingt in allen Dimensionen die gleiche Größe. Dies bedeuted, dass ein zweidimensionales Feld muss nicht rechteckig sein muss!

Die folgende Implementierung erzeugt ein "dreieckiges" zweidimensionales Feld:

int[][] array1;
array1 = new int[3][];
array1[0] = new int[1];
array1[1] = new int[2];
array1[2] = new int[3];

Die Speicherstruktur zu diesem Feld sieht wie folgt aus:

Eine aufzählende Initialisierung ist auch möglich:

int[][] array1 = {{1},{11,22},{111,222,333}};

Das length Attribut liefert bei dieser Struktur die unterschiedlichsten Ergebnisse.

Höherdimensionale Felder

Nach dem gleichen Verfahren können dreidimensionale oder noch höherdimensionale Felder erzeugt und verwaltet werden.

Person[][][] Mitarbeiter = new Person[10][10][10];
Mitarbeiter[7][8][9] = new Person ("Jane","Doe");

Im vorliegenden Beispiel handelt es sich um ein dreidimensionales Feld mit einem Objekttyp (Person). Bei Objektfeldern werden nur die Felder angelegt nicht aber die zugehörigen Objekte. Sie müssen individuell erzeugt werden. Nach der initialen Felderzeugung sind alle Felder mit Nullreferenzen belegt. Mit dieser Belegung lässt sich normalerweise schlecht arbeiten. Bei Basistypen ist dies anders. Sie werden auch auf Null initialisiert und können direkt verwendet werden. Bei Feldern mit Referenzen werden jedoch nicht direkt die benötigten Objekte angelegt.

Stefan Schneider Mon, 10/11/2010 - 15:50

7.4 Übungen

7.4 Übungen

Duke als Boxer

 7.4.1 Telefonbuchanwendung (1)

Implementieren Sie eine Telefonbuchanwendung die es erlaubt die folgenden Datensätze zu verwalten:

  • Name String
  • Vorname String
  • Telefonnummer Ganzzahl

 Benötigte Zeit: 30-60 Minuten für einen gübten Programmierer

Die Klasse Telefonbuch soll die folgenden Eigenschaften haben:

  • Verwaltung des Namens, Vornamens, Telefonnummer in drei Feldern mit den entsprechenden Typen
  • Eine Methode die das gesamte Telefonbuch ausdruckt
  • Suche nach allen drei Attributen mit drei verschiedenen Methoden
  • Eine Methode zum "bevölkern" des Telefonbuchs mit mindestens 10 Namen
    • Alle Datensätze seien unterschiedlich
  • Das Telefonbuch soll initial Felder für 4 Einträge besitzen. Beim Vollaufen des Telefonbuchs sollen neue Felder angelegt werden die um 50% größer sind.
  • Kapseln Sie die gesamte Implementierung der Felder innerhalb der Klasse
  • Implementieren Sie eine Methode zum Löschen eines gesuchten Datensatzes
    • Beim Löschen sollen keine leeren Einträge in den Feldern entstehen
  • Implementieren Sie eine Testmethode die
    • 10 Adressen einträgt
    • 2 Adressen löscht
    • 1 Adresse hinzufügt

Hinweise:

  • Benutzen Sie Methoden für alle sinnvollen Teilaufgaben
  • Das Telefonbuch ist nicht notwendigerweise sortiert. Man muss alle Datensätze durchsuchen

Tipp: Die Suchanfragen lassen sich mit wenig Aufwand vom einer grafischen Swingoberfläche steuern. Ein Beispielprogramm finden Sie hier.

7.4.2 "Objektorientierte" Telefonbuchanwendung (2)

Überarbeiten Sie die Telefonbuchanwendung aus der vorhergehenden Aufgabe derart, dass Sie:

  • Eine Klasse Person mit den drei Attributen nutzen
  • Nur ein Feld vom Typ Person in dem alle Daten verwaltet werden

Welche der beiden Lösungen gefällt Ihnen besser? Warum?

7.4.3 Zufallszahlengenerator

Schreiben Sie ein Programm welches die Zuverlässigkeit des Java Zufallszahlengenerator prüft.

  • Erzeugen Sie ein Feld mit 1 Million (Anzahl konfigurierbar) Zufallszahlen im Bereich von 0 bis 999. Nutzen Sie die Methode Math.random() und das existierende Beispielprogramm.
  • Erzeugen Sie ein dreidimensionales Feld für Ganzzahlen mit einer Größe von 10*10*10 Einträgen (Index jeweils 0..9).
    • Speichern Sie in diesem Feld die Häufigkeit einer vorgekommenen Zahl.
    • Bsp: Erhöhen sie den Zähler der Position [5][4][3] um wenn Sie eine Zufallszahl "534" gefunden haben. Die Zelle [5][4][3] speichert die Anzahl der gefundenen Zahlen "542".
  • Zählen Sie die Zufallszahlen und tragen Sie sie in das dreidimensionale Feld ein
    • Beispiel: Inkrementieren den Wert der Zelle array[2][4][5] für jedes Vorhandensein der Zahl 245
  • Schreiben Sie eine Methode zum Ausdrucken des Feldes
  • Schreiben Sie Methoden die die folgenden Fragen beantworten
    • Welche Zahl kommen am häufigsten vor?
    • Welche Zahl kommen am seltensten vor?
  • Optional (keine Musterlösung):
    • Gibt es lokale Häufungen?
      • Welche Einer-, Zehner, Hunderterziffer ist am häufigsten?
      • Haben Zellen mit über/unterdurchschnittlich vielen Einträgen auch Nachbarn mit über/unterdurchschnittlich vielen Einträgen?
      • Eine Zelle array[x][y][z] hat meistens 8 Nachbarn array[x+/-1][y+/-1][z+/-1]

7.4.4 Conway: Das Spiel des Lebens

Das "Spiel des Lebens" wurde 1970 vom Mathematiker John Horton Conway 1970 entworfen.

Das Simulationsspiel basiert auf auf einem zweidimensionalen zellulären Automaten. Die Regeln des Automaten sind im Wikipediaartikel zu finden.

Die gelöste Aufgabe kann man in der unten genannten Anwendung sehen.

  • Das Setzen von Elementen ist mit Mausklicks auf der entsprechenden Zelle möglich
  • Eine neue Generation wird mit dem Button ">" berechnet
  • Der Button ">>>" erlaubt das automatische Erzeugen von neuen Generationen. Mehrfaches Klicken halbiert die Wartezeit zwischen Generationen.
  • Der Button "Stop" beendet den automatischen Modus

Laden Sie das jar-Archiv Conway.jar und starten Sie es im gleichen Verzeichnis mit dem Kommando

java -jar Conway.jar

Bsp. Conway Anwendung

Aufgabe

Vervollständigen die Klasse Generation.java. Nutzen Sie das Hauptprogramm SpielDesLebens.java zum Testen Ihrer Klasse.

Die Interaktion der Klasse Generation mit dem Rahmenprogramm ist im folgenden Diagramm dargestellt:

Interaktion der Klassen

Klasse Generation.java

Hinweise:

  • Das Hauptprogramm erwartet die Klasse Generation mit den vorgegebenen Methoden im gleichen Paket
  • Sie können weitere Methoden wenn nötig implementieren
  • Das Hauptprogramm wird genau eine Instanz der Klasse Generation erzeugen.

Beim Berechnen der Nachbarn eines Feldes ist auf die Sonderfälle am Rand zu achten:

Anzahl NAchbarn

Weitere Hilfestellungen sind den Kommentaren zu entnehmen. Die Klasse kann natürlich auch ohne die Hilfestellung entwickelt werden. Das Feld kann initial zum Testen sehr klein (2) sein. Die Buttons werden dann erst nach dem Vergrößern des Fenster sichtbar. Eine Größe von 50x50 ist für aktuelle Rechner ausführbar. Pro Zelle werden etwa 10 Pixel benötigt. 

package s1.block7;
/*
 * @author scalingbits.com
 */
public class Generation {
    // Hier ein Feld für alten Zustand deklarieren
    // Hier ein Feld für neuen Zustand deklarieren
    // die Felder muessen zweidimensional, vom Typ boolean sein, quadratisch sein

/**
* Groesse des quadratischen Feldes
*/

// Variable für Groesse des Feldes anlegen. Empfohlen 50 ==> GUI benötigt dann etwa 500 Pixel
/**
* Anlegen aller benoetigten Felder mit Initialwerten
* Alle Feldelemente sollen mit dem Zustand "false" = leer versehen sein
*/
public Generation() {
// Initialisieren sie die beiden Felder
// alle Felder sollen den Zustand "false" haben. Dies ist ein leeres Feld

}

/**
*
* @return Kantenlaenge des quadratischen Felds
*/
public int groesse() {return 0;} //Richtigen Wert zurueckgeben!!

/**
* Berechnen einer neuen Generation.
* Legen Sie ein neues Feld an. Berechnen Sie den neuen Zustand
* aller Feldelement aus dem alten Feld
*/
void neueGeneration() {
// Tipps:
// Weisen Sie die aktuelle Generation auf die alte zu
// Erzeugen oder wiederverwenden Sie ein Feld für eine neue Generation
// Nutzen Sie eine doppelt geschachtelte Schleife zum Ueberstrichen des aktuellen Felds
// Zaehlen Sie die Nachbarn der aktuellen Position in der alten Generation
// Achten Sie auf die Feldgrenzen!!
// Setzen Sie den Wert des aktuellen Felds auf "true" falls ein Objekt erhalten oder erzeugt werden soll
// Setzen Sie dem Wert des aktuellen Felds auf "false" falls kein Objekt in der neuen Generation existieren soll

}

/**
* Das Feld mit den aktuellen Werten
* @return
*/
public boolean[][] status() {return null;} // Hier das aktuelle Feld zurückgeben

}

Klasse SpielDesLebens.java

Das Hauptprogramm. Achten Sie auf die Paketstruktur!

Beim vorgebenen Paket kann das Programm mit dem folgenden Befehl gestartet werden

$ java s1.block7.SpielDesLebens
package s1.block7;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
/**
* Das Spiel des Lebens nach Conway
* @author s@scalingbits.com
*/
public class SpielDesLebens extends JApplet implements Runnable {
final private int size;
final private int xRaster=10;
final private int yRaster=10;
final private Generation gen;
final private JButton[][] buttonFeld;
private static boolean appletMode = true;
private static boolean autoMode = false;
private ImageIcon belegtIcon;
private ImageIcon freiIcon;
private static SpielDesLebens myself;
private int sleeptime = 2000; // Millisekunden im Automode

public class Zelle extends JButton {
final public int x;
final public int y;

public Zelle (Icon ic, int x, int y) {
super(ic);
this.x=x;
this.y=y;
}
}
/**
* Der Konstruktor ohne Argumente wird nur beim einem Start als Applet
* benutzt. Hier wird ein Applet mit einem Grid erzeugt.
*/
public SpielDesLebens() {
erzeugeIcons();
myself=this;
gen = new Generation();
size = gen.groesse();
JFrame f = null;
if (!appletMode) f = new JFrame("Game");
JPanel jp = new JPanel();
jp.setLayout(new GridLayout(size, size));
buttonFeld = new JButton[size][size];
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
buttonFeld[i][j] = createButton(i, j);
jp.add(buttonFeld[i][j]);
}
}
JButton naechste = new JButton(">");
naechste.setToolTipText("Erzeuge nächste Generation");
naechste.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) { nextGen();}
} // Ende innere Klasse
);
JButton auto = new JButton(">>>");
auto.setToolTipText("Starte Film");
auto.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
sleeptime /=2; // Verdoppeln der Geschwindigkeit
if (!autoMode) {
autoMode=true;
Thread t1 = new Thread(SpielDesLebens.myself);
t1.start();
}
}
} // Ende innere Klasse
);
JButton stop = new JButton("Stop");
stop.setToolTipText("Stoppe Film");
stop.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
autoMode=false;
sleeptime=4000;
}
} // Ende innere Klasse
);
JPanel buttonPanel = new JPanel();
buttonPanel.add(naechste);
buttonPanel.add(auto);
buttonPanel.add(stop);
Container co;

if (!appletMode) co =f;
else co=this;

co.setLayout(new BorderLayout());
co.add(jp,BorderLayout.CENTER);
co.add(buttonPanel,BorderLayout.SOUTH);
co.setPreferredSize(new Dimension(size * (xRaster+3),size * (yRaster+3)));

if (!appletMode) {
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
}
}
/**
* Starten der Anwendung als eigenständiges Programm
* @param args werden nicht benutzt
*/
public static void main(String[] args) {
appletMode = false;
SpielDesLebens k = new SpielDesLebens();
}
/**
* Erzeugen eines JButtons für jede Zelle des Feldes
* @param xx x Koordinate im Feld
* @param yy y Koordinate im Feld
* @return einen Buttton mit ActionListener
*/
private JButton createButton(int xx, int yy) {
JButton myButton = new Zelle(freiIcon,xx,yy);
myButton.setToolTipText(("("+xx+","+yy+")"));
myButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
if(!autoMode) {
Zelle f = (Zelle) ae.getSource();
//System.out.println("Action auf" +f.x + " " + f.y);
boolean[][] g = gen.status();
if (g[f.x][f.y]) {
f.setIcon(freiIcon);
g[f.x][f.y]=false;
}
else {
f.setIcon(belegtIcon);
g[f.x][f.y]=true;
}
f.updateUI();
}
}
} // Ende innere Klasse
);
return myButton;
}
/**
* Erzeuge die beiden Ikonen für eine freies und ein belegtes Feld
*/
public final void erzeugeIcons() {
BufferedImage belegt =
new BufferedImage(xRaster, yRaster, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g = belegt.createGraphics();
g.setColor(Color.white);
g.fillRect(0, 0, xRaster-1, yRaster-1);
g.setColor(Color.black);
g.fillOval(1, 1, xRaster-2, yRaster-2);
g.dispose();
belegtIcon = new ImageIcon(belegt);
BufferedImage frei =
new BufferedImage(xRaster, yRaster, BufferedImage.TYPE_4BYTE_ABGR);
g = frei.createGraphics();
g.setColor(Color.white);
g.fillRect(0, 0, xRaster-1, yRaster-1);
g.dispose();
freiIcon = new ImageIcon(frei);
}

/**
* Erzeugen einer neuen Generation und Abgleich der JButtons mit neuen
* Ikonen
*/
private void nextGen() {
gen.neueGeneration();
boolean[][] stat = gen.status();
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++)
if (stat[i][j]) buttonFeld[i][j].setIcon(belegtIcon);
else buttonFeld[i][j].setIcon(freiIcon);
}

/**
* Lasse neue Generationen automatisiert in einem eigenen Thread
* erzeugen
*/
@Override
public void run() {
try {
while (autoMode) {
Thread.sleep(sleeptime);
nextGen();
}
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}

Lösung der Aufgabe in Zwischenschritten

1. Die Anwendung übersetzt und läuft fehlerfrei

  • Variable für Feldgröße als Objektvariable dekarieren und mit Konstante belegen 
    • Wert 5 wählen; Fenster per Hand vergrößern
  • Methode zur Rückgabe der Feldgröße implementieren
  • Zweidimensionales Feld als Objektvariable für aktuelles Feld deklarieren. Benutzen Sie den Typ boolean.
  • Im Konstruktor alle Zellen des Felds mit doppelt geschachtelter Schleife initialisieren
  • Methode zur Rückhabe des Felds implementieren
  • Methode neueGeneration() implementieren:
    • Trivialimplementierung die genau ein beliebiges aber festes Feldelement auf "true" setzt
  • Testen der Implementierung: Initialiserung des aktuellen Feldes kann so getestet werden

Ergebnis

Es wurde als Feldgröße 20 verwendet. Es wurde die Zelle [3,3] auf true gesetzt

Bildschirmausgabe
1. Nach Starten des Programms 2. Nach Klicken des ">" Button 3. Nach mehrfachem Kicken auf Zellen
nach Start Nach erstem Klick Nach dem Klicken auf Zellen

Der Benutzer sollte in der Lage sein, den Zustand von Zellen durch einfaches anklicken zu invertieren. Hier wurde im Schritt 3 ein "Happy Face" gezeichnet.

Die Position [3,3] sollte man jetzt auch mit einem Mausklick löschen können. Nach Klicken des ">" Button sollte das Pixel wieder gezeigt werden weil die Methode neueGeneration() aufgerufen wurde.

2. Zellen abhängig von anderen Zellen belegen: Methode neueGeneration()

Erweitern Sie die Methode neueGeneration()

  • Setzen Sie jedes Feldelement (x,y) auf "true" wenn das Element (x+1.y+1) belegt ("true") war. Hierdurch werden aus Punkten Striche die sich nach rechts unten fortpflanzen.
  • Sie benötigen hierfür eine doppelt geschachtelte Schleife die alle Feldelemente abarbeitet.
  • Achten Sie darauf, dass Sie keine Elemente auf Positionen die größer als die Feldgrenze sind!
  • Testen Sie die Anwendung: Jeder Punkt sollte in der Nachfolgegeneration einen neuen links oberhalb erhalten. Es steht pro Generation eine neue belegte Zelle links oberhalb.

Ergebnis

Es wurde als Feldgröße 20 verwendet. Es wurden Zellen nach dem Start des Programms mit der Maus markiert:

Bildschirmausgabe
1. Nach Starten des Programms und Markieren zweier Zellen 2. Nach Klicken des ">" Button 3. Nach zweitem Klicken des ">" Buttons
nach Start Nach erstem Klick Nach dem Klicken auf Zellen

3. Berechnen einer neuen Generation aus einer alten Generation

Man benötigt zu Lösung der Aufgabe zwei Felder. Das erste Feld enthält die Zellen der alten Generation. Das zweite Feld wird für die Belegung der neuen Generation benötigt. Mit nur einem Feld würde man nicht zwischen alter und neuer Generation entscheiden können. Man würde Zellen inkorrekt berechnen und belegen.

  • Deklarieren Sie eine weitere Objektvariable die auf das alte Feld zeigt
  • Initialisieren Sie das Feld in der gleichen Größe im Konstruktor. Belegen Sie alle Zellen mit dem Wert "false";
  • Erweitern Sie die Methode neueGeneration()
    • Referenzieren Sie mit dem Zeiger der alten Generation die aktuelle Generation.
    • Erzeugen sie ein Feld für die neue (aktuelle) Generation
    • Initialiseren Sie das neue Feld mit vernünftigen Werten.
    • Belegen Sie jedes Feld der neuen Generation mit "true" wenn der rechte, untere Nachbar der Vorgängergeneration existiert. Dieses Problem wurde schon in der vorgehenden Phase gelöst.
  • Testen Sie die Anwendung: Sie soll die gleichen Ausgaben produzieren
  • Setzen Sie die Größe des Felds wieder auf 50 (oder mehr)

Jetzt sollte das Umkopieren von neuen auf alte Generationen funktionieren. Alle Schleifen sollten fehlerfrei laufen.

4. Berechnen der korrekten Nachbarschaftsbeziehung in der Methode neueGeneration()

Erweitern Sie die Methode neueGeneration()

  • Zählen Sie für jedes Feld die Anzahl der Nachbarn. Achten Sie auf die Feldgrenzen. Prüfen Sie keine Feldelemente ab, die ausserhalb des Feldes liegen.
  • Bestimmen Sie anhand der Nachbarn und es dem Wert der alten Zelle den Zustand der aktuellen Zelle.

Ergebnis

Es wurde als Feldgröße 20 verwendet. Nach dem Start wurde mit der Maus ein "Glider", ein senkrechter Dreierbalken und ein Rechteck aus sechs Zellen gezeichnet.

Bildschirmausgabe
1. Nach Starten des Programms und Markieren diverser Zellen 2. Nach Klicken des ">" Button 3. Nach zweitem Klicken des ">" Buttons
nach Start Nach erstem Klick Nach dem Klicken auf Zellen

 7.4.5 Flughafenbeispiel mit Feldern

Klasse Flughafen

package airline.block7;

/**
*
* @author stsch
*/
public class Flughafen {
String name;
Flugzeug[] gate;
double treibstoffLager;

public Flughafen(int anzahlGates) {
gate = new Flugzeug[anzahlGates];
}

public void drucken() {
System.out.println("*** Unser Flughafen ***");
System.out.println("Flughafen " + name);
for (int i =0;i<gate.length;i++)
System.out.println("Am Gate " + i + ": " + gate[i]);
System.out.println("Treibstoff: " + treibstoffLager);
System.out.println("***********************");
}

public static void main(String[] args) {

Flughafen pad = new Flughafen(6);
pad.name="Paderborn";
pad.treibstoffLager = 1000000;

pad.drucken();

// Boeing 747, https://de.wikipedia.org/wiki/Boeing_747#747-400
Flugzeug lh1 = new Flugzeug(40000, 400000);
lh1.kennzeichen ="D-ABTL";
lh1.einsteigen(3);
System.out.println("Unsere grosse Gesellschaft" + Flugzeug.meineLG());

double aktuellesGewicht = lh1.gewicht();
System.out.println("aktuelle Gewicht von lh1: " + aktuellesGewicht);

pad.gate[1] = lh1;

// Airbus A380 https://de.wikipedia.org/wiki/Airbus_A380#A380-800
Flugzeug lh2 = new Flugzeug(40000, 400000, "D-AIMA");

lh2.einsteigen(11);
lh2.einsteigen();
lh2.einsteigen(4);
// Wir wollen wieder austteigen
lh2.aussteigen(5);

pad.gate[2] = lh2;

System.out.println("Flughafen " + pad.name);
System.out.println("Am Gate 1: " + pad.gate[1].kennzeichen +
" Passagiere: " + pad.gate[1].getPassagiere() +
" akt. Gewicht: " + pad.gate[1].gewicht());
System.out.println("Am Gate 2: " + pad.gate[2].kennzeichen +
" Passagiere: " + pad.gate[2].getPassagiere() +
" akt. Gewicht: " + pad.gate[2].gewicht());
pad.drucken();

}
}

Klasse Flugzeug

package s1.airline.block7;

/**
* Das ist ein Flugzeug des 7.ten Blocks
* @author s@scalingbits.com
*/
public class Flugzeug {

final static double durchschnittsgewicht = 75;
String kennzeichen;
private int passagiere;
int maxPassagiere = 100;
final double maximalesGewicht;
final double leerGewicht;

public int getPassagiere() {
return passagiere;
}

public Flugzeug(double minGewicht, double maxGewicht) {
System.out.println("Ich baue jetzt ein Flugzeug");
if (minGewicht > 0) leerGewicht = minGewicht;
else leerGewicht = 0;
if ((maxGewicht > 0) && (maxGewicht>=leerGewicht))
maximalesGewicht = maxGewicht;
else maximalesGewicht = leerGewicht;
passagiere = 0;
}

public Flugzeug(double minGewicht, double maxGewicht, String kennz) {
this(minGewicht,maxGewicht);
kennzeichen = kennz;
}

/**
* Einsteigen eines einzelnen Passagiers
*/
public void einsteigen() {
if (passagiere >= maxPassagiere) { // Zuviele Einsteiger
System.out.println("Fehler: Einsteigen verweigert ");
} else { // passt schon
passagiere++;
}
}

/**
* Einsteigen einer vorgegebenen Anzahl Passagiere.
* und sie funktioniert auch!
* Wenn zuviele einsteigen möchten, darf keiner einsteigen!
* @param einsteiger Anzahl der Passagiere die einsteigen.
*/
public void einsteigen(int einsteiger) {
if (passagiere+einsteiger > maxPassagiere) {
System.out.println("Fehler: Einsteigen verweigert ");
} else {
System.out.println("Ich lasse " + einsteiger + " Passagiere eingestiegen");
einsteigen(); // Einer steigt ein
if (einsteiger > 1)
einsteigen(einsteiger-1); //Der Rest steigt ein
}
}

public void aussteigen(final int aussteiger) {
if (passagiere >= aussteiger) {
passagiere -= aussteiger;
} else {
System.out.println("Fehler: Flugzeug ist leer... ");
}
} // Ende der Methode aussteigen

/**
* berechnet das aktuelle Gewicht des Flugzeugs
* @return aktuelle Gewicht
*/
public double gewicht() {
//double g = leerGewicht+passagiere*durchschnittsgewicht;
return leerGewicht+passagiere*durchschnittsgewicht;
}

public static String meineLG() { return "Lufthansa";}

}
 

 

Stefan Schneider Mon, 10/11/2010 - 18:54

7.5 Lösungen

7.5 Lösungen

7.5.1 Telefonbuchanwendung (1)

package s1.block7;
/**
*
* @author s@scalingbits.com
*/
public class Telefonbuch1 {
private String[] vorname;
private String[] nachname;
private String[] telefonnummer;
/**
* Anlegen eines Telefonbuchs für 4 Einträge
*/
public Telefonbuch1 () {
// Telefonbuch mit initial 4 Einträgen
vorname = new String[4];
nachname = new String[4];
telefonnummer = new String[4];
}
/**
* Einfügen einer neuen Telefonnummer mit automatischem
* Vergrössern um 50% des Telefonbuchs
* @param vn Vorname
* @param nn Nachname
* @param nr Telefonnummer
*/
public void einfuegen(String vn, String nn, String nr) {
//Leere Einträge haben keine Telefonummer!
int pos=0; //Suchposition
while ((pos<telefonnummer.length)
&& !(telefonnummer[pos]==null)
) pos++;
if (pos>=telefonnummer.length) // kein freier Eintrag!
{ // Feld um 50% vergroessern und alles umkopieren
String[] tempFeld;
tempFeld = new String[vorname.length*3/2];
System.arraycopy(vorname,0,tempFeld,0,vorname.length);
vorname = tempFeld;

tempFeld = new String[nachname.length*3/2];
System.arraycopy(nachname,0,tempFeld,0,nachname.length);
nachname = tempFeld;

tempFeld = new String[telefonnummer.length*3/2];
System.arraycopy(telefonnummer,0,tempFeld,0,telefonnummer.length);
telefonnummer = tempFeld;
// Jetzt ist Platz um etwas pos zu speichern!
}
vorname[pos]= vn;
nachname[pos]= nn;
telefonnummer[pos] = nr;
}
/**
* Loeschen eines Datensatzes wenn alle Parameter identisch sind
* @param vn vorname
* @param nn Nachname
* @param nr Vorname
*/
public void loesche(String vn, String nn, String nr) {
//Leere Einträge haben keine Telefonummer!
int pos=0; //Suchposition
while ((pos<telefonnummer.length)
&& (telefonnummer[pos]!=null)
&& !(telefonnummer[pos].equals(nr))
&& !(vorname[pos].equals(vn))
&& !(nachname[pos].equals(nn))
) pos++;
if (pos<telefonnummer.length) // Kandidat zum loeschen steht aus pos
{ // Suche hoechsten Eintrag
int loesche = pos;
while ((pos<telefonnummer.length)
&& (telefonnummer[pos]!=null)
) pos++;
pos--; // Einmal zurücksetzen
// Höchsten Datensatz umkopieren und dann ausnullen
// Der alte Datensatz wird dereferenziert
vorname[loesche] = vorname[pos];
vorname[pos] = null;
nachname[loesche] = nachname[pos];
nachname[pos] = null;
telefonnummer[loesche] = telefonnummer[pos];
telefonnummer[pos]=null;
}
}
/**
* Ausdrucken des Telefonbuchs
*/
public void drucken() {
System.out.println("Telefonbuch. Groesse: " + telefonnummer.length);
for (int i=0; i<telefonnummer.length; i++ ){
System.out.print("[" + i + "]: ");
System.out.print( vorname[i] + " | ");
System.out.print( nachname[i] + " | ");
System.out.println( telefonnummer[i] + " |");
}
}
/**
* Testroutine
*/
public static void test() {
Telefonbuch1 buch = new Telefonbuch1();
System.out.println("*** Leeres Telefonbuch ***");
buch.einfuegen("Manuel","Neuer","0171 1");
buch.einfuegen("Philipp","Lahm","0171 2");
buch.einfuegen("Jérome","Boateng","0171 3");
buch.einfuegen("Mats","Hummels","0171 4");
buch.einfuegen("Benedikt","Höwedes","0171 5");
buch.einfuegen("Christoph","Kramer","0171 6");
buch.einfuegen("Bastian","Schweinsteiger","0171 8");
buch.einfuegen("Thomas","Müller","0171 9");
buch.einfuegen("Toni","Kroos","0171 10");
buch.einfuegen("Per","Mertesacker","0171 11");
buch.einfuegen("Miroslav","Klose","017 12");
//
System.out.println("*** Ganze Mannschaft im Telefonbuch ***");
buch.drucken();
System.out.println("*** Kramer raus, Schürrle rein ***");
buch.loesche("Christoph","Kramer","0171 6");
buch.einfuegen("André","Schürrle","0171 7");
buch.drucken();
System.out.println("*** Klose raus, Götze rein ***");
buch.einfuegen("Miroslav","Klose","017 12");
buch.einfuegen("Mario","Götze","0171 13");
buch.drucken();
System.out.println("... und Weltmeister");
}
/**
* Hauptprogramm
* @param args
*/
public static void main(String[] args) {
test();
}
}

7.5.2 Telefonbuch (2)

Klasse Person

package s1.block7;
/**
*
* @author s@scalingbits.com
*/
public class Person {
final public String vorname;
final public String nachname;
final public String telefonnummer;
/**
* Der Konstruktor erlaubt das Belegen der Attribute. Sie können
* spaeter nicht mehr geändert werden
* @param vn Vorname
* @param nn Nachname
* @param nr Telefonnummer
*/
public Person (String vn, String nn, String nr) {
vorname = vn;
nachname = nn;
telefonnummer = nr;
}
/**
* Standardisierte Vergeleichsoperation in Java
* @param o Das Objekt mit dem verglichen werden soll
* @return wahr wenn Objekte gleich sind
*/
@Override
public boolean equals(Object o) {
Person p = (Person) o;
return ((vorname.equals(p.vorname))
&&(nachname.equals(p.nachname))
&&(telefonnummer.equals(p.telefonnummer)));
}
/**
* Standardisierte Methode zum Konvertieren eines Objekts in eine
* Zeichenkett
* @return Das Objekt in einer Repräsentation als Zeichenkette
*/
@Override
public String toString(){
return (" " +vorname + " | " + nachname + " | " + telefonnummer +" |");
}
}

Klasse Telefonbuch2 (Hauptprogramm)

package s1.block7;
/**
 *
 * @author s@scalingbits.com
 */
public class Telefonbuch2 {
    private Person[] leute;
    /**
     * Anlegen eines Telefonbuchs für 4 EInträge
     */
    public Telefonbuch2 () {
        // Telefonbuch mit initial 4 Einträgen
        leute = new Person[4];
    }
    /**
     * Einfügen einer neuen Telefonnummer mit automatischem
     * Vergrössern um 50% des Telefonbuchs
     * @param p Person
     */
    public void einfuegen(Person p) {
        //Leere Einträge haben keine Telefonummer!
        int pos=0; //Suchposition
        while ((pos<leute.length)
               && (leute[pos]!=null)
                ) pos++;
        if (pos>=leute.length) // kein freier Eintrag!
        { // Feld um 50% vergroessern und alles umkopieren
            Person[] tempFeld; 
            tempFeld = new Person[leute.length*3/2];
            System.arraycopy(leute,0,tempFeld,0,leute.length);
            leute = tempFeld;
            // Jetzt ist Platz um etwas pos zu speichern!
        }
        leute[pos]= p;
    }
    /**
     * Loeschen eines Datensatzes wenn alle Parameter identisch sind
     * @param p zu löschende Person
     */
    public void loesche(Person p) {
        //Leere Einträge haben keine Telefonummer!
        int pos=0; //Suchposition
        while ((pos<leute.length) // Noch nicht am Ende des Feldes
                && (leute[pos]!=null) // Es gibt einen Eintrag
                && !(leute[pos].equals(p)) ) // Er passt nicht
            pos++;
        if (pos<leute.length) // Kandidat zum loeschen steht aus pos
        { // Suche hoechsten Eintrag
            int loesche = pos;
            while ((pos<leute.length)
               && (leute[pos]!=null)
                    ) pos++;
            pos--; // Einmal zurücksetzen
            // Höchsten Datensatz umkopieren und dann ausnullen
            // Der alte Datensatz wird dereferenziert
            leute[loesche] = leute[pos];
            leute[pos] = null;
        }
    }
    /**
     * Ausdrucken des Telefonbuchs
     */
    public void drucken() {
        System.out.println("Telefonbuch. Groesse: " + leute.length);
        for (int i=0; i< leute.length; i++)
            System.out.println("[" + i + "]: " +leute[i]);
    }
    /**
     * Testroutine
     */
    public static void test() {
        Telefonbuch2 buch = new Telefonbuch2();
        System.out.println("*** Leeres Telefonbuch ***");
        buch.einfuegen(new Person("Manuel","Neuer","0171 1"));
        buch.einfuegen(new Person("Philipp","Lahm","0171 2"));
        buch.einfuegen(new Person("Jérome","Boateng","0171 3"));
        buch.einfuegen(new Person("Mats","Hummels","0171 4"));
        buch.einfuegen(new Person("Benedikt","Höwedes","0171 5"));
        buch.einfuegen(new Person("Christoph","Kramer","0171 6"));
        buch.einfuegen(new Person("Bastian","Schweinsteiger","0171 8"));
        buch.einfuegen(new Person("Thomas","Müller","0171 9"));
        buch.einfuegen(new Person("Toni","Kroos","0171 10"));
        buch.einfuegen(new Person("Per","Mertesacker","0171 11"));
        buch.einfuegen(new Person("Miroslav","Klose","017 12"));
        //
        System.out.println("*** Ganze Mannschaft im Telefonbuch ***");
        buch.drucken();
        System.out.println("*** Kramer raus, Schürrle rein ***");
        buch.loesche(new Person("Christoph","Kramer","0171 6"));
        buch.einfuegen(new Person("André","Schürrle","0171 7"));
        buch.drucken();
        System.out.println("*** Klose raus, Götze rein ***");
        buch.einfuegen(new Person("Miroslav","Klose","017 12"));
        buch.einfuegen(new Person("Mario","Götze","0171 13"));
        buch.drucken();
        System.out.println("... und Weltmeister");
    }
    /**
     * Hauptprogramm
     * @param args 
     */
    public static void main(String[] args) {
    test();
    }

7.5.3 Zufallszahlengenerator

package s1.block7;
/**
 *
 * @author s@scalingbits.com
 */

public class Zufallszahlen {
/**
* Drucke dreiminensionale Felder
* @param feld dieses Feld wird gedruckt
*/
public static void feldDrucken(int[][][] feld) {
for (int i=0; i<feld.length; i++) {
System.out.println("*** Kubusebene["+i+"] ***");
feldDrucken(feld[i]);
}
}
/**
* Drucke zweidimensionale Felder
* @param feld dieses Feld wird gedruckt
*/
public static void feldDrucken(int[][] feld) {
for (int i=0; i<feld.length; i++) {
System.out.print("["+i+"]: ");
feldDrucken(feld[i]);
System.out.println(""); // Zeilenumbruch provozieren
}
}
/**
* Drucke eindinensionale Felder
* @param feld dieses Feld wird gedruckt
*/
public static void feldDrucken(int[] feld) {
for (int i=0; i<feld.length; i++) {
System.out.print(" "+feld[i]+" |"); // kein Zeilenumbruch
}
}
/**
* Suche die am häufigsten vorkommende Zahl
* @param feld Feld mit Häufigkeiten
* @return haeufigste Zahl im Feld
*/
public static int haeufigsteZahl(int[][][] feld) {
int max = -1;
int ergebnis = 0;
for (int i=0; i<feld.length; i++)
for (int j=0; j<feld[i].length; j++)
for (int k=0; k<feld[i][j].length;k++)
if (feld[i][j][k] > max) {
max = feld[i][j][k];
ergebnis=i*100+j*10+k;
}
System.out.println("Häufigste Vorkommen: " + max);
return ergebnis;
}
/**
* Suche die am seltensten vorkommende Zahl
* @param feld Feld mit Häufigkeiten
* @return das Eregebnis
*/
public static int seltensteZahl(int[][][] feld) {
int min = Integer.MAX_VALUE;
int ergebnis = 0;
for (int i=0; i<feld.length; i++)
for (int j=0; j<feld[i].length; j++)
for (int k=0; k<feld[i][j].length;k++)
if (feld[i][j][k] < min) {
min = feld[i][j][k];
ergebnis=i*100+j*10+k;
}
System.out.println("Seltenstes Vorkommen: " + min);
return ergebnis;
}
public static void main(String[] args) {
int sampleSize = 1000000;
int[] sample = new int[sampleSize];
System.out.println("Feld mit " + sampleSize + " Zellen angelegt." );
for (int i=0; i<1000000; i++)
sample[i] = (int)(Math.random()* 1000D);
System.out.println("Feld mit " + sampleSize + " Zufallszahlen belegt." );
int[][][] verteilung = new int[10][10][10];
for (int wert: sample) {
verteilung[(wert/100)%10][(wert/10)%10][wert%10]++;
}
System.out.println("Verteilungsfeld belegt mit " + sampleSize + " Zufallszahlen." );
feldDrucken(verteilung);
System.out.println("Suche häufigst vorkommende Zahl");
System.out.println("Häufigste Zahl " + haeufigsteZahl(verteilung));
System.out.println("Suche seltenst vorkommende Zahl");
System.out.println("Seltenste Zahl " + seltensteZahl(verteilung));
}
}

7.5.4 Conway's Spiel des Lebens

package s1.block7;

/*
* @author scalingbits.com
*/
public class GenerationLoesung {
/**
* Groesse des quadratischen Feldes
*/
private int size = 50;
private boolean[][] alt;
private boolean[][] aktuell;

/**
* Anlegen aller benoetigten Felder mit Initialwerten
* Alle Feldelemente sollen mit dem Zustand "false" = leer versehen sein
*/
public GenerationLoesung() {
aktuell = new boolean[size][size];
alt = new boolean[size][size];
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++) {
aktuell[i][j] = false;
alt[i][j] = false;
}
}

/**
* @return Kantenlaenge des quadratischen Felds
*/
public int groesse() {
return size;
}

/**
* Berechnen einer neuen Generation.
* Legen Sie ein neues Feld an. Berechnen Sie den neuen Zustand
* aller Feldelement aus dem alten Feld
*/
void neueGeneration() {
alt = aktuell;
aktuell = new boolean[size][size];
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++) {
aktuell[i][j] = false;
// Zaehle Nachbarn
int nachbar = 0;
if ((i > 0) && alt[i - 1][j]) nachbar++; //links
if ((i + 1 < size) && alt[i + 1][j]) nachbar++; //rechts
if ((j > 0) && alt[i][j - 1]) nachbar++; //oben
if ((j + 1 < size) && alt[i][j + 1]) nachbar++; //unten
if ((i > 0) && (j > 0) && alt[i - 1][j - 1]) nachbar++; //links,oben
if ((i > 0) && (j + 1 < size) && alt[i - 1][j + 1]) nachbar++; //links, unten
if ((i + 1 < size) && (j > 0) && alt[i + 1][j - 1]) nachbar++; //rechts, oben
if ((i + 1 < size) && (j + 1 < size) && alt[i + 1][j + 1]) nachbar++; //rechts, unten

// Übernehmen des alten Status als Default
aktuell[i][j] = alt[i][j];
// Geburt einer neuen Zelle
if ((!alt[i][j]) && (nachbar == 3)) aktuell[i][j] = true;
// Tod einer alten Zelle wegen Einsamkeit
if ((alt[i][j]) && (nachbar < 2)) aktuell[i][j] = false;
// Tod einer alten Zelle wegen Überbevölerung
if ((alt[i][j]) && (nachbar > 3)) aktuell[i][j] = false;
}
}

/**
* Das Feld mit den aktuellen Werten
*
* @return
*/
public boolean[][] status() {
return aktuell;
}
}

 7.5.5 Flughafenbeispiel aus der Vorlesung

Mit einem Feld eingebaut

Flughafen

package s1.airlineSolution.block7;
public class Flughafen {
String name;

Flugzeug[] gate;
double treibstoffLager;

/**
*
* @param name Name des Flugzeuge
* @param gates Anzahl der Gates
*/
public Flughafen(String name, int gates) {
this.name = name;
gate = new Flugzeug[gates];
}


public static void main(String[] args) {


Flughafen pad = new Flughafen("Paderborn",6);
pad.treibstoffLager = 1000000;


// Boeing 747, https://de.wikipedia.org/wiki/Boeing_747#747-400
Flugzeug lh1 = new Flugzeug("ABTL",450000,200,200);
lh1.einsteigen(120);

double aktGewicht=lh1.gewicht();
System.out.println("gewicht" + aktGewicht);

lh1.drucken();

pad.gate[1] = lh1;
pad.gate[2] = lh1;
System.out.println("Boarding für lh1 nach Mannheim...");
pad.gate[1].einsteigen(17);
pad.gate[1].einsteigen(2);
pad.gate[2].einsteigen();
lh1.einsteigen(2);

lh1.drucken();

// Airbus A380 https://de.wikipedia.org/wiki/Airbus_A380#A380-800
Flugzeug lh2 = new Flugzeug("ABTL",500000,100,200);

lh2.einsteigen(100);

lh2.drucken();

pad.gate[2] = lh2;

pad.drucken();

// Hänge Flugzeug um. mover bewegt Flugzeug
// von Gate 1 nach Gate 3

Flugzeug mover = pad.gate[1];
pad.gate[1]=null;

pad.drucken();

pad.gate[3]= mover;
mover=null;

}

/**
* druckt alle wichtigen Informationen ueber einen Flughafen auf die Konsole
*/
public void drucken() {
System.out.println("*** Unser Flughafen ***");
System.out.println("Flughafen " + name);
for (int i=0; i<gate.length; i++) {
if (gate[i] != null)
System.out.println("Am Gate " + i +": " + gate[i]);
else
System.out.println("Gate " + i +" unbelegt");
}
System.out.println("Treibstoff: " + treibstoffLager);
System.out.println("***********************");
}
}

Flugzeug

package s1.airlineSolution.block7;
public class Flugzeug {

public String kennzeichen; // Ein Attribut vom Typ einer Zeichenkette
// 1. Privates Attribut zur Verwaltung der Passagierkapazität
// Tipp: Untersuchen Sie die Druckmethode zur Wahl der
// Variablennamen (1-5)!
private int maxPassagiere;
// 2. Privates Attribut zur Verwaltung der aktuellen Pasagiere
private int passagiere;
// 3. Leergewicht in privates Attribut ändern
public int leergewicht; // Ein Attribut vom Type einer Ganzzahl
// 4. Maximales Gewicht des Flugzeugs
private int maxgewicht;
// 5. Öffentliche Konstante für durchschn. Passagiergewicht
public final int PASSAGIERGEWICHT = 85;

// Anzahl aller erzeugten Flugzeuge
private static int objekte;

/**
* 8. Konstruktor implementieren
* Konstruktur der Klasse Flugzeug
* @param kennz Kennzeichen des Flugzeugs
* @param kapazitaet Passagierkapazität
* @param leergew Leergewicht in kg
* @param maxgew Maximalgewicht in kg
*/
public Flugzeug(String kennz, int kapazitaet, int leergew, int maxgew) {
kennzeichen = kennz;
objekte++;
// Prüfen ob Kapazität größere Null ist
if (kapazitaet >= 0) {
maxPassagiere = kapazitaet;
} else {
maxPassagiere = 0;
}
// Prüfen ob Leergewicht größer Null ist
if (leergew > 0) {
leergewicht = leergew;
} else {
leergewicht = 0;
}
// Prüfen ob Maximalgewicht größer-gleich Leergeicht ist.
if (maxgew > leergewicht) {
maxgewicht = maxgew;
} else {
maxgewicht = leergewicht; // Viel Spass...
}
}

/**
* 10. Fügt einen Passagier zum aktuellen Flugzeug hinzu
*/
public void einsteigen() {
if (passagiere < maxPassagiere) {
passagiere++;
}
}

/**
*
* @param anzahl Anzahl der Passagiere die einsteigen sollen
*/
public void einsteigen(int anzahl) {
if ((anzahl >0) && (passagiere+anzahl) <= maxPassagiere) {
passagiere+= anzahl;
}
}

/**
* 11. Entfernt einen Passagier des aktuellen Flugzeugs
*/
public void aussteigen() {
if (passagiere > 0) {
passagiere--;
}
}

/**
*
* @param anzahl Anzahl der Passagiere die aussteigen sollen
*/
public void aussteigen(int anzahl) {
if ((anzahl >0) && (passagiere-anzahl) >=0) {
passagiere-= anzahl;
}
}

/**
* 12. Ausgabe der aktuellen Anzahl der Passagiere
* @return aktuelle Anzahl der Passagiere
*/
public int anzahlPassagiere() {return passagiere;}


/**
* 6. Berechnen des aktuellen Gewichts
* @return aktuelles Gewicht
*/
public int gewicht() {
return (leergewicht+ passagiere*PASSAGIERGEWICHT);}

/**
* 13. Ausgabe der maximalen Anzahl der Passagiere
* @return Maximale Anzahl der Passagiere
*/
public int passagierkapazitaet() {return maxPassagiere;}

/**
*
* @return Anzahl aller erzeugten Objekte der Klasse Flugzeug
*/
public static int anzahlFlugzeuge() {return objekte;}

/**
* Eine Methode zum Drucken der Attributbelegung des Objekts
* Die Methode erfordert keine Eingaben. Sie erzeugt keine
* Ausgaben
*/
public void drucken() {
// 7. Vervollständigen der Druckmethode
System.out.println("*****************************");
System.out.println("Kennzeichen: " + kennzeichen);
System.out.println("Leergewicht: " + leergewicht + "kg");
System.out.println("Maximalgewicht: " + maxgewicht + "kg");
System.out.println("Aktuelles Gewicht : " + gewicht() + "kg");
System.out.println("Passagiere: " + passagiere);
System.out.println("Maximal Anzahl P.: " + maxPassagiere);
System.out.println("******************** " + objekte + " Flugz.");
}

/**
* Ueberschriebene Methode die das Kennzeichen anstatt der Objektidentitaet
* druckt
* @return
*/
public String toString() {return kennzeichen;}

}

 

Stefan Schneider Sat, 12/03/2011 - 22:15

7.6 Lernziele

7.6 Lernziele

Am Ende dieses Blocks können Sie:

  • ... die Javasyntax zum Umgang mit ein- und mehrdimensionalen Feldern beschreiben und anwenden.
  • ... die Lebensdauer eines Feldes und seiner Unterobjekte bestimmen.
  • ... die Index eines Felds benutzen um Daten zu lesen und zu schreiben.
  • ... die Länge eines Felds bstimmern und Unter- bzw. Überläufe beim Zugriff auf das Feld vermeiden.
  • ... das Objektmodell von Feldern bei Zuweisungen und Kopien von Feldern und Feldvariablen erklären und anwenden.
  • ... Felder als Parameter von Methoden benutzen und das "Call by Reference" Prinzip bei deren Übergabe erklären.
  • ... Methoden implementieren und nutzen die eine variable Anzahl von Argumenten besitzen
  • ... mit mehrdimensionalen Feldern umgehen (initialisieren, auslesen, belegen, Über- und Unterläufe vermeiden)

Lernzielkontrolle

Sie sind in der Lage die Fragen zu Feldern zu beantworten.

Feedback

Zur Umfrage

QR Code für Umfrage

Stefan Schneider Thu, 09/27/2012 - 12:18