Bitte um Hilfe bei 2DArrays

Mr Ma

Mitglied
Hallo, guten Abend
Ich stehe so richtig auf dem Schlauch. Ich versuche eine Aufgabe zu lösen, die sich um 2D Arrays dreht.
Es geht darum, dass zuerst ein int[][] array erzeugt werden soll. Die Größe dieses 2D-Arrays soll durch einen Kommandozeilenparameter (args[1]) festgelegt werden, praktisch (args[1])^2. Die Ausgabe soll in Matrixform geschehen.
Jetzt soll ein weiterer Parameter (args[0]), in Form einer Fließkommazahl, willkürlich auf eines der Felder platziert werden. Dann soll eine Schleife dafür sorgen, dass dieses spezielle Feld pro Schleifendurchlauf die Anderen verändert (seinen Wert zuweist) und zwar mit einer Wahrscheinlichkeit, welche der eingegebenen Fliesskommazahl entspricht. Die veränderbaren Felder sollen nur unmittelbare Nachbarn sein und zwar nur horrizontal und vertikal. Diagonal ist verboten. Die Schleife soll abbrechen, wenn alle möglichen Nachbarfelder verändert wurden (wo die Wahrscheinlichkeit gegriffen hat).
Und zu guter Letzt soll es noch ein 2D- Array geben vom Typ char, wo in Zeichen visualisiert werden soll, welche Felder sich verändert haben und welche nicht (z.B. mit '+', '-').
So weit bin ich nun:
[CODE lang="java" title="Klasse Main"]public class Main {
public static void main(String[] args) {
float eingabe1 = Float.parseFloat(args[0]);
int eingabe2 = Integer.parseInt(args[1]);

Arraykommunikation arraykommunikation = new Arraykommunikation(eingabe1, eingabe2);
arraykommunikation.veraenderung();
System.out.println();
arraykommunikation.anzeige();
}
}[/CODE]
[CODE lang="java" title="Die Methoden"]import java.util.Random;

public class Arraykommunikation {
private float wahrscheinlichkeit;
private int groesse;

//Konstruktor
public Arraykommunikation(float wWahrscheinlichkeit, int gGroesse) {
wahrscheinlichkeit = wWahrscheinlichkeit;
groesse = gGroesse;
}
//Gettermethoden
public float getWahrscheinlichkeit() {
return wahrscheinlichkeit;
}

public int getGroesse() {
return groesse;
}

public void veraenderung() {
Random random = new Random();
int[][] arr = new int[getGroesse()][getGroesse()];
//Beschreiben des Arrays mit Nullen
for(int a = 0; a < arr.length; a++) {
for(int b = 0; b < arr.length; b++) {
arr[a] = 0;
}
}
//Zufälliges Feld wird verändert
int randomindex1 = random.nextInt(getGroesse());
int randomindex2 = random.nextInt(getGroesse());
arr[randomindex1][randomindex2] = 1;
/*
// while(Abbruchbedingung alle möglichen Felder nach Vorgabe verändert) {
if(getWahrscheinlichkeit > 100.0) {
System.out.println("Falsche Eingabe! Bitte eine Wahrscheinlichkeit bis 100.0 eingeben!");
continue;
}
//Wenn Bedingung erfüllt, verändere Nachbarfelder
if((Math.random() *10 <= getWahrscheinlichkeit()) {
//Verändere
}
else if((Math.random() *100 <= getWahrscheinlichkeit()) {
//Verändere
}
} //Schleifenende
*/
//Ausgabe des Arrays in Matrixform
for(int c = 0; c < arr.length; c++) {
for(int d = 0; d < arr.length; d++) {
System.out.print(arr[c][d] + " ");
}
System.out.println();
}


// }
}
public void anzeige() {

char[][] anzeige = new char[getGroesse()][getGroesse()];
for(int i = 0; i < anzeige.length; i++) {
for(int j = 0; j < anzeige.length; j++) {
anzeige[j] = '-';
}
}
for(int k = 0; k < anzeige.length; k++) {
for(int l = 0; l < anzeige.length; l++) {
System.out.print(anzeige[k][l] + " ");
}
System.out.println();
}
}
}[/CODE]
Der Code kompiliert bei mir. Die auskommentierten Zeilen sind meine zusätzlichen Ideen.
Mit dem Verändern, da denke ich gerade an "Pathfinding", bekomme es aber nicht umgesetzt: Es sollen ja alle Nachbarfelder mit der gleichen Wahrscheinlichkeit angesprochen werden. Da entsteht oder soll ein exponentielles Wachstum entstehen. Und wie macht man es, dass ein bereits verändertes Feld NICHT mehrmals verändert wird? Ich habe keine Ahnung.
Das Schwierigste ist aber wie das int[][] und das char[][] Array synchronisiert werden? Hat jemand eine Idee?
Lieben Dank schon mal.

PS Wenn ich mich unverständlich ausgedrückt haben sollte, bitte noch einmal nachfragen. Ich habe im Moment Fieber und unter solchen Bedingungen habe ich Mühe zu programmieren. Ich muss aber, weil die Aufgabe bewertet wird.
 
Nur um erst mal deine Aufgabe zu verstehen:
Sagen wir du hast ein Eingangs leeres 5x5 2d Array (wie eine 5x5 Matrix in Mathe).

Sagen wir deine Wahrshceinlichkeitszahl ist 0.5 also 50%.


jetzt soll zufällig eins dieser 5^2=25 Felder mit diesem Wert 0.5 belegt werden.
Sagen wir wir landen auf dem Feld (3,3).

Nun gucken wir für jeder der Felder (2,3)(4,3)(3,2) und (3,4) (eben die 4 Felder direkt daneben)jeweils
einmalig ob wir dieses Feld ebenso mit 0.5 belegen.
Hierzu werfen wir für jedes der 4 Felder den Zufallsgenerator.
landet er auf einer zahl >=0.5, wird der Wert 0.5 ins Feld eingetragen.
Gibt er uns eine zahl <0.5 zurück, dann bleibt das feld unverändert leer.
und das mahcne wir halt einmalig für jedes der 4 Felder.


Korrekt so grundsätzlich das Vorgehen?

Oder wie war das genau gemeint mit dem zufälligen verändern der Nachbarfelder?

Wobei du ja was shcreibst von "einmal die nahcbarfelder verändern pro schleifendurchgang".
Das musst du nochmal erklären was da genau gemeint ist.
Oder wird in JEDEM schleifendurchlauf geguckt ob die 4 felder verändert wurden,
und falls nicht wird für jedes unveränderte feld separat "gewürfelt" ob es in dieser runde verändert wird oder nicht?
Da smüsstest du noch klarstellen was da genau gemeint ist.
Idealerweise den Originaltext der Aufgabe bzw. zumindest dieses Teils posten.


Wobei ich irgendwie den sinn hinter den Shcleifendurchläufen nicht verstehe.
Ich meine, es kann mit glück in Runde 1 Alles verändert werden, mit Pech auch erst in Rund 300.
Ist ja aber egal da das Programm so oder so dann fertig ist, wenn Alles verändert ist.
Also endresultat ist IMMER das Spielfeld mit den 5 (startfeld und 4 nachbarfelder) veränderten feldern.
Wozu da die ganzen wahrshceinlichkeitssachen und co. drin sind, muss man wohl nciht verstehen 🙂

Gut und am Ende solslt du es halt noch graphisch auf der konsole darstellen lassen, der Part ist dann kleinkram.
Wobei du bei der Anzeige am Ende vermutlich hingehen sollst und Felder , die nahc wie vor leer sind, durhc ein - darstellen sollst und mit einem wert belegte Felder durch ein + verändern sollst.
Aktuell, wenn ich mich nicht vergukt habe,s tellst du Alles als - dar.

Kleiner Tipp vorab:
Es macht sicherlich SEHR viel Sinn, sich die random gewählte Startposition auch einmal zu speichern 🙂
Auch ist es sinnhafter, dem startfeld statt 1 eben die Wahrshcienlichkeit zuzuordnen.
 
Hallo berndoa, danke für deine Antwort.
jetzt soll zufällig eins dieser 5^2=25 Felder mit diesem Wert 0.5 belegt werden.
In der Aufgabenstellung ist ein 2D int-Array gefordert. Ein Feld soll auf jeden Fall belegt werden. Diese Ursprungszelle soll dann mit der beim Programmstart eingegebenen Wahrscheinlichkeit pro Schleifendurchlauf seinen Nachbarfelder seinen Wert überschreiben.
Nun gucken wir für jeder der Felder (2,3)(4,3)(3,2) und (3,4) (eben die 4 Felder direkt daneben)jeweils
einmalig ob wir dieses Feld ebenso mit 0.5 belegen.
Hierzu werfen wir für jedes der 4 Felder den Zufallsgenerator.
landet er auf einer zahl >=0.5, wird der Wert 0.5 ins Feld eingetragen.
Gibt er uns eine zahl <0.5 zurück, dann bleibt das feld unverändert leer.
und das mahcne wir halt einmalig für jedes der 4 Felder.


Korrekt so grundsätzlich das Vorgehen?
Das ist korrekt.
Wobei du ja was shcreibst von "einmal die nahcbarfelder verändern pro schleifendurchgang".
Das musst du nochmal erklären was da genau gemeint ist.
Im ersten Schleifendurchlauf können diese von dir oben genannten Felder verändert bzw. beschrieben werden. Durch die Wahrscheinlichkeit ergeben sich 4 Möglichkeiten: von gar keines bis zu allen Vieren.
Nun beginnt der zweite Schleifendurchlauf: Die neu beschriebenen Felder sollen jetzt mit der gleichen Wahrscheinlichkeit wieder ihre Nachbarn "befallen". Nehmen wir an, die Chance fällt auf 2,3. Dieses Feld hat drei Nachbarn: 2,2 2,4 und 1,3.
Pro Schleifendurchlauf soll es so einen Fortschritt geben.
Idealerweise den Originaltext der Aufgabe bzw. zumindest dieses Teils posten.
Das kann und darf ich leider nicht tun, da ich nicht allein arbeite (tue ich im Endeffekt doch, weil Team ja bedeutet: Toll ein anderer machts🤬)
Um die anderen Mitglieder vor Disqualifikation zu schützen bitte ich darum um Verständnis.
Ich habe die Aufgabenstellung maskiert und sinnbildlich versucht darzulegen. Außerdem ist das natürlich nicht alles.
Die Abbruchbedingung der Schleife ist:
Die beschriebenen Felder sollen eine Halbwertzeit haben! Jedes neu beschriebene Feld kann nur 3 bis 5 Schleifendurchläufe (Wert darf ich mir wohl aussuchen) auf seine Nachbarn einwirken. Danach soll der Wert "eingefroren" werden und sie nicht mehr in die Lage stellen andere Felder zu beeinflussen.
Wenn alle Werte eingefroren sind, dann soll die Schleife verlassen werden! (das habe ich erst einmal bewusst rausgelassen um das kleinere Übel, die Verbreitung der Feldbeschreibung, zuerst lösen zu können).
Also gefordert ist: Das 2D-int Array, die Eingabe in Kommandozeilenparameter <Fließkomma, int(Arraygröße)>, diese Schleife, die visuelle synchrone Ausgabe auf der Konsole (char[][]) und noch eine Auswertung mit Berechnungen von dem Ganzen (ist hier erst einmal zu viel).
Gut und am Ende solslt du es halt noch graphisch auf der konsole darstellen lassen, der Part ist dann kleinkram.
😶 Kleinkram??
Wobei du bei der Anzeige am Ende vermutlich hingehen sollst und Felder , die nahc wie vor leer sind, durhc ein - darstellen sollst und mit einem wert belegte Felder durch ein + verändern sollst.
Ja, genau. Es soll dann aber noch ein drites Sonderzeichen den "eingefrorenen/unschädlichen Zustand" markieren😞.
Es macht sicherlich SEHR viel Sinn, sich die random gewählte Startposition auch einmal zu speichern 🙂
Auch ist es sinnhafter, dem startfeld statt 1 eben die Wahrshcienlichkeit zuzuordnen.
Danke, daran werde ich mich mal halten und mein Programm anpassen. Ich vermute die Startposition ist wichtig für die char-Darstellung?
 
Wieso muss ich gerade an Game of Life und so denken? ;-)

Ich bin mir im prinzip immer noch unsicher:
so als Analoges Beispiel sagen wir mal, du hast eine Fläche unterteilt in quadrate.
Auf ein zufällig ausgewähltes feld wird ein Virus aufgebracht.
In der Folgerunde kann jeder der Nachbarfelder zufällig auch infiziert sein, abhängig von einer Wahrshceinlichkeit.

Frage ist nun:
Können insgesamt gesehen nur das Startfeld und die 4 Nachbarfelder infitziert werden und es wird eben so lange gespielt bis diese 5 Felder infiziert sind (sprich: Ausser den 5 Feldern bleiben garantiert alle Andern uninfiziert)?

oder breitet sich das von Runde zu Runde weiter aus?
Also wenn bspw. ein Feld neu infiziert wird in dieser Runde, können dessen Nachbarfelder dann im nächsten Schritt auch infiziert werden ?

Das mit der Halbwertszeit macht das Ganze natürlcih schon etwas komplizierter.
Ich weiß ja nicht was die Vorgaben sind, aber um von der Runde zur Folgerunde zu kommen, würde ich tatsächlich mit einem alten und einem neuen Array arbeiten, wobei das alte Array eben die aktuelle Situation hat und die Zellen im neuen Array abhängig von den alten Zellen ihre Werte kriegen.


Und generell:
Dass ein zufälliges Feld neu infiziert wird, passiert aber nur einmal am Anfang des Spiels, oder?
Also es wird nur einmlig ein Virstropfen auf das Feld getropft?

Und danach lässt man ihn sich fleissig verbreiten bis Alle Felder voll sind?
 
oder breitet sich das von Runde zu Runde weiter aus?
Also wenn bspw. ein Feld neu infiziert wird in dieser Runde, können dessen Nachbarfelder dann im nächsten Schritt auch infiziert werden ?
exakt so.
Dass ein zufälliges Feld neu infiziert wird, passiert aber nur einmal am Anfang des Spiels, oder?
Also es wird nur einmlig ein Virstropfen auf das Feld getropft?
genau
Und danach lässt man ihn sich fleissig verbreiten bis Alle Felder voll sind?
nicht ganz. Wenn wir davon ausgehen, dass es ein Virus sein soll wird es Zellen geben, die nach einer Weile immun sind.
Also die Schleife soll verlassen werden, wenn keine Zelle verändert/infiziert werden kann. Die "Eingefrorenen" sind für eine erneute Überschreibung gesperrt.
 
So, jetzt habe ich einen vielversprechenden Ansatz:
Java:
import java.util.Random;
import java.util.Arrays;

public class Arraykommunikation {
    private float wahrscheinlichkeit;
    private int groesse;
    private int startpunktZeile;
    private int startpunktSpalte;

    //Konstruktor
    public Arraykommunikation(float wWahrscheinlichkeit, int gGroesse) {
        wahrscheinlichkeit = wWahrscheinlichkeit;
        groesse = gGroesse;
    }
    //Getter- und Settermethoden
    public float getWahrscheinlichkeit() {
        return wahrscheinlichkeit;
    }

    public int getGroesse() {
        return groesse;
    }

    public int getStartpunktZeile() {
        return startpunktZeile;
    }

    public int getStartpunktSpalte() {
        return startpunktSpalte;
    }

    public void setStartpunktZeile(int derStartpunktZeile) {
        startpunktZeile = derStartpunktZeile;
    }

    public void setStartpunktSpalte(int derStartpunktSpalte) {
        startpunktSpalte = derStartpunktSpalte;
    }

    public void veraenderung() {
        Random random = new Random();
        int[][] arr = new int[getGroesse()][getGroesse()];

        //Zufälliges Feld wird verändert
        setStartpunktZeile(random.nextInt(getGroesse()));
        setStartpunktSpalte(random.nextInt(getGroesse()));
        arr[getStartpunktZeile()][getStartpunktSpalte()] = (int)(getWahrscheinlichkeit()*10);

        if((Math.random() *100) < getWahrscheinlichkeit()) {
            arr[getStartpunktZeile()][getStartpunktSpalte()+1] = (int)(getWahrscheinlichkeit()*10);
        }

        if((Math.random() *100) < getWahrscheinlichkeit()) {
            arr[getStartpunktZeile()-1][getStartpunktSpalte()] = (int)(getWahrscheinlichkeit()*10);
        }

        if((Math.random() *100) < getWahrscheinlichkeit()) {
            arr[getStartpunktZeile()][getStartpunktSpalte()-1] = (int)(getWahrscheinlichkeit()*10);
        }

        if((Math.random() *100) < getWahrscheinlichkeit()) {
            arr[getStartpunktZeile()+1][getStartpunktSpalte()] = (int)(getWahrscheinlichkeit()*10);
        }

        for(int c = 0; c < arr.length; c++) {
            for(int d = 0; d < arr.length; d++) {
                System.out.print(arr[c][d] + " ");
            }
            System.out.println();
        }
        //Array Kopieren
   int q = 1;//Zum Testen der Schleife
   int wert = (int)(getWahrscheinlichkeit()*10);
   while(q < 11) {
        q = q+1;
        int[][] arr2 = arr;
        //Visuelle Trennung der Arrays
        System.out.println();
        System.out.println("arr"+q +" = copy");
        for(int c = 0; c < arr2.length; c++) {
            for(int d = 0; d < arr2.length; d++) {
                if((arr2[c][d] == wert) && ((Math.random() *100) < getWahrscheinlichkeit())) {
                    arr2[c+1][d] = wert;
                    if(arr2[c+1][d] > arr2.length) {
                        continue;
                    }
                }
                if((arr2[c][d] == wert) && ((Math.random() *100) < getWahrscheinlichkeit())) {
                    arr2[c-1][d] = wert;
                    if(arr2[c-1][d] < 0) {
                        continue;
                    }
                }
                if((arr2[c][d] == wert) && ((Math.random() *100) < getWahrscheinlichkeit())) {
                    arr2[c][d+1] = wert;
                    if(arr2[c][d+1] > arr2[d].length) {
                        continue;
                    }
                }
                if((arr2[c][d] == wert) && ((Math.random() *100) < getWahrscheinlichkeit())) {
                    arr2[c][d-1] = wert;
                    if(arr2[c][d-1] < 0) {
                        continue;
                    }
                }
            }
        }
        for(int c = 0; c < arr2.length; c++) {
            for(int d = 0; d < arr2.length; d++) {
                System.out.print(arr2[c][d] + " ");
            }
            System.out.println();
        }
    }//Whileschleife Ende

    }
    public void anzeige() {

        char[][] anzeige = new char[getGroesse()][getGroesse()];
        for(int i = 0; i < anzeige.length; i++) {
            for(int j = 0; j < anzeige.length; j++) {
                anzeige[i][j] = '-';
            }
        }
        for(int k = 0; k < anzeige.length; k++) {
            for(int l = 0; l < anzeige.length; l++) {
                System.out.print(anzeige[k][l] + " ");
            }
            System.out.println();
        }
    }
}
Ich bekomme in der Whileschleife aber ab und an leider noch eine IndexOutOfBoundsException.
Und ich fürchte, so werden die bereits vorhandenen Werte auch mehrfach überschrieben?
 
@berndoa: Danke, das "Game of Life" hat geholfen (musste erst einmal forschen was das ist). Ich habe mein Programm noch einmal umgeschrieben und die Fehler sind weg.
Jetzt stehe ich aber immer noch vor zwei Problemen:
Das mit den eingefrorenen Werten.
und die visuelle Ausgabe von dem Ganzen, du sagtest das ist eine Kleinigkeit?😃
 
Öh, hm, pff.

im Zweifel würde ich eine separate 2. Matrix nutzen in der ich die Halbwertszeiten notiere. Und sobald in der Hauptmatrix das betreffende Feld geändert wird, beginnt der Countdown zu laufen dermit jeder Runde um 1 runter geht.

Also wenn deine infizierten Felder 5 runden durchhalten, würde ich in der 2. matrix am Anfang Alles auf 5 setzen.
Wird in einer Runde das Feld (1,2) "infiziert", dann würde ich am Ende dieser Runde in der 2. matrix das Feld (1,2) von 5 auf 4 runtersetzen.

Hat ein Feld eine 5 stehen, wurde es noch nciht infiziert. hat es eine 1-4, ist es infiziert und derzeit auf einem coutndown.
hat es 0 erreicht, geht der countdown nicht weiter runter und bleibt bei 0.

Wenn irgendwann das Spiel zu einem willkürlichen zeitpunkt zu Ende ist, dann entsprichtin der 2. matrix bei einem Feld die 0 einer abgestorbenen Zelle, eine 1-4 eine infizierten aber noch aktiven Zelle. Und eine 5, die eine nicht infizierte Zelle darstellt, sollte erst gar nicht mehr vorkommen 🙂

Dementsprechend kannst du beim Ausdrucken dann auch direkt die zahl im betreffenden Feld in ein passenden Symbol für "infiziert und aktiv" oder "abgestorben" bzw. "eingefroren" übersetzen.


Würde ich so machen.

Gibt sicherlich einfachere oder besserere Wege um das mit maps und anderen Dateitypen zu machen , wo man kein 2. Array braucht.

Ich würde auf diesem Noobweg hier lösen 🙂
 

Neue Themen


Zurück
Oben