Javakurs/Übungsaufgaben/DiffusionLimitedAggregation/Musterlösung: Unterschied zwischen den Versionen
Erscheinungsbild
K ein paar Kommentare geändert |
K fix alignment |
||
| Zeile 3: | Zeile 3: | ||
public class DLA { | public class DLA { | ||
public static void main(String[] args) { | public static void main(String[] args) { | ||
//Feld erstellen, in dem gespeichert wird, ob an gegebenen Koordinaten ein Partikel ist | // Feld erstellen, in dem gespeichert wird, ob an gegebenen Koordinaten | ||
// ein Partikel ist | |||
int[][] field = new int[400][400]; | int[][] field = new int[400][400]; | ||
//Maximalwerte fuer Koordinaten der Partikel, lassen sich aus den Dimensionen von field berechnen (.length verwenden) | // Maximalwerte fuer Koordinaten der Partikel, lassen sich aus den | ||
// Dimensionen von field berechnen (.length verwenden) | |||
int maxX = field.length; | int maxX = field.length; | ||
int maxY = field[0].length; | int maxY = field[0].length; | ||
| Zeile 19: | Zeile 20: | ||
drawPad.setColor(Pad.white); | drawPad.setColor(Pad.white); | ||
// "Samen" erzeugen, also den ersten Pixel aufs Feld setzen (Color: Pad.white) | // "Samen" erzeugen, also den ersten Pixel aufs Feld setzen (Color: | ||
// Pad.white) | |||
// Hier: Pixel wird genau in die Mitte des Feldes gesetzt - andere | |||
// Startpixel waeren moeglich | |||
setPixel(drawPad, field, maxX / 2, maxY / 2, Pad.white); | setPixel(drawPad, field, maxX / 2, maxY / 2, Pad.white); | ||
// Abstand des Partikels, der am weitesten vom Zentrum des Feldes | |||
// entfernt ist | |||
int maxR = 0; | int maxR = 0; | ||
// Falls der Startpunkt auch ein anderer sein kann als das Zentrum des | |||
// Feldes: | |||
// Berechne fuer alle bereits vorhandenen Partikel den Abstand zum | |||
// Zentrum des Feldes | |||
// speichere das Maximum dieser Abstaende in maxR | |||
for (int x = 0; x < maxX; x++) { | for (int x = 0; x < maxX; x++) { | ||
for (int y = 0; y < maxY; y++) { | for (int y = 0; y < maxY; y++) { | ||
if (testPixel(field, x, y)) { | if (testPixel(field, x, y)) { | ||
maxR = (int) Math.max(maxR, Math.sqrt(Math.pow((x - maxX / 2), 2) + Math.pow((y - maxY / 2), 2))); | |||
maxR = (int) Math.max(maxR, Math.sqrt(Math.pow( | |||
} | } | ||
} | } | ||
} | } | ||
//Abbruchbedingung: Hat einer der Partikel sich aus dem Feld heraus bewegt? | // Abbruchbedingung: Hat einer der Partikel sich aus dem Feld heraus | ||
// bewegt? | |||
boolean isAtBorder = false; | boolean isAtBorder = false; | ||
//Schleife: Erstelle solange neue Partikel, wie die Abbruchbedingung false ist | // Schleife: Erstelle solange neue Partikel, wie die Abbruchbedingung | ||
// false ist | |||
while (!isAtBorder) { | while (!isAtBorder) { | ||
// auf einem gedachten Kreis um den Mittelpunkt mit Radius maxR + 20 einen Partikel "erzeugen" | // auf einem gedachten Kreis um den Mittelpunkt mit Radius maxR + 20 | ||
// einen Partikel "erzeugen" | |||
// d.h. die Koordinaten eines zufaelligen Punktes auf dem Kreisrand | |||
// berechnen | |||
// neuer Partikel ist somit an Position movingPixelX ; movingPixelY | |||
double x = Math.random() * 360; | double x = Math.random() * 360; | ||
int movingPixelX = limit((int) (Math.cos(x) * (maxR + 20)) + maxX | int movingPixelX = limit((int) (Math.cos(x) * (maxR + 20)) + maxX / 2, 0, maxX); | ||
int movingPixelY = limit((int) (Math.sin(x) * (maxR + 20)) + maxY / 2, 0, maxY); | |||
int movingPixelY = limit((int) (Math.sin(x) * (maxR + 20)) + maxY | |||
// Nun Start der brownschen Bewegung | |||
// Partikel bewegt sich, bis er einen bereits vorhandenen Partikel | |||
// beruehrt oder bis er das Feld verlaesst | |||
while (!isTouching(field, movingPixelX, movingPixelY) && inRange(movingPixelX, movingPixelY, maxR + 30, maxX, maxY)) { | |||
while (!isTouching(field, movingPixelX, movingPixelY) | |||
// zufaelliges Verschieben des Partikels um +/- 1 Pixel mit | |||
// moveRandom | |||
movingPixelX = moveRandom(movingPixelX); | movingPixelX = moveRandom(movingPixelX); | ||
movingPixelY = moveRandom(movingPixelY); | movingPixelY = moveRandom(movingPixelY); | ||
} | } | ||
// Brownsche Bewegung zu Ende - Ist Partikel auf einen bereits vorhandenen Partikel gestossen? | // Brownsche Bewegung zu Ende - Ist Partikel auf einen bereits | ||
// vorhandenen Partikel gestossen? | |||
if (isTouching(field, movingPixelX, movingPixelY)) { | if (isTouching(field, movingPixelX, movingPixelY)) { | ||
// Wenn ja: Partikel ist jetzt "fest" an dieser Stelle, zeichne | |||
// einen Punkt dort | |||
// Farbwertberechnung fuer 1337 blau-Effekt | // Farbwertberechnung fuer 1337 blau-Effekt | ||
int k = limit( | int k = limit(255 - (int) (255 * ((double) maxR * 2) / (double) maxX), 0, 255); | ||
Color c = new Color(255, k, k); | Color c = new Color(255, k, k); | ||
| Zeile 79: | Zeile 84: | ||
setPixel(drawPad, field, movingPixelX, movingPixelY, c); | setPixel(drawPad, field, movingPixelX, movingPixelY, c); | ||
// Abstand des neu gesetzten Partikels zum Mittelpunkt des Feldes berechnen | // Abstand des neu gesetzten Partikels zum Mittelpunkt des | ||
// wenn groesser als alter maximaler Abstand maxR, dann Maximum mit neuem Abstandswert ueberschreiben | // Feldes berechnen | ||
maxR = (int) Math.max(maxR, Math.sqrt(Math.pow( | // wenn groesser als alter maximaler Abstand maxR, dann Maximum | ||
// mit neuem Abstandswert ueberschreiben | |||
maxR = (int) Math.max(maxR, Math.sqrt(Math.pow(((double) movingPixelX - (double) maxX / 2), 2) + Math.pow(((double) movingPixelY - (double) maxY / 2), 2))); | |||
// Falls der Partikel das Feld verlassen hat: Zeichnung ist | |||
// fertig, setze Abbruchkriterium der aeusseren Schleife auf | |||
if (movingPixelX - 1 <= 0 || movingPixelX + 1 >= maxX | // true | ||
if (movingPixelX - 1 <= 0 || movingPixelX + 1 >= maxX || movingPixelY - 1 <= 0 || movingPixelY + 1 >= maxY) { | |||
isAtBorder = true; | isAtBorder = true; | ||
} | } | ||
| Zeile 98: | Zeile 103: | ||
} | } | ||
public static void setPixel(Pad drawPad, int[][] field, int x, int y, Color c) { | |||
/** | |||
public static void setPixel(Pad drawPad, int[][] field, int x, int y, | * Pruefe, ob sich der Partikel an Koordinaten (x,y) innerhalb des | ||
* Feldes befindet Wenn ja, speichere ihn fest im Feld an dieser Stelle | |||
* zeichne dort einen Punkt | |||
*/ | |||
if (x > 0 && y > 0 && x < field.length - 1 && y < field[0].length - 1) { | if (x > 0 && y > 0 && x < field.length - 1 && y < field[0].length - 1) { | ||
field[x][y] = 1; | field[x][y] = 1; | ||
drawPad.setColor(c); | drawPad.setColor(c); | ||
drawPad.drawDot(x, y); | drawPad.drawDot(x, y); | ||
| Zeile 132: | Zeile 132: | ||
*/ | */ | ||
public static boolean inRange(int x, int y, int maxR, int maxX, int maxY) { | public static boolean inRange(int x, int y, int maxR, int maxX, int maxY) { | ||
// Mittelpunkt des Rechtecks ausrechen | // Mittelpunkt des Rechtecks ausrechen | ||
int middleX = maxX / 2; | int middleX = maxX / 2; | ||
int middleY = maxY / 2; | int middleY = maxY / 2; | ||
// Der Abstand vom Mittelpunkt sqrt(a² + b²) mit Hilfe der in Java | // Der Abstand vom Mittelpunkt sqrt(a² + b²) mit Hilfe der in Java | ||
// intigrierten Klasse "Math" | // intigrierten Klasse "Math" | ||
int distance = (int) Math.sqrt(Math.pow((x - middleX), 2) | int distance = (int) Math.sqrt(Math.pow((x - middleX), 2) + Math.pow((y - middleY), 2)); | ||
if (distance < maxR) { | if (distance < maxR) { | ||
return true; | return true; | ||
} | } | ||
return false; | return false; | ||
} | } | ||
| Zeile 161: | Zeile 156: | ||
*/ | */ | ||
public static boolean isTouching(int[][] field, int x, int y) { | public static boolean isTouching(int[][] field, int x, int y) { | ||
// ist eigentlich unschön, in diesem Fall aber wesentlich einfacher zu | // ist eigentlich unschön, in diesem Fall aber wesentlich einfacher zu | ||
// lesen und zu verstehen | // lesen und zu verstehen | ||
| Zeile 170: | Zeile 164: | ||
return true; | return true; | ||
} | } | ||
return false; | return false; | ||
} | } | ||
| Zeile 193: | Zeile 184: | ||
y = limit(y, 0, field[0].length - 1); | y = limit(y, 0, field[0].length - 1); | ||
// länge des zweiten arrays | // länge des zweiten arrays | ||
if (field[x][y] > 0) { | if (field[x][y] > 0) { | ||
return true; | return true; | ||
} | } | ||
return false; | return false; | ||
} | } | ||
| Zeile 213: | Zeile 202: | ||
*/ | */ | ||
public static int limit(int value, int lower, int upper) { | public static int limit(int value, int lower, int upper) { | ||
if (value < lower) { | if (value < lower) { | ||
return lower; | return lower; | ||
} | } | ||
if (value > upper) { | if (value > upper) { | ||
return upper; | return upper; | ||
} | } | ||
return value; | return value; | ||
} | } | ||
| Zeile 233: | Zeile 219: | ||
*/ | */ | ||
public static int moveRandom(int movePixel) { | public static int moveRandom(int movePixel) { | ||
// erstelle eine random-Zahl zwischen 1 und | // erstelle eine random-Zahl zwischen 1 und | ||
int random = 1 + (int) (Math.random() * 3); | int random = 1 + (int) (Math.random() * 3); | ||
| Zeile 248: | Zeile 233: | ||
return movePixel + 1; | return movePixel + 1; | ||
} | } | ||
} | } | ||
} | } | ||
</pre> | </pre> | ||
Aktuelle Version vom 4. März 2013, 19:29 Uhr
import java.awt.Color;
public class DLA {
public static void main(String[] args) {
// Feld erstellen, in dem gespeichert wird, ob an gegebenen Koordinaten
// ein Partikel ist
int[][] field = new int[400][400];
// Maximalwerte fuer Koordinaten der Partikel, lassen sich aus den
// Dimensionen von field berechnen (.length verwenden)
int maxX = field.length;
int maxY = field[0].length;
// Fenster fuer Grafikausgabe vorbereiten und anzeigen
Pad drawPad = new Pad();
drawPad.setBackground(Pad.black);
drawPad.setPadSize(maxX, maxY);
drawPad.setVisible(true);
drawPad.setColor(Pad.white);
// "Samen" erzeugen, also den ersten Pixel aufs Feld setzen (Color:
// Pad.white)
// Hier: Pixel wird genau in die Mitte des Feldes gesetzt - andere
// Startpixel waeren moeglich
setPixel(drawPad, field, maxX / 2, maxY / 2, Pad.white);
// Abstand des Partikels, der am weitesten vom Zentrum des Feldes
// entfernt ist
int maxR = 0;
// Falls der Startpunkt auch ein anderer sein kann als das Zentrum des
// Feldes:
// Berechne fuer alle bereits vorhandenen Partikel den Abstand zum
// Zentrum des Feldes
// speichere das Maximum dieser Abstaende in maxR
for (int x = 0; x < maxX; x++) {
for (int y = 0; y < maxY; y++) {
if (testPixel(field, x, y)) {
maxR = (int) Math.max(maxR, Math.sqrt(Math.pow((x - maxX / 2), 2) + Math.pow((y - maxY / 2), 2)));
}
}
}
// Abbruchbedingung: Hat einer der Partikel sich aus dem Feld heraus
// bewegt?
boolean isAtBorder = false;
// Schleife: Erstelle solange neue Partikel, wie die Abbruchbedingung
// false ist
while (!isAtBorder) {
// auf einem gedachten Kreis um den Mittelpunkt mit Radius maxR + 20
// einen Partikel "erzeugen"
// d.h. die Koordinaten eines zufaelligen Punktes auf dem Kreisrand
// berechnen
// neuer Partikel ist somit an Position movingPixelX ; movingPixelY
double x = Math.random() * 360;
int movingPixelX = limit((int) (Math.cos(x) * (maxR + 20)) + maxX / 2, 0, maxX);
int movingPixelY = limit((int) (Math.sin(x) * (maxR + 20)) + maxY / 2, 0, maxY);
// Nun Start der brownschen Bewegung
// Partikel bewegt sich, bis er einen bereits vorhandenen Partikel
// beruehrt oder bis er das Feld verlaesst
while (!isTouching(field, movingPixelX, movingPixelY) && inRange(movingPixelX, movingPixelY, maxR + 30, maxX, maxY)) {
// zufaelliges Verschieben des Partikels um +/- 1 Pixel mit
// moveRandom
movingPixelX = moveRandom(movingPixelX);
movingPixelY = moveRandom(movingPixelY);
}
// Brownsche Bewegung zu Ende - Ist Partikel auf einen bereits
// vorhandenen Partikel gestossen?
if (isTouching(field, movingPixelX, movingPixelY)) {
// Wenn ja: Partikel ist jetzt "fest" an dieser Stelle, zeichne
// einen Punkt dort
// Farbwertberechnung fuer 1337 blau-Effekt
int k = limit(255 - (int) (255 * ((double) maxR * 2) / (double) maxX), 0, 255);
Color c = new Color(255, k, k);
// den Partikel setzen und zeichnen
setPixel(drawPad, field, movingPixelX, movingPixelY, c);
// Abstand des neu gesetzten Partikels zum Mittelpunkt des
// Feldes berechnen
// wenn groesser als alter maximaler Abstand maxR, dann Maximum
// mit neuem Abstandswert ueberschreiben
maxR = (int) Math.max(maxR, Math.sqrt(Math.pow(((double) movingPixelX - (double) maxX / 2), 2) + Math.pow(((double) movingPixelY - (double) maxY / 2), 2)));
// Falls der Partikel das Feld verlassen hat: Zeichnung ist
// fertig, setze Abbruchkriterium der aeusseren Schleife auf
// true
if (movingPixelX - 1 <= 0 || movingPixelX + 1 >= maxX || movingPixelY - 1 <= 0 || movingPixelY + 1 >= maxY) {
isAtBorder = true;
}
}
// System.out.println(maxX + "\t" + maxY + "\t " + maxR + "\t"
// + movingPixelX + "\t" + movingPixelY + "\t"+isAtBorder);
}
}
public static void setPixel(Pad drawPad, int[][] field, int x, int y, Color c) {
/**
* Pruefe, ob sich der Partikel an Koordinaten (x,y) innerhalb des
* Feldes befindet Wenn ja, speichere ihn fest im Feld an dieser Stelle
* zeichne dort einen Punkt
*/
if (x > 0 && y > 0 && x < field.length - 1 && y < field[0].length - 1) {
field[x][y] = 1;
drawPad.setColor(c);
drawPad.drawDot(x, y);
}
}
/**
* Prüft ob sich ein Punkt innerhalb eines Radius vom Mittelpunkt eines
* Rechtecks befindet
*
* @param x
* die x Koordinate des fields
* @param y
* die y Koordinate des fields
* @param maxR
* der Radius
* @param maxX
* die x Koordinate des Rechtecks
* @param maxY
* die y Koordinate des Rechtecks+30
*/
public static boolean inRange(int x, int y, int maxR, int maxX, int maxY) {
// Mittelpunkt des Rechtecks ausrechen
int middleX = maxX / 2;
int middleY = maxY / 2;
// Der Abstand vom Mittelpunkt sqrt(a² + b²) mit Hilfe der in Java
// intigrierten Klasse "Math"
int distance = (int) Math.sqrt(Math.pow((x - middleX), 2) + Math.pow((y - middleY), 2));
if (distance < maxR) {
return true;
}
return false;
}
/**
* Testet ob das gegebene Pixel an ein anderes grenzt
*
* @param field
* das Array von Pixeln
* @param x
* die x Koordinate des fields
* @param y
* die y Koordinate des fields
* @return grenzt an ein anders Pixel (true) oder nicht (false)
*/
public static boolean isTouching(int[][] field, int x, int y) {
// ist eigentlich unschön, in diesem Fall aber wesentlich einfacher zu
// lesen und zu verstehen
if (testPixel(field, x - 1, y - 1) || testPixel(field, x - 1, y)
|| testPixel(field, x - 1, y + 1) || testPixel(field, x, y - 1)
|| testPixel(field, x, y + 1) || testPixel(field, x + 1, y - 1)
|| testPixel(field, x + 1, y) || testPixel(field, x + 1, y + 1)) {
return true;
}
return false;
}
/**
* Testet ob der Wert des Pixels größer 0 ist. (Falls der Wert außerhalb der
* Grenzen ist wird er mit der limit() Methode gelimited)
*
* @param field
* das Array von Pixeln
* @param x
* die x Koordinate des fields
* @param y
* die y Koordinate des fields
* @return ob der Wert größer 0 ist (true) oder nicht (false)
*/
public static boolean testPixel(int[][] field, int x, int y) {
// länge des ersten arrays
x = limit(x, 0, field.length - 1);
y = limit(y, 0, field[0].length - 1);
// länge des zweiten arrays
if (field[x][y] > 0) {
return true;
}
return false;
}
/**
* Limitiert einen Wert auf einen Bereich
*
* @param value
* der zu limitierende Wert
* @param lower
* die untere Grenze
* @param upper
* die obere Grenze
* @return den limitierten Wert
*/
public static int limit(int value, int lower, int upper) {
if (value < lower) {
return lower;
}
if (value > upper) {
return upper;
}
return value;
}
/**
* Bewegt eine Pixelkoordinate randommäßig -1, +1 oder gar nicht
*
* @param movePixel
* die zu bewegende Pixel-Koordinate
* @return die Bewegte Pixel-Koordinate
*/
public static int moveRandom(int movePixel) {
// erstelle eine random-Zahl zwischen 1 und
int random = 1 + (int) (Math.random() * 3);
// Math.random() gibt eine double-Zahl >= 0.0 und < 1.0 zurück
switch (random) {
case 1:
return movePixel - 1;
case 2:
return movePixel;
default:
return movePixel + 1;
}
}
}