Bestimmte Zahlen bei Math.random ausschließen?

Wuast

Bekanntes Mitglied
Hallo,
gibt es eine elegante Lösung um auszuschließen, dass mehrere integer, die mittels der math.random initialisiert wurden, die gleiche Zahl erhalten?

Java:
// es sollen zwei Punktobjeke mit den Zufalls-Koordinaten x1/y1 und x2/y2 geben

for (int i = eingabe; i <= eingabe2; i++) {    //eingabe und eingabe 2 kommen von der Konsole und geben den Spielfeldrahmen vor
          
        x1 = (int) ((Math.random() * eingabe2)+1);   
        y1 = (int) ((Math.random() * eingabe1)+1);         
  
        x2 = (int) ((Math.random() * eingabe2)+1);          // x2 soll != 1 sein, wenn
        y2 = (int) ((Math.random() * eingabe1)+1);          // y2 ==y1 ist (und vice versa)

        java.awt.Point Spieler1 = new java.awt.Point(x1, y1);          //
        java.awt.Point Spieler2 = new java.awt.Point(x2, y2);          //

}

Meine Gedanken gehen in Richtung

Java:
if (Spieler1 == Spieler2) {
    ... //  noch keine konkrete Idee, Vorschläge sind natürlich sehr willkommen
 
}

oder vllt.
    do {
        // wie könnte ich das formulieren? vllt. einfach wieder so:
         x2 = (int) ((Math.random() * eingabe2)+1);
         y2 = (int) ((Math.random() * eingabe1)+1);
    }
while (Spieler1 == Spieler2)

    // die Punkte dürfen nicht die gleichen Koordinaten haben

Was sagt ihr zu den Vorschlägen? Da es im Verlauf mehr als zwei Spieler geben kann, bin ich unsicher, ob ich mit der if-Abfrage oder dem do-While so gut fahre.
Kennt ihr aber vllt. noch etwas "besseres", was verhindert, dass Math-Random die gleichen Zufallskoordinaten ausspuckt?

Grüße Yannik
 

Wuast

Bekanntes Mitglied
Ich habe jetzt
Java:
do {
            x2 = (int) ((Math.random() * spielfeldBreite)+1);
            y2 = (int) ((Math.random() * spielfeldHöhe)+1);
        }
        while (spieler1.equals( spieler2) );    //spieler2.x=x2 //spieler2.y=y2
wenn es etwas schickeres gibt, was ich direkt in die Math.random packen kann, freue ich mich über eine Info :)

Ich möchte noch eine andere (wichtigere) Frage ergänzen:

Wie kann ich sicherstellen, dass die Spielerpositionen im Rahmen des Spielfeldes gesetzt werden? Manchmal wird mit ein Spieler nicht in der Konsole angezeigt.

Die Eingaben definieren den Rahmen, in welchem die Spieler gesetzt werden.
eingabe1 entspricht der y-Achse, eingabe2 der x-Achse (also Höhe und Breite), die als System.out.print('-') dargestellt werden.

Java:
for (int y = 0; y < eingabe1; y++) {
                for (int x = 0; x < eingabe2; x++) {
                    java.awt.Point p = new java.awt.Point(x, y);
                    if (spieler1.equals(p)) {
                        System.out.print('1');
                    }
                    else if (spieler2.equals(p)) {
                        System.out.print('2');
                    }
                    else System.out.print('-');
                }
                System.out.println();

Manchmal scheint einer der spieler außerhalb des Spielfeldes zu liegen.

Danke und LG

PS: Ich hoffe, ich stifte hier keine Verwirrung und das Gerüst ist klar :) Sonst bitte nochmal darauf hinweisen.
 
Zuletzt bearbeitet:

mihe7

Top Contributor
gibt es eine elegante Lösung um auszuschließen, dass mehrere integer, die mittels der math.random initialisiert wurden, die gleiche Zahl erhalten?
Naja, was heißt elegant? Man kann sich erst einmal überlegen, dass gilt: (a,c) == (b,d) gdw. a == b und c == d.

D. h. die Koordinaten a, c und b können schon mal beliebig innerhalb ihrer Grenzen gewählt werden: Wenn a != b gilt, können wir auch d beliebig wählen, nur wenn a == b gilt, muss d so gewählt werden, dass c != d gilt.
Java:
Random rand = new Random();
int a, b, c, d;

a = rand.nextInt(breite);
b = rand.nextInt(breite);
c = rand.nextInt(hoehe);
if (a == b) {
    // TODO: wähle d aus der Menge [0, hoehe[ \ {c}
} else {
    d = rand.nextInt(hoehe);
}
Betrachten wir noch das TODO.

Wir hatten c aus der Menge [0, hoehe[ ⊆ ℕ gewählt. Diese Menge hat hoehe Elemente, d. h. für die Wahl von c standen hoehe verschiedene Möglichkeiten zur Verfügung. Da wir das c nun aus der Menge der Möglichkeiten für d herausnehmen wollen, gibt es für d nur noch hoehe-1 Möglichkeiten.

Wir wählen d also aus der Menge [0, hoehe-1[ ⊆ ℕ. Gilt d < c, haben wir unser d gefunden. Gilt d >= c, dann brauchen wir d nur um 1 zu erhöhen, um das d in das Intervall ]c, hoehe[ zu verschieben. Ersetzen wir also das TODO durch:
Java:
    d = Math.nextInt(hoehe-1);
    if (d >= c) {
        d++;
    }
Fertig.

Damit sollte auch die Frage
Wie kann ich sicherstellen, dass die Spielerpositionen im Rahmen des Spielfeldes gesetzt werden?
beantwortet sein.
 

Wuast

Bekanntes Mitglied
Danke für deine ausführliche Antwort!!

Ich übertragedeine abcd-Konstanten gedanklich auf mein Bsp., demnach wäre bei mir
spieler1(x,y) = spieler1(a,c) und spieler2(b,d), korrekt?^^

So ganz habe ich es noch nicht. Schau mal bitte:

Java:
public class Spiel {
   
    public static void main(String[] args) {
       
        int eingabe1 = new java.util.Scanner(System.in).nextInt(); //Spielfeldbreite
        int eingabe2; //Spielfeldhöhe
       
        do{
        int eingabe2 = new java.util.Scanner(System.in).nextInt(); //Spielfeldhöhe festlegen
            if (eingabe2 >= eingabe1){
                System.out.println("bitte kleiner"); //Sollte breiter als hoch sein, macht den Code nachfolgend einfacher denke ich?! sieht jedenfalls besser aus
            }
        }
        while (eingabe2 >= eingabe1)
           
    //Ist das so überhaupt korrekt?

    for (int i = eingabe1; i <= eingabe2; i++) {
        x1 = (int) ((Math.random() * eingabe2)+1);    //dein a
        y1 = (int) ((Math.random() * eingabe2)+1);    //dein c
       
        x2 = (int) ((Math.random() * eingabe2)+1);    //dein b
        y2 = (int) ((Math.random() * eingabe2)+1);    //dein d
       
        //jetzt deine TODO? Irgendwas stimmt doch hier noch nicht :D
       
        if (x1 == x2){
            if (y2 >= y1){
                y2 ++;
            }
        }
       
        for (int y = 0; y < eingabe2; y++)    //koordinaten d. nachfolgenden Punktobjekts
            for (int x = 0; x < eingabe1; x++){
                java.awt.Point p = new java.awt.Point(x,y);
                if (spieler1.equals(p)){
                    System.out.print('1');
                }
                if (spieler2.equals(p)){
                    System.out.print('2');
                }
                else System.out.print('-');
            }
       
    }

Das habe ich jetzt aktuell dazu. Deine Erläuterung macht für mich - wenn auch mathematischer ausgedrückt als es mir lieb ist :D - durchaus Sinn. Einfach ausgedrückt muss ich ja nur sicherstellen, dass wenigstens eine x oder eine y-Koordinate bei den Spieler-Punktobjekten abweichend von der jeweils anderen ist?!
Aber so richtig KLICK gemacht hat es noch nicht :/
 

mihe7

Top Contributor
Einfach ausgedrückt muss ich ja nur sicherstellen, dass wenigstens eine x oder eine y-Koordinate bei den Spieler-Punktobjekten abweichend von der jeweils anderen ist?!
Richtig.

Machen wir das mal mit einer Dimension.

Aufgabe: wähle zufällig zwei verschiedene(!) Zahlen zwischen 0 und 5.

Wir können uns gedanklich eine Liste mit diesen 6 Zahlen aufschreiben:
012345

Jetzt können wir mit rand.nextInt(6) zufällig eine dieser Zahlen wählen. Sagen wir mal, wir hätten die 2 ermittelt. Soweit kein Problem. Wie können wir jetzt aber die 2 beim Ermitteln der nächsten Zahl ausschließen?

Streichen wir die 2 mal gedanklich aus unserer Liste:
012345

Offensichtlich stehen nur noch 5 Zahlen zur Wahl: 0, 1, 3, 4 und 5 sind fünf Stück. Also rufen wir nextInt(5) auf und erhalten so eine Zahl zwischen 0 und 4. Das können wir mal mit einem Sternchen in die Tabelle einzeichnen:

012345
*****

Wenn die zufällig gezogene Zahl kleiner als die gestrichene 2 ist, können wir sie unmittelbar verwenden. Ist sie größer oder gleich 2, müssen wir sie nur um eine Spalte nach rechts verschieben, also 1 addieren, dann ergibt sich folgendes Bild:

012345
*****

Damit wäre die Aufgabe gelöst und im Code sähe das so aus:
Java:
int zahl1 = rand.nextInt(6);
int zahl2 = rand.nextInt(5);
if (zahl2 >= zahl1) {
    zahl2++;
}
Jetzt klar?
 

Wuast

Bekanntes Mitglied
Ja, das schon! Danke! 😁👌

Also im Code konkrekt bei dann
Java:
if (x1 == x2 && y1 == y2){
    if (x2 >= x1 || y2 >= y1 ){
        y2++;
    }
}

richtig?? Ich muss ja nur aktiv werden, wenn sowohl x1undx2, als auch y1undy2 gleich sind. Ansonsten ist es ja egal.

Müsste nicht aber folgender Code auf das gleiche rauskommen?
Java:
do {
            x2 = (int) ((Math.random() * spielfeldBreite)+1);
            y2 = (int) ((Math.random() * spielfeldHöhe)+1);
        }
        while (spieler1.equals( spieler2) );
Dieser Teil bewirkt doch, dass - immer wenn spieler1 (Punkt mit den Koordinaten x1,y1) und spieler2 (Punkt mit den Koordinaten x2,y2) equal sind, wird spieler2 einfach neu zufällig bestimmt.

Nur das Problem, dass manchmal Spieler1 oder Spieler2 außerhalb des Feldes gesetzt werden, wird doch dadurch nicht gelöst, oder (also weder durch deine Lösung mit der if-Abfrage, noch durch meinen Vorschlag mit der dowhile-Schleife)? Weil im Code habe ich doch weiterhin

Java:
y2= (int) ((Math.random() * eingabe2)+1);

Müsste dann statt +1 -1 dahin? (in Gedanken bei deiner ersten Antwort)
Wir hatten c aus der Menge [0, hoehe[ ⊆ ℕ gewählt. Diese Menge hat hoehe Elemente, d. h. für die Wahl von c standen hoehe verschiedene Möglichkeiten zur Verfügung. Da wir das c nun aus der Menge der Möglichkeiten für d herausnehmen wollen, gibt es für d nur noch hoehe-1 Möglichkeiten.

Wir wählen d also aus der Menge [0, hoehe-1[ ⊆ ℕ. Gilt d < c, haben wir unser d gefunden. Gilt d >= c, dann brauchen wir d nur um 1 zu erhöhen, um das d in das Intervall ]c, hoehe[ zu verschieben. Ersetzen wir also das TODO durch:
Java:
    d = Math.nextInt(hoehe-1);
    if (d >= c) {
        d++;
    }
Fertig.

Damit sollte auch die Frage

beantwortet sein.
Vielen Dank für deine Hilfe!!
 

mihe7

Top Contributor
Müsste nicht aber folgender Code auf das gleiche rauskommen?
Das Snippet als solches bewirkt entweder nichts oder eine Endlosschleife, weil Du in der Schleife weder an spieler1 noch an spieler2 etwas geändert wird.

Was Deine Erklärung betrifft: die wäre natürlich richtig. Der Unterschied ist nur: mit oder ohne Schleife. Die Schleife wird halt ggf. mehrfach durchlaufen.

Bau Dir doch einfach ein paar Methoden:
Java:
/** Returns a random integer.
 *
 * @param  bound  upper bound.
 * @return random int between 0 and bound-1.
 */
static int randomInt(int bound) {
     return (int)(Math.random() * bound);
}

/** Returns a random integer different from a given value.
 * 
 * @param  bound  upper bound
*  @param  excluding  the value the result must not match
*  @return random int between 0 and bound-1, guaranteed to be different from {@code excluding}.
*/
static int randomIntExcluding(int bound, int excluding) { 
    if (excluding < 0 || excluding >= bound) {
        return (int)(Math.random() * bound);
    }

    int value = (int) (Math.random() * (bound-1));
    if (value >= excluding) {
        value++;
    }
    return value;
}

Die kannst Du dann einfach testen (dazu müsstest Du allerdings java.util.Random mit einem Seed verwenden und evtl. in eine Klasse auslagern) und auch verwenden:

Java:
int x1 = randomInt(spielfeldBreite);
int y1 = randomInt(spielfeldHoehe);
int x2 = randomInt(spielfeldBreite);
int y2 = (x1 == x2) ? randomIntExcluding(spielfeldHoehe, y1) : randomInt(spielfeldHoehe);

Nur das Problem, dass manchmal Spieler1 oder Spieler2 außerhalb des Feldes gesetzt werden, wird doch dadurch nicht gelöst,
Das Problem wird dadurch gelöst, dass Du Dir klar machst, dass man von 0 beginnt zu zählen :) Eine Breite von 10 heißt, dass der Spieler an Positionen 0, 1, 2, 3, ..., 9 sein kann.
 

Wuast

Bekanntes Mitglied
Bau Dir doch einfach ein paar Methoden:
Entspricht leider nicht mehr den Vorgaben: 3 Methoden., d.h. Menü inkl. Einstellungen, Spiel, Main zum Aufrufen.

In die Einstellungen stopfe ich gerade alles rein, was so nötig ist, um das Spiel zu konfigurieren. Dazu zählt z.B. die Möglichkeit, das Spielfeld einstellen zu können, sprich eingabe1 und eingabe2.

Spieler1 und Spieler2 müssen jetzt irgendwo zufällig in diesem Rahmen gesetzt werden, d.h. deren Koordinaten x1y1 und x2y2 sind zufällig zu ermitteln.
Dazu habe ich folgende Möglichkeit recherchiert und versucht auf meine Situation bezogen richtig anzuwenden (s.oben):

Java:
 for (int i = eingabe1; i <= eingabe2; i++) {
        x1 = (int) ((Math.random() * eingabe2)+1);    //dein a
        y1 = (int) ((Math.random() * eingabe2)+1);    //dein c
     
        x2 = (int) ((Math.random() * eingabe2)+1);    //dein b
        y2 = (int) ((Math.random() * eingabe2)+1);    //dein d

Das man bei 0 anfängt habe ich mal gelernt, stimmt ;) Daraus folgt die -1, weil wenn ich z.B. 10 Felder/Möglichkeiten/... generiere, macht der Rechner daraus 0-9 (das entspricht 10 Feldern/Möglichkeiten/...). Soweit klar!

Übertragen auf die for-Schleife heißt das, ich multipliziere die Math.random-Zahl mit der Breite (der Maximal-Wert) und rechne dann -1 und nicht +1?! oder müsste es lauten
Java:
        x1 = (int) ( ((Math.random() * eingabe2)-1) +1);
?


Ich kann verstehen, dass hier keine Lösungen präsentiert werden und grundsätzlich möchte ich das auch nicht. Aber ich bin an einem Punkt angekommen wo mir etwas der Schädel raucht und ich es nicht noch komplizierter machen kann als es für mich schon ist :D (also noch zusätzlich rumexperimentieren und random mit seed und so, dass verschiebe ich auf wenn ich den Kopf wieder frei habe ;) )

Insofern frage ich jetzt mal ganz direkt: Habe ich das so richtig umgesetzt
Java:
if (x1 == x2 && y1 == y2){
    if (x2 >= x1 || y2 >= y1 ){
        y2++;
    }
}
oder nicht? 🤯😭


Wie immer dickes Dankeschön!
In größerwerdender Verzweiflung
Yannik
 

mihe7

Top Contributor
Übertragen auf die for-Schleife heißt das, ich multipliziere die Math.random-Zahl mit der Breite (der Maximal-Wert) und rechne dann -1 und nicht +1?!
Du multiplizierst einfach mit der Breite. Fertig. Die Breite ist nicht der Maximalwert, sondern die obere Grenze, die niemals erreicht wird.

Warum?

Math.random() liefert eine Gleitkommazahl zwischen 0 und 1, jedoch ohne die 1.

Für y = Math.random() gilt somit 0 <= y < 1.

Multipliziert mit der nicht-negativen Breite b ergibt sich 0 <= y*b < b, d. h. insbesondere, dass Math.random()*b eine Zahl liefert, die kleiner als die Breite b ist.

Castest Du jetzt noch auf ein int, schneidest Du damit halt noch die Nachkommastellen weg und damit gilt:

0 <= (int)(Math.random() * b) <= (b-1)
 

Wuast

Bekanntes Mitglied
Du multiplizierst einfach mit der Breite. Fertig. Die Breite ist nicht der Maximalwert, sondern die obere Grenze, die niemals erreicht wird.

Warum?

Math.random() liefert eine Gleitkommazahl zwischen 0 und 1, jedoch ohne die 1.

Für y = Math.random() gilt somit 0 <= y < 1.

Multipliziert mit der nicht-negativen Breite b ergibt sich 0 <= y*b < b, d. h. insbesondere, dass Math.random()*b eine Zahl liefert, die kleiner als die Breite b ist.

Castest Du jetzt noch auf ein int, schneidest Du damit halt noch die Nachkommastellen weg und damit gilt:

0 <= (int)(Math.random() * b) <= (b-1)
JETZT...wo ich das lese.. frage ich mich, ob ich wirklich so beschränkt bin :D

Vielen Dank!! :)
 

Wuast

Bekanntes Mitglied
Was sind den das für Vorgaben? Wie lautet die Aufgabenstellung?
2 Spieler (Jäger, Gejagter) zufällige Positionen mehrerer Punktobjekte, d.h. Spieler und Ausgang, Spielfeld einstellbar. Main zur Ausführung, Klasse Einstellungen, Klasse Spielfeld und sinnvolle Aufteilung und Untergliederung der Methoden. Vereinfacht ausgedrückt. :D

Aber mit mihes Erörterungen sieht es jetzt ganz brauchbar aus.

Ein Problem habe ich noch zu lösen, da habe ich irgendwas bei den Einstellungen vermurkst aber vllt. und hoffentlich kriege ich es alleine hin. Ansonsten gibts bald nen neuen Thread. Der Rest sieht aber ganz gut aus würd ich sagen
 

Blender3D

Top Contributor
Spieler (Jäger, Gejagter) zufällige Positionen mehrerer Punktobjekte, d.h. Spieler und Ausgang, Spielfeld einstellbar. Main zur Ausführung, Klasse Einstellungen, Klasse Spielfeld und sinnvolle Aufteilung und Untergliederung der Methoden. Vereinfacht ausgedrückt.
Da steht aber nichts von einer Limitierung auf nur 3 Methoden.
 

Wuast

Bekanntes Mitglied
das kann man durchaus auch als das komplette Gegenteil von:

verstehen.
tja... was soll ich machen :D lass mich erstmal korrigieren: 3 Klassen. innerhalb derer ist eine sinnvolle Methodenwahlzu erstellen und in der Main entsprechend darauf zuzugreifen.
Da steht aber nichts von einer Limitierung auf nur 3 Methoden.
klassen, sorry. s.o.

bin bisschen durch damit gerade :D

Darf ich in einer Methode nicht mehrere returns haben?

Java:
         x1 = (int) ((Math.random() * eingabe2); 
        y1 = (int) ((Math.random() * eingabe2); 
  
        x2 = (int) ((Math.random() * eingabe2); 
        y2 = (int) ((Math.random() * eingabe2); 
                  
    Point spieler1 = new java.awt.Point(x1,y1);
    Point spieler2 = new java.awt.Point(x2,y2);
                  
                    return spieler1;
                    return spieler2; //geht nicht... unreachable code WARUM??? :D

Muss man sowas immer über getter machen wenn ich mehrere Werte zurückgeben möchte?
 

Wuast

Bekanntes Mitglied
Nein. Dafür kann man sich selber einen Typ (Klasse) bauen und dann ein Objekt dieser Klasse zurückgeben.
Driet.. es bleibt spannend!
Aber eigentlich kann ich die Spielerpositionen ja auch in die selbe Methode packen, die dann den Spielablauf steuert.

Oder meinst du, dass wäre "nicht elegant"? Ist ja kein riesen Spiel, nur ein kleines Progrämmchen, da wirds ja nicht unübersichtlich. ^^
 

Kamil1

Gesperrter Benutzer
hmmm @Wuast , wie wärs damit?

Java:
import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;

public class NoDuplicatesIterator implements Iterable<Integer> {
    public class NoDuplicatePointsIterator implements Iterable<Point> {
        @Override
        public Iterator<Point> iterator() {
            final NoDuplicatesIterator xsIterator1 = new NoDuplicatesIterator(n);
            final NoDuplicatesIterator ysIterator1 = new NoDuplicatesIterator(n);

            return new Iterator<>() {
                private Iterator<Integer> xsIterator2 = xsIterator1.iterator();
                private Iterator<Integer> ysIterator2 = ysIterator1.iterator();

                @Override
                public boolean hasNext() {
                    return ysIterator2.hasNext();
                }

                @Override
                public Point next() {
                    Point p1 = new Point(xsIterator2.next(), ysIterator2.next());
                    if (!ysIterator2.hasNext()) {
                        ysIterator2 = ysIterator1.iterator();
                    }
                    if (!xsIterator2.hasNext()) {
                        xsIterator2 = xsIterator1.iterator();

                        ysIterator2.next();
                    }
                    return p1;
                }
            };
        }
    }

    private final int n;
    private final ArrayList<Integer> list = new ArrayList<>();

    public NoDuplicatesIterator(int n) {
        this.n = n;
        for (int i = 0; i < n; i++) {
            list.add(i);
        }
        Collections.shuffle(list);
    }

    @Override
    public Iterator<Integer> iterator() {
        return list.iterator();
    }

    public static void main(String[] args) {
        for (Point p1 : new NoDuplicatesIterator(4).new NoDuplicatePointsIterator()) {
            System.out.println(p1);
        }
    }
}

Rennt in O(n). :D
 
K

kneitzel

Gast
@Kamil1
Dein Code lässt nicht zu, dass sich X oder Y Koordinate gleichen. Es muss aber nur verhindert werden, dass x und y Koordinate gleich sind.

Wird spätestens dann problematisch, wenn Du n unterschiedliche Punkte hast mit n > xmax oder n>ymax. Also z.B. 11 unterschiedliche Punkte auf einem 10x10 Spielfeld.
 
K

kneitzel

Gast
Aber eigentlich kann ich die Spielerpositionen ja auch in die selbe Methode packen, die dann den Spielablauf steuert.

Oder meinst du, dass wäre "nicht elegant"? Ist ja kein riesen Spiel, nur ein kleines Progrämmchen, da wirds ja nicht unübersichtlich. ^^
Damit hast Du sehr schön erkannt, wie es dazu kommt, dass Code immer schlechter wird. Ist ja nur eine kleine Änderung und so unübersichtlich ist es nicht. Und wenn doch, dann hat man ja einen Kommentar dazu gepackt ... Außerdem hat man doch gerade jetzt gar keine Zeit, es richtig zu machen.

Generell sollte man sich immer gut überlegen, wie die Dinge aufgebaut sind und dann auch Elemente, die zusammen gehören, zusammen packen.

Die Position der Spieler gehört zu dem Spieler. Damit sind wir uns doch erst einmal einig denke ich mal. Also sowas wie
Java:
public class Player {
    private Point position;
    
    // ...
}

Die Zwei Spieler mit Ihrer Position: Was bedeutet das denn genau? Die Position sind ja Koordinaten... Von was? Das ist doch eine Map oder Spielfeld oder so. Damit haben wir ja schon die nächste Klasse: Es gibt eine Map mit Spielern:
Java:
public class GameMap {
    private List<Player> player;
    
    // ...
}

Nun müssen n Spieler positioniert werden. Aber doch natürlich auf dem Spielfeld. Also überlegen wir uns einmal, wo das hin gehören würde. Methoden, die etwas in einen Container packen, sind immer am Container zu finden. List.add z.B. Ist hier auch nicht anders:
-> Die Methode gehört in die GameMap.

Wenn Du etwas so aufteilst, dann kann dieses Problem nie entstehen. Denn jede Methode macht ja etwas anderes. Eine Methode, die also A und B erzeigt und die hängen auch nicht wirklich zusammen, kann es so eigentlich nie geben. Dann wären es ja auch zwei Methoden geworden. Oder sie gehören zusammen - dann muss der Zusammenhang irgendwo abgebildet sein ("A gehört zu B" oder "A und B gehören zu C". Hier ist es letzteres: Die Spieler gehören zum Spielfeld.)

Jetzt kannst Du da den Code auch schreiben. Unabhängig davon, was wir bisher so alles hatten an Vorgehen im Thread, kann man sich das von Grund auf überlegen. Das kann man sich auch ganz einfach bildlich vorstellen:

Du hast ein Spielfeld von 6x6 und einen Würfel. Du sollst da jetzt eine Reihe Spielfiguren plazieren. Also was machst Du?

So lange wie ich noch unplazierte Spielfiguren habe:
- ich nehme den Würfel und würfle -> neue X Position
- ich nehme den Würfel und würfle -> neue Y Position
- Wenn die Position (X,Y) frei ist: platziere die nächste Figur dort.

Das kann man durchspielen und schauen, ob es funktioniert.
==> Erster Algorithmus ist soweit fertig. Kann man testen und dürfte gut funktionieren.

==> Ein typisches Vorgehen um mehrere unterschiedliche zufällige Elemente zu bekommen. Kann man also im Hinterkopf behalten.

Nun wollen wir aber 36 Spielfiguren auf dem 6 mal 6 Spielfeld platzieren.
Wir stellen uns nur die Situation vor: nur ein Platz ist frei. Und du würfelst jetzt so lange, bis der erste Wurf die freie x-Koordinate ergibt und der zweite Wurf die freie y Koordinate. Das ist etwas doof. Mit 6 mal 6 mag es noch gehen, aber stell Dir vor Du hast 1000x1000 Felder ...

Schauen wir in die Welt: Wie klappt das denn da? Lotto-Zahlen 6 aus 49: Da sind nie Doppelte!
Wenn wir uns so ein Gerät anschauen, dann sehen wir: Das Gerät nimmt aus einer Menge von Kugeln eine raus. Die ist dann aus der Menge entfernt. Das können wir auch abbilden. Wir erzeugen eine Liste aller Möglichkeiten und nehmen da ein zufälliges Element raus und entfernen es.
==> Das geht von der Laufzeit sehr gut, aber man erkennt den nächsten Nachteil: Das braucht Vorbereitung und Speicherplatz: Schreibe mal alle Felder einer 1000x1000 Spielfeldes auf Zettel und pack die in kleine Ü-Ei Behälter. 1 Millionen Behälter brauchen viel Platz... Aber da kannst Du dann schön immer einzelne Kugeln entnehmen. Wirst Du aber vermutlich nicht machen, wenn Du nur 5 Werte brauchst.

==> Zweiter, universeller Ansatz. Inkl. einer kleinen Betrachtung von Vor- und Nachteilen.

Was will ich damit aufzeigen: Saubere, objektorientierte Struktur und die Dinge passen direkt gut zusammen. Und dabei immer ruhig den bildlichen Vergleich haben. Das geht in den meisten Fällen und hilft dann auch, die natürlichen Grenzen zu erkennen und entsprechend im Model abzubilden.

Ich hoffe, ich konnte diese Punkte etwas erläutern.
 

Blender3D

Top Contributor
Oder meinst du, dass wäre "nicht elegant"? Ist ja kein riesen Spiel, nur ein kleines Progrämmchen, da wirds ja nicht unübersichtlich. ^^
Oder du könntest ein Spielfeld machen in das Spielobjekte eingefügt werden können. Die Spielobjekte haben die Positionen.
Die Methode
Java:
public SpielFeld(){
    ..
    boolean add( SpielObjekt o ){
        // prüfe
        // ob Postion von o erlaubt ist sonst --> false
        // ob Postion von o besetzt ist sonst --> false
        // füge o zum Spielfeld hinzu --> true
    }
}
 

Wuast

Bekanntes Mitglied
Naja also wenn die Erwartung ist, den Code einfach zu halten, damit er übersichtlich und leicht lesbar bleibt, finde ich es mit meiner kaum vorhandenen Erfahrung sinnvoll, nicht für jeden Kram eine Klasse und Methode zu schreiben, sondern es kompakt zu halten (sofern möglich und sinnvoll). Die Grundstruktur von dem Code ist bereits gegeben (und der Insel zu entnehmen). Nun soll es entsprechend den Vorgaben angepasst und um ein Hauptmenü ergänzt werden, sprich die Klassen und sinnvolle Methoden. Im Buch ist das gesamte Spiel in der main auf 2 Seiten geschrieben. Finde ich nicht unübersichtlich, da mit Kommentaren versehen.

Aber wahrscheinlich fehlt mir hier der von Erfahrungswerten gestützte Blick und das Know-How, um es besser umzusetzen.
Oder du könntest ein Spielfeld machen in das Spielobjekte eingefügt werden können. Die Spielobjekte haben die Positionen.
[/CODE]
So soll es aussehen, genau.
 

Wuast

Bekanntes Mitglied
hmmm @Wuast , wie wärs damit?
(...)

Rennt in O(n). :D
Danke für deine Überlegungen, aber ungeachtet der Anmerkungen von Kneiztel ist mir das an dieser Stelle zu viel unbekanntes. Habe es doch jetzt lösen können mit mihe7s Erklärungen und Vorschlägen.


Damit hast Du sehr schön erkannt, wie es dazu kommt, dass Code immer schlechter wird. Ist ja nur eine kleine Änderung und so unübersichtlich ist es nicht. Und wenn doch, dann hat man ja einen Kommentar dazu gepackt ... Außerdem hat man doch gerade jetzt gar keine Zeit, es richtig zu machen.

==> Ein typisches Vorgehen um mehrere unterschiedliche zufällige Elemente zu bekommen. Kann man also im Hinterkopf behalten.


Ich hoffe, ich konnte diese Punkte etwas erläutern.

Rieche ich da Sarkasmus? :D

Das typische Vorgehen werde ich mir merken!

Danke
 
K

kneitzel

Gast
Naja also wenn die Erwartung ist, den Code einfach zu halten, damit er übersichtlich und leicht lesbar bleibt, finde ich es mit meiner kaum vorhandenen Erfahrung sinnvoll, nicht für jeden Kram eine Klasse und Methode zu schreiben, sondern es kompakt zu halten
Das kann ich in keiner Weise nachvollziehen. Gerade ohne Erfahrung wirst Du kaum in der Lage sein, den stark verschachtelten Code, der ohne eben Methoden und Klassen entsteht, auch nur ansatzweise zu verstehen. Von so Dingen wie Kommentierung durch gut gewählte Bezeichner rede ich da noch nicht einmal.

Das ist ein Punkt, der von Anfang an schlicht existenziell ist und viel zu wenig gerade den Anfängern vermittelt wird.
 

Wuast

Bekanntes Mitglied
Das kann ich in keiner Weise nachvollziehen. Gerade ohne Erfahrung wirst Du kaum in der Lage sein, den stark verschachtelten Code, der ohne eben Methoden und Klassen entsteht, auch nur ansatzweise zu verstehen. Von so Dingen wie Kommentierung durch gut gewählte Bezeichner rede ich da noch nicht einmal.

Das ist ein Punkt, der von Anfang an schlicht existenziell ist und viel zu wenig gerade den Anfängern vermittelt wird.
Scheinbar. Ich glaube dir wirklich und werde es beherzigen.
In diesem Fall möchte ich nur darauf hinweisen, dass der Code im Leittext an einem Stück geschrieben ist und ich ihn gut verstehen kann (wirklich sehr einfach, ohne viel Schnickschnack). Die Leistung jetzt besteht darin, den gegebenen Code anzupassen und zu sortieren (damit er auch mit den Ergänzungen lesbar bleibt denke ich?! - wobei ich sagen muss, dass es mir leichter gefallen wäre, die Ergänzungen in der main zu implementieren, wäre eine halbe Seite Code on top gewesen und gut ist, jetzt quäl ich mich durch Klassen, Methodenaufrufe, Parameterübergaben etc. und komme mehr durcheinander als alles andere - aber wie gesagt: wenig Erfahrung und know-how).

Was mich z.B. zur Verzweiflung bringt.. ich habe jetzt in einer Klasse in einer Methode die zufälligen Punktobjekte in Abhängigkeit von Spielereingaben (Spielfeldgröße) erzeugt. Diese wird nun in der main in einer Schleife gebraucht, damit ich die Menüführung haben kann. Die Werte dieser Klasse benötige ich nun in einer anderen Klasse, welche den Spielablauf steuern soll. Der Spielstart wird über die Main in der While-Schleife gschachtelt mit einer switch case Abfrage gestartet. Wenn ich in dieser Abfrage im case ("Spielstart") die Methode Spielablauf aufrufen möchte, muss ich ja was mitgeben.
Java:
case x: spielablauf.spielfeld();
wie ich es drehe und wende, es will nicht. Wäre für mich deutlich leichter, alles in der main zu haben. :(
 
Zuletzt bearbeitet:
K

kneitzel

Gast
Wenn Du tatsächlich meinst, dass es einfacher wäre, dann mach es so. Dann ist alles in der main.

Aber hier im Thread hat man ja schon etwas gesehen, dass dies eben nicht leichter ist, denn gerade dann wird es schwer, alles mit den Schleifen und co eben sinnvoll zusammen zu setzen. Aber probiere es einfach weiter aus.

Das mit den Methoden und deren Aufrufen ist etwas, das man nur einmal verstehen muss. Das ist aber etwas, um das Du auch kaum drum herum kommst. Denn Du willst ja z.B. Dinge des Frameworks nutzen. Und da wirst Du Instanzen von diversen Klassen erstellen und darauf dann Methoden aufrufen müssen.
 

Wuast

Bekanntes Mitglied
Wenn Du tatsächlich meinst, dass es einfacher wäre, dann mach es so. Dann ist alles in der main.
Ne darf ich ja hier nicht.
Ist ja auch egal, muss ich ja nicht diskutieren. Vorgaben sind eben so und damit versuch ich nun klar zu kommmen. Was das angeht
Das mit den Methoden und deren Aufrufen ist etwas, das man nur einmal verstehen muss. Das ist aber etwas, um das Du auch kaum drum herum kommst. Denn Du willst ja z.B. Dinge des Frameworks nutzen. Und da wirst Du Instanzen von diversen Klassen erstellen und darauf dann Methoden aufrufen müssen.
dachte ich eigntl ich hab das geschnallt. Von Klasse 2 nach Klasse 1(main) ist kein Problem. Von Klasse 2 nach Klasse 3 oder Klasse 2 nach 1 und dann an 3 tu ich mich irgendwie schwerer.. :D Aber man lernt ja noch!
 
K

kneitzel

Gast
Die Frage ist dabei immer, woran es evtl. scheitert. Wichtig ist natürlich, dass man die Aufteilung richtig hin bekommt. Da ist eine gewisse Übung durchaus nicht unwichtig. Bezüglich der Herangehensweise hat mir damals das Buch "Object thinking" sehr gut gefallen. Vielleicht gibt es das ja in der Fernleihe oder so (Das Buch ist recht alt, kaufen würde ich es mir nicht - es sei denn du findest es extrem preiswert).

Aber ist schon lange her, dass ich es gelesen habe - nicht, dass meine Erinnerung verfälscht ist.
 

Wuast

Bekanntes Mitglied
Die Frage ist dabei immer, woran es evtl. scheitert. Wichtig ist natürlich, dass man die Aufteilung richtig hin bekommt. Da ist eine gewisse Übung durchaus nicht unwichtig.
Ich vermute mal: Mangelnde Erfahrung, fehlende Übung, fehlendes Know-How, kein Coding-Überflieger, bin noch nicht lange dabei, in kurzer Zeit viel Input sodass ich viel verwechsel und auch das eine oder andere vergesse und Lernen um den Alltag rum ^^ da kommt eins zum anderen.

Mein größtes Problem ist glaube ich aktuell, mit Werten und Ergebnissen einer Klasse/Methode in anderen Klassen/Methoden weiterzuarbeiten. Aber ich fuchs mich nochmal da rein..
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
B Alle Zahlen finden, die 3 bestimmte Ziffern enthalten? Java Basics - Anfänger-Themen 9
T Bestimmte Zahlen ausgeben mit einer whilfe Schleife Java Basics - Anfänger-Themen 21
I bestimmte Zahlen markieren.helppp. Java Basics - Anfänger-Themen 17
S Bestimmte werte aus einem Array löschen Java Basics - Anfänger-Themen 2
K loop pausieren für eine bestimmte Anzahl? Java Basics - Anfänger-Themen 1
Cassy3 Binäre Bäume Rekursiv durchlaufen und bestimmte Elemente Zählen Java Basics - Anfänger-Themen 6
Schniffi Nur bestimmte Bilder aus einem Array auf Image Button anzeigen lassen Java Basics - Anfänger-Themen 3
J Bestimmte parameter aus Jsonfile auslesen Java Basics - Anfänger-Themen 15
HighLife Bestimmte Werte aus Array zählen Java Basics - Anfänger-Themen 15
M Wie kann ich bei int-Variablen im exception handler auf bestimmte Strings reagieren? Java Basics - Anfänger-Themen 5
B Neue Liste erstellen, wenn Objekte bestimmte Referenz hat / Gruppierung von Einträgen Java Basics - Anfänger-Themen 12
B Nur eine bestimmte Anzahl an Arrays ausgeben Java Basics - Anfänger-Themen 9
M Regex für bestimmte Wörter bzw. bestimmte Zeichen erstellen Java Basics - Anfänger-Themen 5
B Von Array nur eine bestimmte Anzahl bekommen Java Basics - Anfänger-Themen 3
J Datei auslesen (nur bestimmte Stellen) Java Basics - Anfänger-Themen 2
L Nur Bestimmte Werte aus einem Array in ein anderes Speichern Java Basics - Anfänger-Themen 11
B Denkanstoß benötigt: Emails an bestimmte Emailadresse schicken Java Basics - Anfänger-Themen 6
U Mehrfacheingabe auf bestimmte Parameter prüfen Java Basics - Anfänger-Themen 8
L String auf bestimmte zeichen untersuchen Java Basics - Anfänger-Themen 9
L Bestimmte Werte eines Arrays ausgeben. Java Basics - Anfänger-Themen 3
P Input/Output Bestimmte Anzahl von Werten in einem Array an Methode übergeben Java Basics - Anfänger-Themen 2
Henri Bestimmte Werte eine XML-Datei ausgeben. Java Basics - Anfänger-Themen 8
M ComboBox bestimmte Elemente disablen/ausgrauen Java Basics - Anfänger-Themen 3
S JButton soll für bestimmte Zeit verschwinden Java Basics - Anfänger-Themen 5
E Datei einlesen und bestimmte Wörter ausgeben Java Basics - Anfänger-Themen 2
A Threads Threads bestimmte Aufgaben zuweisen... Java Basics - Anfänger-Themen 3
D Input/Output Buchstaben als bestimmte Zahl erkennen Java Basics - Anfänger-Themen 4
S Welche Datenstruktur ist die optimalste um Funktionen fuer bestimmte Wertebereiche abzurufen..? Java Basics - Anfänger-Themen 5
N Bestimmte Zeichen eines Strings umwandeln Java Basics - Anfänger-Themen 4
K Eine bestimmte Zeit, eine Schleife laufen lassen. Java Basics - Anfänger-Themen 4
A CSV datei eine Bestimmte Zeile ansprechen Java Basics - Anfänger-Themen 1
W char-Array auf bestimmte Zeichen prüfen Java Basics - Anfänger-Themen 10
C Array kopieren und nur bestimmte Werte speichern Java Basics - Anfänger-Themen 6
D Bestimmte Werte von Objekten aus einer ArrayList in eine andere ArrayList kopieren Java Basics - Anfänger-Themen 14
N Bestimmte Inhalte aus Datei lesen Java Basics - Anfänger-Themen 11
Ananaskirsche Input/Output Bestimmte Zeile aus Datei einlesen Java Basics - Anfänger-Themen 4
B Best Practice Bestimmte Zahl auslesen und in Variable speichern Java Basics - Anfänger-Themen 3
N Bestimmte Zeile aus einer Datei auslesen Java Basics - Anfänger-Themen 10
I Int Array, Zahl an bestimmte position setzten Java Basics - Anfänger-Themen 2
C [Bukkit Plugin] Blöcke eine bestimmte route entlang fliegen Java Basics - Anfänger-Themen 3
A Button in eine bestimmte Spalte platzieren Java Basics - Anfänger-Themen 4
D Bestimmte Zeile aus TXT Datei ausgeben Java Basics - Anfänger-Themen 4
A Eine Datei Lesen und bestimmte Position überschreiben Java Basics - Anfänger-Themen 2
M Bestimmte Zeichen auslesen Java Basics - Anfänger-Themen 2
G bestimmte dateiendungen in jtree rausfiltern Java Basics - Anfänger-Themen 7
W bestimmte Objekte in ArrayList auslesen Java Basics - Anfänger-Themen 8
G JTextArea: nur bestimmte Zeilen anders formatieren Java Basics - Anfänger-Themen 7
B Input/Output bestimmte Zeilen in .txt Dateinen überschreiben Java Basics - Anfänger-Themen 20
J Bestimmte Anzahl Zeichen aneinander fügen Java Basics - Anfänger-Themen 9
C Bestimmte Informationen von Webseite suchen Java Basics - Anfänger-Themen 13
B Nur bestimmte Klasse ausführen Java Basics - Anfänger-Themen 6
Kenan89 Bestimmte Zeile in txt-Datei ersetzen Java Basics - Anfänger-Themen 4
D BufferedInputStream nur bestimmte Zeichen Java Basics - Anfänger-Themen 11
D Input/Output bestimmte Zeile auslesen Java Basics - Anfänger-Themen 3
B Bestimmte Ziffer Java Basics - Anfänger-Themen 27
B Input/Output In Datei an eine bestimmte Stelle schreiben Java Basics - Anfänger-Themen 37
S Bestimmte Objekte aus Collections anwählen/herausbekommen Java Basics - Anfänger-Themen 8
I Bestimmte Objekte einer Liste hinzufügen Java Basics - Anfänger-Themen 16
R Bestimmte Stellen eines BigInteger Java Basics - Anfänger-Themen 7
S Collections Aus Set<Object> bestimmte Typen entfernen Java Basics - Anfänger-Themen 3
S Bestimmte Methode von unbestimmter Datei Java Basics - Anfänger-Themen 6
V Bestimmte Stellen aus .txt Datei auslesen Java Basics - Anfänger-Themen 11
B bestimmte klammern im string ersetzten Java Basics - Anfänger-Themen 17
Binary.Coder JTable bzw. Tabelle in bestimmte Form überführen Java Basics - Anfänger-Themen 5
B Bestimmte Werte aus einem String entnehmen Java Basics - Anfänger-Themen 3
0 Grafik eine bestimmte Strecke laufen lassen Java Basics - Anfänger-Themen 6
X im Verzeichnissbaum recursiv nur bestimmte Dateien finden Java Basics - Anfänger-Themen 7
M Aus String bestimmte Inhalte auslesen Java Basics - Anfänger-Themen 8
M Reaktion auf bestimmte Zeit Java Basics - Anfänger-Themen 2
2 Bestimmte Anzahl von Bytes lesen und als string ausgeben? Java Basics - Anfänger-Themen 3
N Bestimmte Zeichen aus Strings zählen Java Basics - Anfänger-Themen 11
P Bestimmte Zeilen einer Datei ermitteln ? Java Basics - Anfänger-Themen 30
StrikeTom Bestimmte stelle in string herausfiltern Java Basics - Anfänger-Themen 7
M Float auf bestimmte Nachkommazahl runden Java Basics - Anfänger-Themen 3
E Bild eine bestimmte Anzahl blinken lassen Java Basics - Anfänger-Themen 3
B array bestimmte summe berechnen Java Basics - Anfänger-Themen 4
Luk10 Zufallszahl "ohne" eine bestimmte Zahl(en) Java Basics - Anfänger-Themen 8
S OOP Wie bei Spiel "17+4" eine Karte an bestimmte Position hinzufügen Java Basics - Anfänger-Themen 13
B OOP String auf bestimmte Zeichen abfragen Java Basics - Anfänger-Themen 4
S Bestimmte Elemente einer ArrayList löschen Java Basics - Anfänger-Themen 3
S Double bis bestimmte Nachkommzahl vergleichen (ohne zusätzliche Libs) Java Basics - Anfänger-Themen 12
Ollek Bestimmte Zeilen aus einer HTML Datei lesen Java Basics - Anfänger-Themen 8
N Text an bestimmte Stelle eines Dokuments schreiben Java Basics - Anfänger-Themen 6
G Bestimmte Zeile aus CSV ausgeben Java Basics - Anfänger-Themen 14
Assassin Nur bestimmte Daten aus txt auslesen... Java Basics - Anfänger-Themen 12
Developer_X Durch int Bestimmte Zeile überschreiben Java Basics - Anfänger-Themen 16
Developer_X Bestimmte Zeile aus TextDocument lesen Java Basics - Anfänger-Themen 2
V Nur bestimmte Werte zulassen Java Basics - Anfänger-Themen 2
M Bestimmte zeile aus .txt einlesen Java Basics - Anfänger-Themen 6
Q Nach Stringvorgabe bestimmte funktionen ausführen Java Basics - Anfänger-Themen 3
G Bestimmte Ebene eines Baumes rekursiv ausgeben Java Basics - Anfänger-Themen 49
G Bestimmte Position im array auslesen Java Basics - Anfänger-Themen 8
H bestimmte objekte in ArrayList löschen? Java Basics - Anfänger-Themen 7
P Hilfe für JComboBox, bmp einbinden/bestimmte punkte auf bmp Java Basics - Anfänger-Themen 3
M bestimmte Zeichen in String eliminieren Java Basics - Anfänger-Themen 2
T Bestimmte Zeile aus einer .txt-Datei auslesen? Java Basics - Anfänger-Themen 10
S Bestimmte Anzahl an nummern auslesen Java Basics - Anfänger-Themen 4
K bestimmte Dateien aus Ordner verschieben Java Basics - Anfänger-Themen 5
F Bestimmte Werte nicht beachten Java Basics - Anfänger-Themen 10
G bestimmte Stelle aus Textdatei auslesen. Java Basics - Anfänger-Themen 7

Ähnliche Java Themen

Neue Themen


Oben