# Lottozahlen



## javastudent25 (11. Feb 2016)

Hallo Freunde

Mich hat es mal interessiert einen Lottozahlenzufallsgenerator zu programmieren und der Algorithmus, wie doppelte Einträge vermieden werden.

Der Code ist sicher sonst auch verbesserungswürdig, aber ich bekomme es irgendwie auch ideentechnisch nicht auf die Reihe, es zu vermeiden, dass doppelte Zahlen vorkommen.
Irgendwie habe ich das Problem, dass ich zwar Schritt für Schritt vorgehe und bei Differenz 0 eine neue Zahl generiere, aber dann auch wieder zurück gehen muss um zu prüfen, ob er nicht eine neue Zahl generiert hat, die zuvor irgendwo war...
hmm, irgendwie lustig, ich steh da voll daneben.

Es ist die Methode entferneGleicheZahl()


```
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Random;

public class eugen {
    static int zahl = 0;
    static int num = 0;
    static String name1;
    static int alter;
    static String begriff;
    static int[] zufallsZahlen = new int[6];
    static Random rand = new Random();
    static int x = 0;

    public static void main(String[] args) {
        erzeugeZahl();
        entferneGleicheZahl();
        zahlenAusgeben();
    }

    public static void entferneGleicheZahl() {
        int s = 0;
        int m = 1;
        int i;
        int y;

        for (y = 0; y < (zufallsZahlen.length - 1); y++) {
            s = zufallsZahlen[y];
            for (i = m; i < zufallsZahlen.length; i++) {
                while ((s - zufallsZahlen[i]) == 0) {
                    zufallsZahlen[i] = rand.nextInt(42) + 1;
                    for (int b = i; b > 0; b--) {
                        if ((zufallsZahlen[b] - zufallsZahlen[b - 1]) == 0) {
                            while ((zufallsZahlen[b] - zufallsZahlen[b - 1]) == 0) {
                                zufallsZahlen[b - 1] = rand.nextInt(49) + 1;
                            }
                        }
                    }
                }
                m++;
            }
        }
    }

    public static void zahlenAusgeben() {
        Arrays.sort(zufallsZahlen);
        for (int i = 0; i < zufallsZahlen.length; i++) {
            System.out.print(zufallsZahlen[i] + " ");
        }
    }

    public static void erzeugeZahl() {
        int i = 0;

        for (i = 0; i < zufallsZahlen.length; i++) {
            num = rand.nextInt(42) + 1;
            zufallsZahlen[i] = num;
        }
    }

    public static void erzeugeGlueckszahl() {
        int glk1 = 0;
        int glk2 = 0;
        int a;
        for (int i = 0; i < 1; i++) {
            a = rand.nextInt(6) + 1;
            if (i == 0) {
                glk1 = a;
            }
        }
        zufallsZahlen[6] = glk1;
    }
}
```


----------



## kneitzel (11. Feb 2016)

Also dein Vorgehen verstehe ich hier jetzt nicht ganz. Dein Algorithmus ist ja mehr als komplex und das kann ich im Augenblick nicht nachvollziehen.

Also als erstes würde ich bemängeln, dass es nicht objektorientiert ist. Da würde ich dran arbeiten.

Dann sehe ich zwei Möglichkeiten, wie man sinnvoll vorgehen kann:
a) Direkt bei der Erzeugung einer Zufallszahl wird die Gültigkeit geprüft. Also direkt mit jeder neuen Zahl wird geprüft, ob diese schon vorkommt. Dann hat man einen ganz einfachen Algorithmus:
- Solange noch keine 6 Zahlen gezogen wurden:
-- Ziehe eine Zahl
-- Falls Zahl noch nicht in gezogenen Zahlen, dann füge Zahl hinzu
Ganz trivial und einfach zu verstehen. Anders als Deine verschachtelten Schleifen.

b) Du kannst es so machen, wie es auch physikalisch funktioniert. Du hast ein Array von Lottokugeln (int Werte). Du initialisierst die Werte von 1 bis 49 (Wie kommst Du auf 42 oder habe ich mich versehen?). Und wenn Du feste Arrays nutzt, dann musst Du noch merken, wie viele Kugeln vorhanden sind.
Nun ziehst Du eine Kugel:
- Zufallszahl ermitteln (1-Anzahl Kugeln). 
- Nun merkst Du den Wert der Kugel (Array-Element von Zufallszahl-1 auslesen)
- Nun schiebst Du die letzte Kugel an die Stelle (Also den Wert von AnzahlKugeln -1 in Zufallszahl-1 schreiben)
- AnzahlKugeln um 1 reduzieren.
Dann hast Du einfach die physikalische Maschine im Code umgesetzt.

Allgemeine Hinweise:
- Sobald du mehr als 2 Schleifen verschachtelt hast, dann hast Du schon unleserlichen Code und Du hast es umzuschreiben! Lager Dinge in Funktionen aus! Ich habe nur eine Schleife in meinem angegebenen Algorithmus, aber die Unterfunktionen können natürlich jeweils auch wieder Schleifen enthalten. Aber das sieht man denn nicht direkt sondern hat alles schön übersichtlich.
- Wähle gute Namen für deine Variablen. Ist ja absolut grausig!


----------



## javastudent25 (11. Feb 2016)

Hallo Konrad

Danke für deine schnelle Reaktion.
Es ist mir im Moment auch weniger darum gegangen, alles objektorientiert zu gestalten, da mir der Vorgang des doppelten Eintrags wichtig war.
Fall a verstehe ich und ich weiss man sollte sich das Leben nicht allzu schwer machen, aber ich möchte den Algorithmus trotzdem so haben, wenn die Zahlen gezogen und im Array sind.

Fall b habe ich mir jetzt 3 mal durchgelesen, aber irgendwie leuchtet mir nicht ein, was 
Zufallszahl-1, 1-Anzahl KUgeln, und AnzahlKugeln-1 in Zufallszahl-1 sein soll.
kannst du das mal vllt so schreiben Array[i-1] oder sowa?

PS: 42 deshalb, weil wir in der Schweiz zu wenig Kugeln haben...  Österreich liegt da sogar 3 Punkte vorn.
Aber ihr, das Deutsche Reich, seid die Führer. Hat wohl anscheinend mit der Fläche der einzelnen Länder zu tun


----------



## kneitzel (11. Feb 2016)

Also Du hast ein Array kugeln vom typ int[], Größe 42. Das füllst Du mit den Zahlen von 1 - 42.

Nun kannst Du eine Zahl ziehen. Dazu brauchst du eine Zufallszahl, die die Kugel angibt. Diese kann von 1-42 oder von 0 - 41 gehen - ist prinzipiell egal.
Dann hast Du die kugel ermittelt, indem Du einfach den Inhalt aus dem Array an der entsprechenden Position ausliest.
Da die Kugel nun aus dem Spiel ist, musst Du diese entfernen. Also stecken wir die letzte Kugel einfach an diese Stelle. Und nun haben wir eine Kugel weniger.
Also wird bei der zweiten Kugel nun eine Zahl von 1 - 41 ermittelt.

Ist also relativ einfach und entspricht zumindest der Lotto Ziehung wie wir diese in Deutschland haben. Da werden halt die Kugeln in eine Maschine gesteckt wo sie herum gewirbelt werden und dann wird eine Kugel entnommen. Danach ist halt eine Kugel weniger in der Maschine und von den verbliebenen Kugeln wird nun wieder eine entnommen. Und das so lange, bis man die gewünschten Kugeln hat.


----------



## StrammerMax93 (11. Feb 2016)

Habe mal ein Lottospiel in der Schule programmiert.


```
package lotto.fachklassen;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class LottoLogik {

   private LottoLogik () {
     //verstecke Konstruktor, da dies eine reine Hilfsklasse ist.
   }
 
 
   /**
    * Diese Methode erzeugt ein Array mit 6 Zufallszahlen aus dem Bereich 1 - 49.
    *
    * @return Array mit 6 Zufallszahlen aus dem Bereich 1 - 49.
    */
   public static int[] generiereLottozahlen() {       
     int[] zahlen = new int[49]; // 49 Lottozahlen, zunächst alle = 0
     //Nun initialisiere den Wert der Zellen mit dem Index
     for (int i=0; i<49; i++) zahlen[i] = i+1; //
    // Ziehung von 6 aus 49
    int h, z;
    for (int i=0; i<6; i++) {
    z = (int) (Math.random()*(49-i)); // Zufallszahl aus Bereich 0 bis 48-i
    h = zahlen[z];
    zahlen[z] = zahlen[48-i];
    zahlen[48-i] = h; // Zahlen an den Plätzen z und 48-i werden getauscht.
    }
    //Mit diesem Algorithmus können keine doppelten Werte vorkommen.
    //Der Trick ist, das man den Index verwendet für die Ermittlung der Zufallszahl und nicht die Zahl selbst.
    //Hierzu wird der Wert im Array des gezogenen Index ausgetauscht mit dem Wert aus dem Index des letzten Feldes
    //das noch an der Ziehung teilgenommen hat. Dieses letzte Feld nimmt in der nächsten Ziehung nicht mehr teil,
    //da der Bereich der Zufallszahlen um 1 reduziert wurde.
   
   
    //jetzt fehlt noch die Sortierung
    //zunächst mal die nach hinten sortierten Zahlen in ein neues Array kopieren
    int[] ergebnis = Arrays.copyOfRange(zahlen, 43, 49);
    //nun dieses Array sortieren
    Arrays.sort(ergebnis);
    //sortiertes ergebnis zurückliefern
    return ergebnis;
   }
 
   
   /**
    * Diese Methode liefert die übereinstimmenden Zahlen beider Teilmengen zurück.
    * Entspricht der Schnittmenge beider Arrays.
    *
    * @param tippSet Menge stellt Tipp dar.
    * @param ziehung Menge stellt gezogene Zahlen dar.
    * @return array mit übereinstimmenden Zahlen
    */
   public static Set<Integer> berechneTrefferListe(Set<Integer> tippSet, int[] ziehung) {
     Set<Integer> treffer = new HashSet<Integer>();
     for (int i=0; i < ziehung.length; i++) {
       for (int tipp : tippSet) {
         if (ziehung[i] == tipp) {
           treffer.add(ziehung[i]);
         }
       }
     }
     return treffer;
   }
}
```




Bei Bedarf kann ich auch das ganze Projekt hochladen.
Ist mit UI umgesetzt.


----------



## javastudent25 (11. Feb 2016)

StrammerMax93 hat gesagt.:


> Habe mal ein Lottospiel in der Schule programmiert.



Hallo Max
Zum Chinesen werde ich erst, wenn ich das verstanden habe, was ich gerade vorhabe 
Aber trotzdem danke für deine Hilfe 
Ich werds mir dann ansehen


----------



## javastudent25 (11. Feb 2016)

Ok, Konrad ich habe in der Zwischenzeit mal an Aufgabe a gebastelt.
Aber irgendwie schaff ich das nicht mal irgendwie.
Der Code müsste so ein wenig übersichtlicher sein..
Nach der 1. Zahl kommen ein Haufen gleiche Zahlen


```
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Random;

public class eugen {

    public static void main(String[] args) {
        zahlenAusgeben(erzeugeZahlenArray());
    }

    public static void zahlenAusgeben(int[] x) {     
        int[] zufallsZahlen = x;
        Arrays.sort(zufallsZahlen);
        for (int i = 0; i < zufallsZahlen.length; i++) {
            System.out.print(zufallsZahlen[i] + " ");
        }
    }

    public static int[] erzeugeZahlenArray() {     
        int y = 0;
        int zaehler=0;
        int[] zufallsZahlen = {0, 0, 0, 0, 0, 0, 0};
        Random rand = new Random();
        int num;

        while(zaehler != 6){         
            num = rand.nextInt(42) + 1;
            for (y = 0; y < (zufallsZahlen.length-1); y++) {
                if(zufallsZahlen[y] != num){
                zufallsZahlen[zaehler] = num;
                }
                zaehler++;
            }         
        }
        erzeugeGlueckszahl(zufallsZahlen, rand);
        return zufallsZahlen;
    }

    public static void erzeugeGlueckszahl(int[] x, Random z) { 
        int a;
        Random rand = z;
        int[] zufallsZahlen = x;     
        a = rand.nextInt(6) + 1;
        zufallsZahlen[6] = a;
    }
}
```


----------



## javastudent25 (11. Feb 2016)

achh, jetzt habs ich glaub ich


----------



## kneitzel (11. Feb 2016)

Deine Schleife zur Prüfung, ob die Zahl schon vorhanden ist, macht nicht das, was sie soll. Spiel diese Schleife einmal in Gedanken durch.


----------



## StrammerMax93 (11. Feb 2016)

javastudent25 hat gesagt.:


> Hallo Max
> Zum Chinesen werde ich erst, wenn ich das verstanden habe, was ich gerade vorhabe
> Aber trotzdem danke für deine Hilfe
> Ich werds mir dann ansehen


Das tut doch genau das was du vorhast?
Es erstellt dir die Zahlen ohne dabei doppelte zu genrieren.
Und wirklich komplex ist das auch nicht.


----------



## thecain (11. Feb 2016)

Mach doch einfach ein Set und füll solange zahlen rein bis es 6 sein, dann das ganze zu einem Array umwandeln...


----------



## javastudent25 (11. Feb 2016)

Ich muss es mir morgen nochmals anschauen, ich komme nicht drauf, was mein Fehler ist..
Irgendwie habe ich heute ein Brett vor dem Kopf..
Wenn ich halb krank bin, sollte ich glaub einfach nicht aus Langeweile programmieren.. 

Aber die beiden Varianten von Konrad muss ich schon noch irgendwie herbringen
Mal sehen..


```
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Random;

public class eugen {

    public static void main(String[] args) {

        zahlenAusgeben(erzeugeZahlenArray());

    }

    public static void zahlenAusgeben(int[] x) {
       
        int[] zufallsZahlen = x;
        Arrays.sort(zufallsZahlen);
        for (int i = 0; i < zufallsZahlen.length; i++) {
            System.out.print(zufallsZahlen[i] + " ");
        }

    }

    public static int[] erzeugeZahlenArray() {
       
        int y = 0;
        int zaehler=0;
        int[] zufallsZahlen = {0, 0, 0, 0, 0, 0, 0};
        Random rand = new Random();
        int num=0;
        int a=0;

        while(zaehler !=  6){
           
                num = rand.nextInt(42) + 1;
                       
            for (y = 0; y < (zufallsZahlen.length-1); y++) {
                if((num - zufallsZahlen[y]) == 0){
                a=1;
                }
                if(a==1){
                    zufallsZahlen[zaehler] = num;
                    a=0;
                    zaehler++;
                }
            }
           
           
        }
        erzeugeGlueckszahl(zufallsZahlen, rand);
        return zufallsZahlen;

    }

    public static void erzeugeGlueckszahl(int[] x, Random z) {
   
        int a;
        Random rand = z;
        int[] zufallsZahlen = x;
       
        a = rand.nextInt(6) + 1;
        zufallsZahlen[6] = a;

    }

}
```


----------



## void_nutzer16 (12. Feb 2016)

Hi,
ich hab mir zwar die ganzen Codes nicht angesehen, aber spontan würde ich folgendes vorschlagen:

Speichere doch jede Zufallszahl nacheinander in ein Array. Jede neue Zahl wird - bevor sie eingespeichert wird - mit allen bisherigen Zahlen verglichen. Sobald eine Übereinstimmung vorliegt wird die Zahl sofort verworfen und es geht wieder zur Ziehung einer neuen Zahl.



```
public class Zufallszahlen {
    static Random rand = new Random();
 
    //Methode für die Ziehung
    static int erzeugeZahl() {
        int zahl = rand.nextInt(48)+1;
        return zahl;
    }
 
    public static void main(String[] args) {
        int lottozahlen [] = new int [6];
     
        //äußere Schleife --> hier 6 Durchläufe für 6 Zahlen
        meinLabel: for(int i = 0; i < lottozahlen.length; i++) {
            int zwischenspeicher = erzeugeZahl();
         
            //innere Schleife vergleicht neue Zahl mit breits gezogenen Zahlen
            for(int k = 0; k <= i; k++) {
                if(zwischenspeicher == lottozahlen[k])
                    continue meinLabel; //Abbruch bzw Zahl wird verworfen
             
                lottozahlen[i] = zwischenspeicher;
            }
        }
     
        for (int j: lottozahlen) {
            System.out.println(j);
        }
    }
}
```


Bin selber erst seit kurzem am Java lernen, deswegen ist das bestimmt kein schöner/sauberer objektorientierter Ansatz, aber es funzt 

Grüße


----------



## kneitzel (12. Feb 2016)

Erst einmal eine korrekt aussehende Lösung. Ich würde da aber gerne noch ein paar Worte zur Lesbarkeit verlieren:

Also aus meiner Sicht solltest Du Label komplett vergessen! Das macht den Code in meinen Augen extrem unleserlich!

Das wurde bei Dir ja nur notwendig, weil Du nicht mehr die feste Anzahl an Durchgängen hast sondern nun plötzlich mehrere Durchgänge brauchst. Also wäre die logische Konsequenz, statt for schleife eine while (oder do while) Schleife zu verwenden:

```
//äußere Schleife --> hier 6 Durchläufe für 6 Zahlen
      int i = 0; // i sollte besser etwas wie "gezogeneLottozahlen" oder so sein. i sagt ja nichts aus!  
      while(i  < lottozahlen.length){
           int zwischenspeicher = erzeugeZahl();
         
           // Statt innerer Schleife eine Funktion!
           if (!arrayContains(lottozahlen, i, zwischenspeicher))
           {
                lottozahlen[i]= zwischenspeicher;
                i++;
           }
       }
```
Und die Funktion arrayContains wäre dann einfach:

```
public static boolean arrayContains(int[] array, int maxIndex, int value) {
    for (int index=0; index < maxIndex; index++) {
        if (array[index] == value) return true;
    }
    return false;
}
```

Hinweise:
- Deine innere Schleife prüfte auf <= und hat damit einen Wert zuviel geprüft.
- Diese Version ist deutlich lesbarer. Alleine schon, dass eine Verschachtelung weniger da ist, ist dies so deutlich lesbarer. (Die Alternative wäre tatsächlich so ein "continue" oder eben die Einführung einer Hilfsvariable.)

Das nur als kleine Hinweise zur Lesbarkeit Deines Codes.

Konrad


----------



## nvidia (12. Feb 2016)

Das geht mit etwas Nachdenken alles viel einfacher. Was sind Lottozahlen? Lottozahlen sind eine Liste von Zahlen in einem bestimmten Intervall aus denen n Stück zufällig gezogen werden. Wie modelliert man das am einfachsten?

1. Liste mit Zahlen von 1-49 generieren (per Stream oder For-Schleife)
2. Liste mischen
3. Die ersten 6 Zahlen auslesen und sortiert ausgeben



```
public class Lotto {
    public static void main (String ... args){
        //1. Lottozahlen von 1-49 generieren
        List<Integer> lottozahlen = IntStream.range(1, 50).boxed().collect(Collectors.toList());
        //2. Liste mischen
        Collections.shuffle(lottozahlen);
        //3.Die ersten 6 Zahlen auslesen
        List<Integer> ziehung = lottozahlen.subList(0, 6);
        // und Sortieren
        Collections.sort(ziehung);
        System.out.print(ziehung);
    }
}
```


----------



## thecain (12. Feb 2016)

Nach einer Nacht drüber schlafen 


```
final int[] ints = new Random().ints(1, 50).distinct().limit(6).toArray();
```


----------



## kneitzel (12. Feb 2016)

Das erinnert mich an die Zeit, in der ich in einigen MSDN Foren aktiv wa. Im c# Bereich war jemand aktiv, der bei reinen Hausaufgaben-Fragen immer versuchte, so eine Antwort zu bringen. 100% korrekt und es ist klar, dass der Lehrer die Aufgabe nicht als erfüllt ansah und wo auch klar war, dass es nicht vom Schüler gekommen ist


----------



## Schwupsi (12. Feb 2016)

Habe auch ein Lotto Programm geschrieben vor paar Monaten zur Übung.
Sieht ungefähr so aus:

Die Box quasi mit Kugeln von 1-49 füllen


```
public static void initZahlen(){
     
     for(int i = 1; i<=49; i++)
       getLottozahlen().add(i);
     //   System.out.println("Array gefüllt!");
   }
```

Die Zahlenziehung und das Entfernen bereits vorgekommener Zahlen aus der "Box"


```
public void Ziehung(){
       
        Random random = new Random();
        int random_number;
        setListSize(49);
       
        for(int i = 0; i<ziehung.length; i++){
           
            random_number = random.nextInt(list_size);
            //ziehung[i] = LottoZahlen.Lottozahlen.get((int)((Math.random()*list_size)+1));
            ziehung[i] = LottoZahlen.getLottozahlen().get(random_number);
            LottoZahlen.getLottozahlen().remove(random_number);
            list_size--;
        }
       
    }
```


----------



## JStein52 (12. Feb 2016)

Spontan hätte ich ja auch eine Lösung mit einer Liste von Zahlen vorgeschlagen die am Anfang  mit den Zahlen von 1 - 49 gefüllt wird. Dann wird gewürfelt und die gewürfelte Zahl wird aus der Liste entfernt undf als Ergebnis gemerkt.
Aber der Einzeiler von @thecain ist echt der Hit !


----------



## Schwupsi (12. Feb 2016)

Stimmt! Sehr stark


----------



## Thorwine (15. Feb 2016)

Bin ja auch anfangender Umsteiger oder umsteigender Anfaenger in Java, wie man's nimmt. Hab hier grad ein Lottozahlen Projekt aus einem Buch durchgearbeitet, der Erguss kommt also nicht von mir, sondern aus dem Buch "Java fuer Kids". Auch wenn ich dem "Kids" Alter schon etwas entwachsen bin, kann ich die Lektuere sehr empfehlen!


```
public class Lotto {

    public static void main(String[] args) {
        // Konstanten
        final int ANZAHL = 6;
        final int MAX = 49;
        // Lottozahlen Array
        int[] lottozahl = new int[MAX + 1];
        // Zufallszahl
        int zufall = 0;

        // Alle Werte im Array auf 0 setzen (noch nicht gezogen)
        for (int count = 1; count < lottozahl.length; count++)
            lottozahl[count] = 0;

        // Sechs Zahlen "ziehen"
        for (int count = 1; count <= ANZAHL; count++) {
          
            // noch nicht verwendete Zufallszahl suchen
            do {
                zufall = (int) (Math.random() * MAX) + 1;
            } while (lottozahl[zufall] == 1);

            // benutzte Zahl als gezogen markieren
            lottozahl[zufall] = 1;
          
            // Ausgabe
            System.out.println(count + ". Ziehung: " + zufall);
        }
    }
}
```


----------



## kneitzel (15. Feb 2016)

Also kleines Feedback zu Deinem Programm Thorwine:
a) Namensgebung der Variablen: Sieht schon recht gut aus. lottozahl ist etwas unschön. In dem Array ist ja nicht eine lottozahl sondern das ist gezogeneLottozahlen oder so. Ebenso zufall - das ist ja eine zufallszahl. Aber schon eine super Namenswahl.
b) Typenwahl. Ein Array, das nur MAX element speichern soll, sollte auch nur MAX groß sein. Ansonsten muss man den Index immer -1 nehmen oder so. Desweiteren: Wenn Du nur 0/1 als Werte hast, dann ist int der falsche Typ. Da ist boolean ja deutlich besser mit true/false.


----------



## Thorwine (15. Feb 2016)

Korrigierte Fassung:


```
public class Lotto {

    public static void main(String[] args) {
        // Konstanten
        final int ANZAHL = 6;
        final int MAX = 49;
        // Lottozahlen Array
        boolean[] gezogeneLottozahlen = new boolean[MAX];
        // Zufallszahl
        int zufallszahl = 0;

        // Alle Werte im Array auf 0 setzen (noch nicht gezogen)
        for (int count = 0; count < gezogeneLottozahlen.length; count++)
            gezogeneLottozahlen[count] = false;

        // Sechs Zahlen "ziehen"
        for (int count = 1; count <= ANZAHL; count++) {

            // Neue Zufallszahl suchen...
            do {
                zufallszahl = (int) (Math.random() * MAX) + 1;
            }
            while (gezogeneLottozahlen[zufallszahl] == true);

            // benutzte Zahl als gezogen markieren
            gezogeneLottozahlen[zufallszahl] = true;

            // Ausgabe
            System.out.println(count + ". Ziehung: " + zufallszahl);
        }
    }
}
```


----------



## kneitzel (15. Feb 2016)

Da hast Du jetzt aber einen Punkt übersehen. Wenn der MAX Wert gezogen wird, dann bekommst Du eine ArrayOutOfBoundException.
Die Zufallszahl geht von 1 - 49
Dein Array gezogeneLottozahlen geht von 0 - 48
Das musst Du bei Zugriffen beachten. Wenn Zufallszahl 1 ist, willst Du ja in das erste Feld schreiben. Bzw. das erste Feld prüfen. Und das ist Feld 0.
Also müsstest Du diese Zugriffe auch noch anpassen.


----------



## Xyz1 (15. Feb 2016)

Wieso denn Counting Sort? Wieso nicht:
Liste mischen,
2 Listen,
Set,
n Folgen, wobei in (n-1). keine doppelten vorkommen?
Nur, um ein paar Beispiele zu nennen.

```
int[] intArr = new int[6]; // 6 bitte nicht ändern :-)
        a: while (true) {
            for (int i = 0; i < intArr.length; i++) {
                intArr[i] = (int) func1(1, 49);
            }
            for (int i = 0; i < intArr.length - 1; i++) {
                for (int j = i + 1; j < intArr.length; j++) {
                    if (intArr[i] == intArr[j]) {
                        continue a;
                    }
                }
            }
            break a;
        }
        System.out.println(Arrays.toString(intArr));
```
Meine Funktion func1 sieht bei mir so aus:

```
private static float func1(int f, int t) {
        return (float) (Math.random() * (t - f + 1) + f);
    }
```
Ohnehin braucht random() nur einmal Nanotime.

Btw. Euer nicht reicher Text-Editor ist echt mies für die Augen.


----------



## Thorwine (15. Feb 2016)

Aehm, dann geh ich bei der Pruefung und Zuweisung der Felder im Array einfach eins runter. Ich hoffe, das ist jetzt nicht gepfuscht. Funktionieren tut's so, auch mit den Ziehungen der 1 und der 49. Diese werden jetzt in Feld 0 und Feld 48 geschrieben.


```
public class Lotto {

    public static void main(String[] args) {
        // Konstanten
        final int ANZAHL = 6;
        final int MAX = 49;
        // Lottozahlen Array
        boolean[] gezogeneLottozahlen = new boolean[MAX];
        // Zufallszahl
        int zufallszahl = 0;

        // Alle Werte im Array auf 0 setzen (noch nicht gezogen)
        for (int count = 0; count < gezogeneLottozahlen.length; count++)
            gezogeneLottozahlen[count] = false;

        // Sechs Zahlen "ziehen"
        for (int count = 1; count <= ANZAHL; count++) {

            // Neue Zufallszahl suchen...
            do {
                zufallszahl = (int) (Math.random() * MAX) + 1;
            }
            while (gezogeneLottozahlen[zufallszahl-1] == true);

            // benutzte Zahl als gezogen markieren
            gezogeneLottozahlen[zufallszahl-1] = true;

            // Ausgabe
            System.out.println(count + ". Ziehung: " + zufallszahl);
        }
    }
}
```


----------



## thecain (15. Feb 2016)

DerWissende hat gesagt.:


> Nur, um ein paar Beispiele zu nennen.
> 
> ```
> int[] intArr = new int[6]; // 6 bitte nicht ändern :-)
> ...



Dein code ist echt mies für die Augen. "jump to", while(true).

Mir ist egal wie andere ihren Code schreiben, aber es dann Anfängern so zu empfehlen... Bitte nicht.


----------



## Xyz1 (15. Feb 2016)

thecain hat gesagt.:


> Dein code ist echt mies für die Augen. "jump to", while(true).
> 
> Mir ist egal wie andere ihren Code schreiben, aber es dann Anfängern so zu empfehlen... Bitte nicht.



Die besten Kommentare sind keine Kommentare, ich mag das von Thorwine nicht mal lesen, weil es einfach überflüssig ist, jede Zeile zu kommentieren.

Zu dem Rest: Ich presse da kein boolean rein, zu unübersichtlich. for (; { wäre noch eine Alternative.

Wählt man n zu groß, hält das Programm leider nicht an. *heul schluchz flenn*


----------



## kneitzel (15. Feb 2016)

@Thorwine: Super! Genau so meinte ich es! Jetzt hätte ich an Deinem Code keine Auffälligkeiten, die ich anders schreiben würde.

@DerWissende: Ich habe echt Probleme Deine Aussage zu verstehen. Der Code selbst ist aber absolut unleserlich und nach meinem Verständnis schlicht schrott:
- Die Nutzung von Label in Java ist etwas, das in meinen Augen jeden Entwickler direkt disqualifiziert. Ich sehe für so einen Spagetticode keine Veranlassung und das ist auch bei fremden Code für mich nicht diskutabel.
- Variablennamen vernünftig wählen,  ist hier im Thread oft genug angesprochen worden.
- Dein Code ist extrem verwirrend - Du hast eine Endlosschleife gebaut, dabei wird die Schleife maximal einmal komplett durchlaufen (Du magst mehrfach hoch springen aber sonst?)
- Wenn nur eine Lottozahl doppelt ist, dann fängst Du von vorne an und ermittelst 6 neue Lottozahlen. Vom Algorithmus her ist das alles andere als gut.
- Die Verschachtelungstiefe ist schon zu hoch. Wenn so ein Algorithmus, dann doch bitte mit Unterteilung in Funktionen. Immer noch ganz mangelhaft, aber besser wäre:

```
int[] lottoZahlen;
do {
  lottoZahlen = createRandomIntArray(6, 1, 49);
} while (containsDoubleValues(lottoZahlen));

// ...

public static int[] createRandomIntArray(int size, int min, int max) {
  int[] result = new int[size];
  for (int index = 0; index<size; index++)
    result[index] = generateRandomNumber(min, max);
  return result;
}

public static int generateRandomNumber(int min, int max) {
  return (int) (Math.random()*(max - min +1) + min);
}

public static boolean containsDoubleValues(int[] array) {
  for (int lowIndex = 0; lowIndex < array.length-1; lowIndex++) {
    for (int highIndex = lowIndex+1; highIndex < array.length; highIndex++) {
      if (array[lowIndex] == array[highIndex])
        return true;
    }
  }
  return false;
}
```
Das nur um die Unterteilung zu zeigen. Die Funktionen am Ende sind weniger optimiert. Der Algorithmus ist jetzt aber direkt zu verstehen.


----------



## Xyz1 (15. Feb 2016)

kneitzel hat gesagt.:


> Die Funktionen am Ende sind weniger optimiert. Der Algorithmus ist jetzt aber direkt zu verstehen.



Nein(!), ist er nicht. Nicht mal ansatzweise eine Verbesserung.

Da wir schon bei "blöden" Lösungen waren, hab ich einfach mal eine beigesteuert.

Natürlich ist besser: (Achso, muss ich mich selber zitieren



DerWissende hat gesagt.:


> Liste mischen,
> 2 Listen,
> Set,



Grüße


----------



## Thorwine (15. Feb 2016)

kneitzel hat gesagt.:


> @Thorwine: Super! Genau so meinte ich es! Jetzt hätte ich an Deinem Code keine Auffälligkeiten, die ich anders schreiben würde.


Super, vielen herzlichen Dank fuer die konstruktive Kritik (wieder mal!)


----------



## kneitzel (15. Feb 2016)

Also dass die Kommentare bei Thorwine überflüssig sind, da der Code selbst erklärend ist, ist richtig. Hätte man so sagen können.

Aber ich verstehe nicht, was Du meintest, beitragen zu müssen. Eine gute Lösung braucht kein "Liste Mischen" und keine 2 Listen und auch kein Set. Hättest Du den Thread gelesen, dann hättest Du eine gute Lösung gesehen. 

Und was "blöde Lösungen" angeht - da sollten wir einmal genau überlegen, was denn eine blöde Lösung ausmacht. Die Algorithmen, die hier von diversen Anfängern beigesteuert wurden, würde ich nicht als solche bezeichnen. Und Hinweise zu Clean Code sind auf jeden Fall sinnvoll. Aber das werde ich jetzt nicht weiter erläutern, denn die Diskussion / Auseinandersetzung mit Dir ist für mich an dieser Stelle vorbei. Mich würde zwar prinzipiell noch interessieren, was Du meintest beitragen zu können / müssen, aber andererseits ist mir dazu meine Zeit zu schade.

Ich wünsche noch einen schönen Abend.


----------



## Thorwine (15. Feb 2016)

DerWissende hat gesagt.:


> Die besten Kommentare sind keine Kommentare, ich mag das von Thorwine nicht mal lesen, weil es einfach überflüssig ist, jede Zeile zu kommentieren.


Sorry, bin noch nicht so der Profi und die Kommentare sind fuer mich persoenlich noch sehr wichtig als Gedankenstuetze und um die Sache in ein paar Wochen auch noch nachvollziehen zu koennen. Aber ich kann die Kommentare in meinen Posts hier im Forum ja zukuenftig vor dem Posten rausloeschen, das sollte kein Problem sein. Dennoch bin ich sehr froh, dass zB @kneitzel meinen Code liest und mir gute Tipps gibt. Des Weiteren hab ich gelernt, dass Kommentare durchaus gewuenscht sind. Bei uns in der Firma bekommen die Entwickler boese auf die Finger, wenn sie ihren Code nicht kommentieren.


----------



## Flown (15. Feb 2016)

@Thorwine bitte behalte dir deinen Stil bei. Wenn es dir eine Stütze ist Gedanken aufzuschreiben und Schritte zu kommentieren, dann soll es so sein (vl. hilft es anderen Anfängern genau so).

An alle anderen: Bleibt sachlich! Keiner muss hier beweisen, wer den besseren/kürzesten Code schreiben kann. Klar im Vordergrund sollte stehen:
- Den Fragenden helfen
- Code anzusehen und Verbesserungsvorschläge bieten!
- Feedback geben und auch erhalten können (und damit auch leben können)!
- Klare Fakten bieten und keinen Sarkasmus/etc.
- Alles klar verständlich ausformulieren und keine Stichworte bieten
- Code den man bereitstellt auch in Javadoc oder außerhalb erklären und kommentieren

PS: Wenn das Thema hier weiter ausartet, wird es geschlossen


----------



## kneitzel (15. Feb 2016)

@Thorwine: Also Du musst die Kommentare nicht löschen! Das ist vollkommen in Ordnung aus meiner Sicht! Daher gab es diesen Punkt von meiner Seite aus nicht! Nur eben ist dieser Punkt, der von dritter Seite angebracht wurde, durchaus legitim. 

Die Idee beim Clean Code ist aber, dass der Code selbst so geschrieben ist, dass er gut lesbar ist. Dann sind die Kommentare nicht mehr notwendig. Und die Probleme durch Kommentare werden vermieden. Probleme gibt es einige:
a) Ungenaue Kommentare - Wenn man einen Kommentar schreibt, dann ist der Kommentar evtl. zu ungenau. Dann steht im Kommentar: "Auto wird lackiert" und der Code klebt die Scheiben ab und lackiert dann das Auto. Kleinigkeit, aber man erkennt die Ungenauigkeit.
b) Mehrfache Änderungen - es wird immer versucht, doppelten Code zu vermeiden, damit man bei Änderungen nur eine Stelle ändern muss. Und durch die Kommentare wird es wieder doppelt: Wenn ich Auto Lackieren ändere, dann ändere ich den Code (z.B. Scheiben werden noch abgeklebt) aber in den Kommentaren vergesse ich es evtl. oder ich muss es eben noch an einer zweiten Stelle ändern.

Daher ist nach aktuellen Überlegungen es tatsächlich so, dass Kommentare eher als problematisch anzusehen sind.

Ausnahme hier sind javadoc Dokumente. Alles, was public ist, muss dokumentiert werden. Hintergrund hier ist, dass diese Kommentare in der Dokumentation wieder auftauchen (Also ähnlich wie die Dokumentation des Frameworks) bzw. bei uns in der Firma: Visual Studio zeigt die Dokumentation im Editor mit an bei IntelliSense. Also wenn ich someObject.SomeFunction( schreibe, dann zeigt mir Visual Studio auch ein Popup mit Beschreibung der Funktion und der Dokumentation der Parameter.

Aber ja - früher war es bezüglich Kommentare wirklich anders. Das kenne ich auch noch. Aber bei CleanCode sind fast alle Kommentare überflüssig. Dafür gibt es sehr viele Regeln, die dann auch Verschachtelungstiefe und Länge einer Funktion eingrenzen. Und alles sollte in einer Funktion auf einer Ebene sein und so.... aber das ist etwas, dass am Anfang einfach zu viel ist. Also immer nur auf eine Sache konzentrieren und dabei dann in erster Linie die Dinge mitnehmen, die nicht so kompliziert sind und auch viel helfen. Sinnvolle Variablennamen sind da z.B. wichtig.

Daher am Ende ein ganz wichtiger Punkt: Im Forum werden Threads manchmal etwas "gehijackt". Dann "kloppen" wir uns mal etwas. Dann legt man eine Aussage auf die Goldwaage und fragt dann nach und dann klären wir evtl. untereinander eine Fragestellung, die für den Thread Ersteller nicht wichtig ist und die ihn nur verwirrt. Da bitte ich um etwas Verständnis.
==> Lass Deine Kommentare also in Zukunft ruhig im Code drin wenn Du Code postest!

Wenn Dich der Punkt mit den Kommentaren interessiert, dann kann ich Dir aber gerne anbieten, dass ich Deinen Code noch einmal etwas umschreibe, so dass Du dann erkennst, dass die Kommentare unnötig werden könnten.


----------



## Xyz1 (16. Feb 2016)

Nagut, dann sorge ich mal dafür, das hier geschlossen wird.

kneitzel, versteht etwas komplizierte Algorithmen nicht. Punkt. Fakt.  :



kneitzel hat gesagt.:


> - Die Nutzung von Label in Java ist etwas, das in meinen Augen jeden Entwickler direkt disqualifiziert. Ich sehe für so einen Spagetticode keine Veranlassung und das ist auch bei fremden Code für mich nicht diskutabel.



Die Hälfte der Entwickler von Oracle sind disqualifiziert. Spagetti entsteht, wenn man auch noch einen Bool oder do-while-true verwendet.



kneitzel hat gesagt.:


> - Variablennamen vernünftig wählen,  ist hier im Thread oft genug angesprochen worden.



Profi Abkürzungen verstehen liegt nicht jedem.



kneitzel hat gesagt.:


> - Dein Code ist extrem verwirrend - Du hast eine Endlosschleife gebaut, dabei wird die Schleife maximal einmal komplett durchlaufen (Du magst mehrfach hoch springen aber sonst?)



Beweis für Korrektheit und Anhaltbarkeit bitte, den du nicht erbringen kannst. q.e.d.



kneitzel hat gesagt.:


> - Wenn nur eine Lottozahl doppelt ist, dann fängst Du von vorne an und ermittelst 6 neue Lottozahlen. Vom Algorithmus her ist das alles andere als gut.



Von Performance / Mikrooptimierung sprach hier keiner, sonst würde es die Hälfte der Lösungen nicht geben, und ihr würdet eine Set verwenden, wegen des Speicherplatzverhaltens.



kneitzel hat gesagt.:


> - Die Verschachtelungstiefe ist schon zu hoch. Wenn so ein Algorithmus, dann doch bitte mit Unterteilung in Funktionen. Immer noch ganz mangelhaft, aber besser wäre:



Vor 40 Jahren wurde dieser Quatsch noch gelehrt, nicht mehr Zeilen als eine Bildschirmseite, mittlerweile ist das überholt, im Übrigen ist es nicht mal eine Bildschirmseite, die du aufteilen willst.



kneitzel hat gesagt.:


> [-] Der Algorithmus ist jetzt aber direkt zu verstehen.



Nicht mehr zu verstehen, meinst du eher.

Andere Beiträge will ich mir jetzt gar nicht rauspicken.

@ TO/TE : Du kannst das zwar so schreiben, aber das ist - zunächst alle Vorkommen zählen - die Hälfte des bereits erwähntem CountingSorts. Auch ist es dir überlassen, jede Zeile zu kommentieren, als Gedankenstütze, um es nach X Jahren noch zu verstehen - lass mich aber bitte damit in Ruhe, denn mit Anfängern will ich nix zu tun haben. 

*Thema schließung droht*


----------



## kneitzel (16. Feb 2016)

Für den Fall, dass jemand interessiert ist, aus welchen Quellen ich mein Wissen beziehe:
- http://www.amazon.de/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882
- http://www.clean-code-developer.de

Nicht, dass hier der Eindruck entsteht, ich würde irgendwelche uralten Dinge umsetzen wollen. (Wobei das Buch von 2008 ist. Das kann schon uralt sein.) Softwareentwicklung ist ein sehr dynamisches Umfeld und regelmäßig werden neue Kühe durch das Dorf getrieben. Derzeit ist es noch continuous delivery aber es gab schon viele Kühe. Einiges hat sich durchgesetzt wie Objektorientierte Entwicklung und andere Dinge haben schlicht ihre Nische gefunden und werden von vielen ignoriert.
Oft ist es auch so, dass manche Dinge einfach nicht passen. So setzen wir auf Arbeit kein wirkliches SCRUM ein sondern haben unsere Arbeitsweise an die Anforderungen des Managements angepasst.
So gibt es auch angepasste Coding Guidelines - so hat jemand neulich im FOrum geschrieben, dass sie auf Arbeit sowohl Java als auch C# Code entwickeln und bezüglich Coding Guidelines haben sie sich auf eine Schreibweise geeinigt. Bei den geschweiften Klammern war es dann die "C# Schreibweise". Ist doch ok! 

Generell soll jeder so Software entwickeln, wie er es für richtig hält. Ich habe Perl Entwickler kennen gelernt, die sehr komplexe Algorithmen in ein oder zwei Zeilen gepackt haben. Hat auch gewisse Vorteile wie Jobsicherung - der Typ war so ohne weiteres nicht ersetzbar solange nicht auf die Wartung aller seiner Scripte verzichtet wird. Aber er hat von sich nie behauptet, dass sein Code gut leserlich gewesen wäre. 

Und die Tatsache, dass es in gewissen Bereichen kaum sinnvolle Alternativen gibt oder dort "Clean Code" uninteressant ist, ändert nichts an den Grundlagen von Clean Code und auch an der Wichtigkeit. Wer das nicht kennt und nicht kennen will: Ist ok, habe ich kein Problem mit. Aber wer darüber diskutieren will, der sollte es kennen. Wer es nicht kennt, soll sich die Ergebnisse ansehen und dann selbst entscheiden, was er besser findet.


----------



## JStein52 (16. Feb 2016)

Leute was habt ihr denn heute geraucht ? @Thorwine hat doch nur etwas aus dem Buch Java für Kids hier gepostet und dazu ein paar Anmerkungen erhalten. Dass in so einem Codeschnipsel ein paar Kommentare mehr drin sind ist doch logisch. Wahrscheinlich müsste man den Buchtext hierzu sehen der sicher darauf Bezug nimmt. Das Anliegen des TO/TE ist doch schon lange abgehakt und wenn es um die "schönste" Lösung geht hat für mich nach wie vor @thecain den Vogel abgeschossen mit seinem Einzeiler (der noch nicht mal Kommentare benötigt um ihn zu verstehen) 



DerWissende hat gesagt.:


> @ TO/TE : Du kannst das zwar so schreiben,


 Du musst den Thread mal komplett lesen, thorwine ist nicht der TE


----------



## javastudent25 (19. Feb 2016)

ok, ich habe jetzt mal die Zahlen in einem einzigen Array generiert..
ich komme einfach nicht zurecht mit der while und einer for
ich verstehe zwar was ihr meint, aber wenn ich jetzt den array habe, kann ich jetzt zB eine Variable definieren

variable a

dort kann ich jetzt den 1. Index vom array speichern und das ganze array durchgehen und abfragen ob die der aktuelle Index der gespeicherten zahl entspricht, ok.
wenn die Zahlen gleich sind, sage ich ok, generiere dann eine neue Zahl und speichere sie in den aktuellen Index.
Aber gleichzeitig muss ich ja sagen, fang von vorne an mit der for-schleife
sonst gibt er vermutlich die gleiche zahl wie index 1 ein und geht einfach weiter.
dann ist ja index 1 und 3 gleich, könnte ja so sein..

könnte mir vllt jemand mal so wie mein Code bisher ist dafür die 2-3 Zeilen Code hinschreiben, die mir doppelte Zahlen vermeiden? oder zumindest mal die ersten SChritte.
Im komme einfach nicht dahinter..


```
import java.io.*;
import java.text.*;
import java.util.*;
import java.lang.String;

public class Lottozahlen {

    public static void main(String[] args) {
        // Dies ist das Array, in das die Zahlen gespeichert werden
        // static String[][] array = new String[500][500];
        Filter filter = new Filter();
        Lotto lotto = new Lotto();
        lotto.getGesamtArray();
      

    }

}
```


```
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Random;

public class Lotto {
  
    private int[] zufallsZahlen = new int[6];
    private int[] gluecksZahl = new int[1];
    private int[] array = new int[zufallsZahlen.length + gluecksZahl.length];

    private void zahlenAusgeben() {
      
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + " ");
        }
    }
  
    private void erzeugeZahlenArray() {
      
        Random rand = new Random();
        for (int a = 0; a < (zufallsZahlen.length); a++) {
            int num = rand.nextInt(42) + 1;
            zufallsZahlen[a] = num;
        }
      
    }
  
    private void erzeugeGlueckszahl() {

        Random random = new Random();
        int zufall = random.nextInt(6) + 1;
        gluecksZahl[0] = zufall;

    }
  
    public void getGesamtArray(){
      
        erzeugeZahlenArray();
        Arrays.sort(zufallsZahlen);
        erzeugeGlueckszahl();
      
        for(int i=0;i<zufallsZahlen.length;i++){
           array[i]=zufallsZahlen[i];
        }
        for(int i=0;i<gluecksZahl.length;i++){
           array[zufallsZahlen.length+i]=gluecksZahl[i];
        }
        zahlenAusgeben();
      
      
    }
}
```


----------



## Tarrew (19. Feb 2016)

Ich muss gestehen, ich habe mir nicht den ganzen Thread durchgelesen aber wenn ich das richtig verstehe möchtest du ein Array mit Zufallszahlen, dass keine doppelten Einträge enthält.
Wenn du nur mit Arrays arbeiten willst, dann würde sowas klappen:

```
public static void main(String[] args) throws ParseException {
        int[] array = new int[6];
        Random r = new Random();
        int randomNumber;
        for(int i=0; i<array.length; i++){
            do{
                randomNumber = r.nextInt(6) + 1;
            }while(containsValue(array, randomNumber));
            array[i]=randomNumber;
        }
        System.out.println(Arrays.toString(array));
    }
  
    private static boolean containsValue(int[] array, int value){
        for(int i=0; i<array.length; i++){
            if(array[i]==value){
                return true;
            }
        }
        return false;
    }
```


Ansonsten wäre für die Aufgabe ein Set ganz nützlich, weil es keine doppelten Elemente enthalten kann, aber das hat vermutlich schon jemand vorgeschlagen:

```
Set<Integer> set = new TreeSet<>();
        Random r = new Random();
        do {
            set.add(r.nextInt(42) + 1);
        } while (set.size() != 6);
        System.out.println(set.toString());
```

#Edit: Wobei ich gerade sehe, dass unter anderem kneitzel schon Code gepostet hat, der genau das macht. Vllt. hab ich dein Problem dann falsch verstanden ;;o


----------



## Xyz1 (19. Feb 2016)

Und ihr werft mir Spagetticode vor, wenn ich das schon sehe *kotz*
Allein das neue Random Objekt ist unnötig.
Genau wie do while usw.


----------



## Meniskusschaden (19. Feb 2016)

DerWissende hat gesagt.:


> Allein das neue Random Objekt ist unnötig.
> Genau wie do while usw.


Hm, verstehe nicht, was gegen ein Random-Objekt einzuwenden ist. Kritik an do while verstehe ich auch nicht.


----------



## Xyz1 (20. Feb 2016)

Math.random() ist bereits ein Singleton (über statische innere Klassen Fabrik)
do while ist ein Schlüsselwort mehr, unleserlich und langsam

Muss ich dazu noch mehr schreiben? An meinem Text hätte er noch was
lernen können.


----------



## Meniskusschaden (20. Feb 2016)

DerWissende hat gesagt.:


> Math.random() ist bereits ein Singleton (über statische innere Klassen Fabrik)


Verstehe immer noch nicht, warum das ein Argument gegen den Komfort eines Random-Objekts sein soll.



DerWissende hat gesagt.:


> do while ist ein Schlüsselwort mehr, unleserlich und langsam


Wenn man die Bedingung am Schleifenende prüfen möchte, braucht man eben etwas, um den Beginn zu kennzeichnen. Das do ist dafür doch sehr geeignet weil es besonders gut lesbar ist. Ist aber müßig, darüber zu diskutieren, denn in Java baut man solche Schleifen eben mit do while. Man kann da schlecht mal eben ein eigenes Schlüsselwort erfinden. Warum sollten do while Schleifen denn langsamer sein, als andere Schleifen?


----------



## kneitzel (20. Feb 2016)

@DerWissende Wäre nett, wenn Du Dich etwas besser verständlich ausdrücken würdest. Im Sugenblick weiss ich einfach nicht, welchen Code Du speziell bemängelst als so unleserlich. Und wenn am Ende geprüft werden soll, dann ist do while die richtige Lösung. Was machst Du denn statt dessen? Doppelten Code? Einmal vor die while schleife und einmal in der Whileschleife? Oder verkomplizierst Du die Bedingung? 
Bezüglich random objekt: Ja, das ist etwas, das optimiert werden könnte. Aber ich würde dies anders optimieren als Du: random Objekt erstellen: ja. Aber bitte für Tests mit seed, damit die Tests gleich ablaufen und rekonstruierbar sind. Aber das ist für eine Hausaufgabe in der Schule deutlich zu komplex und ich habe nicht vor, die Gründe hier zu erläutern.

@javaStudent Die Lösung zu allen Problemen ist oft ganz schnell gefunden, wenn man eine komplexe Aufgabe unterteilt. Divide and Conquer - Teile und Hersche. Das bedeutet für mich im Rahmen der Entwicklung zwei Dinge:
a) Unterteilung des Ablaufs in viele kleine Schritte. Denn genau dies vereinfacht vieles in Bezug auf die Lesbarkeit. Du kannst einfach abbrechen und rausspringen wäre z.B. ein Vorteil. Du hast Dinge direkt "kommentiert" - denn es steht ja ein aussagekräftiger Funktionsname vor den meist kleinen Funktionen. Die Funktionen lesen sich einfach, da dort viele aussagekräftige Funktionen aufgerufen werden ...
b) Unterteilung der zu bearbeitenden Menge. Ein Beispiel wäre hier z.B. der QuickSort Algorithmus. Aber wichtig wird dies auch in vielen anderen Bereichen wie z.B. der Parallelisierung von Aufgaben, was bei den heutigen CPUs sehr wichtig wird..

Und es ist recht fatal, hier mit irgendwelchen massiv verschachtelten Schleifen etwas abbilden zu wollen. Das geht, keine Frage, aber dann hast Du einen riesen-Codeblock, in dem Du auf einem Array mit mehreren Operationen hantierst. Das wird recht komplex.

Aber so ein Code ist schreibbar (auch ohne Label  ):
1. Schleife über das Array
1.1. Arrayelement füllen mit Zufallszahl

2. Schleife über das Array (i=1, i<array.lebgth, i++)
    ==> Dies ist die äußere Schleife!
2.1. Schleife über Elemente bis (exkluded) ites Element (j=0, j<i, j++)
    ==> Diese Elemente vergleichen wir jetzt jeweils mit dem i-ten Element
2.1.1. if ites Element == jtes Element
2.1.1.true.1. ites Element = Zufallszahl
2.1.1.true.2. j = -1
                   ==> wird mit j++ am Ende dann 0, d.h. die Schleife 2.1 fängt von vorne an.

Da hat man jetzt das mit der Zufallszahl zwei Mal. Das könnte man jetzt noch umschreiben (Warum? Clean Code interessierte uns doch nicht!):

1. Schleife über das Array (i=0, i<array.lebgth, i++)
    ==> Dies ist die äußere Schleife! Fängt nun mit 0 an.
1.1. ites Element = Zufallszahl
1.2. Schleife über Elemente bis (exkluded) ites Element (j=0, j<i, j++)
    ==> Diese Elemente vergleichen wir jetzt jeweils mit dem i-ten Element
1.2.1. if ites Element == jtes Element
1.2.1.true.1. j = i;
                   ==> Die innere Schleife wird beendet
1.2.1.true.2 i = i - 1;
                   ==> Wir wiederholen diesen Schritt der äußeren Schleife noch einmal.

Besser? Nicht wirklich.

Du kannst diesen Pseudocode gerne einmal in Java umsetzen. Zur besonderen Unleserlichkeit empfehle ich das array a zu nennen, so dass da nur a, i und j auftauchen 

Andere Lösungen gibt es schon im Thread, so dass ich darauf nicht näher eingehen werde.
==> Lösungen bezüglich "Schule": Da habe unter anderem ich aufgezeigt, wie das aussehen könnte.
==> Lösung bezüglich Framework einsetzen: Da nimmt man kein Array sondern ein Set. Richtige Wahl der vorhandenen Datentypen!
==> "Moderne" Lösung: Hier sehe ich den Einzeiler aus dem Thread ganz weit oben, denn er ist lesbar und liefert eine gute Lösung.


----------



## Xyz1 (20. Feb 2016)

DerWissende hat gesagt.:


> Math.random() ist bereits ein Singleton (über statische innere Klassen Fabrik)
> do while ist ein Schlüsselwort mehr, unleserlich und langsam



... siehe dir diesbezüglich auch Bytecode an, eine Anweisung mehr ...

Zudem ist er auch noch falsch, wenn irgendwann einmal die Anforderung gestellt werden sollte, dass das Zufallszahlenarray auch leer sein könnte.

Alles in Allem, es bleibt Anfängercode, und ihr wollt mir Ver(schlimm)besserungsratschläge geben!


----------



## Meniskusschaden (20. Feb 2016)

DerWissende hat gesagt.:


> ... siehe dir diesbezüglich auch Bytecode an, eine Anweisung mehr ...


Habe es mir angesehen. Für dieses Beispiel:

```
public class DoWhileTest {
    public static void main(String[] args) {
        int i = 0;
        do {
            System.out.println(i++);
        } while (i < 5);
    }
}
```
bekomme ich folgenden Bytecode:

```
public class DoWhileTest {
  public DoWhileTest();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_0
       1: istore_1
       2: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
       5: iload_1
       6: iinc          1, 1
       9: invokevirtual #22                 // Method java/io/PrintStream.println:(I)V
      12: iload_1
      13: iconst_5
      14: if_icmplt     2
      17: return
}
```

Für dieses Beispiel:

```
public class WhileTest {
    public static void main(String[] args) {
        int i = 0;
        while (i < 5) {
            System.out.println(i++);
        }
    }
}
```

erhalte ich folgenden Bytecode:

```
public class WhileTest {
  public WhileTest();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_0
       1: istore_1
       2: goto          15
       5: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
       8: iload_1
       9: iinc          1, 1
      12: invokevirtual #22                 // Method java/io/PrintStream.println:(I)V
      15: iload_1
      16: iconst_5
      17: if_icmplt     5
      20: return
}
```

Ich kann da beim besten Willen keinen Performance-Nachteil der doWhile-Schleife erkennen. Der Bytecode ist sogar kürzer. Die Unterschiede, die es geben mag, wären meines Erachtens ohnehin völlig irrelevant. Das fällt überhaupt nicht in's Gewicht.
Ich verstehe auch nicht, warum dir dieses Performancethema jetzt so wichtig ist. Dun hast weiter oben doch noch geschrieben, dass es nicht um Mikrooptimierung und Performance geht, als an deinem Algorithmus kritisiert wurde, dass er bei einer doppelten Zufallszahl komplett von vorne anfängt (habe nicht geprüft, ob das stimmt). Solange man so großes Optimierungspotential liegen lässt, ist es doch völlig unverhältnismässig, doWhile als vermeintlichen Performancekiller zu umgehen.


----------



## Meniskusschaden (20. Feb 2016)

DerWissende hat gesagt.:


> Zudem ist er auch noch falsch, wenn irgendwann einmal die Anforderung gestellt werden sollte, dass das Zufallszahlenarray auch leer sein könnte.


Da du jetzt Anforderungsänderungen in's Spiel bringst, noch eine Anmerkung zu deinem Algorithmus. Er garantiert ja nicht, dass er überhaupt terminiert (insofern sind Performancevergleiche ohnehin müßig). Habe ihn spaßeshalber mal für eine Ziehung 36 aus 42 aufgerufen. Das hat schon ein paar Minuten gedauert, bis er fertig war.


----------



## Xyz1 (20. Feb 2016)

Er terminiert für höhere n nicht, weil Zufallszahlen nicht wirklich Zufallszahlen sind, müsste man schon das Hintergrundrauschen des Universums beobachten dafür.


----------



## kneitzel (20. Feb 2016)

Also wenn, dann bitte sauber bleiben: Natürlich terminiert er. Wenn ich n Zufallszahlen aus n möglichen ziehe, dann terminiert er, sobald er halt wirklich n "richtige" erwischt hat. Die Wahrscheinlichkeit kann man ausrechnen. Ebenso kann man die Wahrscheinlichkeit auch für x (mit x<n) unterschiedlichen Zahlen aus n berechnen.

Und ob nun ein Befehl mehr bei raus kommt oder nicht, ist relativ egal. Es wird teilweise extrem viel Performance verschenkt nur um Vorteile wie Aspekte oder so zu haben.... Und wer clean-code-developer.de kennt, der wird bei so Optimierungen ehh die Hände über den Kopf zusammen schlagen


----------



## Blender3D (20. Feb 2016)

Ich finde:


Thorwine hat gesagt.:


> *do* {
> zufall = (*int*) (Math.random() * MAX) + 1;
> } *while* (lottozahl[zufall] == 1);


Diese Lösung bildet die Wirklichkeit sehr schlecht ab.
Jedenfalls habe ich noch keine Lottoziehung gesehen, wo die gezogene Zahl wieder in den Kessel geworfen wird und bei der nächsten Ziehung geschaut wird ob diese bereits gezogen war.
Das führt zu unnötigen Laufzeiten z.B. 44 aus 45 oder ähnliches braucht für jede Zahl immer länger bis die nächste Zahl gefunden wird.
Also: Lösung wäre die Anzahl der Zufallszahlen nach jeder Ziehung zu reduzieren und das Ergebnis der Nächsten Zahl auf die Zielmenge zu übertragen.

```
public class Lotto {
    public static int[] ziehen(int totalNumbers, int drawingQuantity) {
        boolean[] usedNumbers = new boolean[totalNumbers];
        int[] drawnNumbers = new int[drawingQuantity];
        int toDrawQuantity = drawingQuantity;
        Random rnd = new Random(System.currentTimeMillis());
        while (toDrawQuantity != 0) {
            int number = Math.abs(rnd.nextInt()) % (toDrawQuantity) + 1;
            drawnNumbers[drawingQuantity - toDrawQuantity] = getConcretNumber(usedNumbers, number);
            toDrawQuantity--;

        }
        return drawnNumbers;
    }

    private static int getConcretNumber(boolean[] usedNumbers, int number) {
        int nummerNeu = number;
        for (int i = 0; i < usedNumbers.length; i++) {
            if (usedNumbers[i])
                nummerNeu++;
            if (i == nummerNeu - 1)
                break;
        }
        usedNumbers[nummerNeu - 1] = true;
        return nummerNeu;
    }

}
```


----------



## Blender3D (20. Feb 2016)

Sorry vorheriger Code stimmt nicht! Hier die Korrektur!

```
import java.util.Random;

public class Lotto {
    public static int[] ziehen(int totalNumbers, int drawingQuantity) {
        boolean[] usedNumbers = new boolean[totalNumbers];
        int[] drawnNumbers = new int[drawingQuantity];
        int toDrawQuantity = drawingQuantity;
        Random rnd = new Random(System.currentTimeMillis());
        while (toDrawQuantity != 0) {
            int number = Math.abs(rnd.nextInt()) % (totalNumbers) + 1;
            drawnNumbers[drawingQuantity - toDrawQuantity] = getConcretNumber(usedNumbers, number);
            toDrawQuantity--;

        }
        return drawnNumbers;
    }

    private static int getConcretNumber(boolean[] usedNumbers, int number) {
        int nummerNeu = number;
        while (usedNumbers[nummerNeu - 1])
            nummerNeu = (nummerNeu + 1) % usedNumbers.length;
        usedNumbers[nummerNeu - 1] = true;
        return nummerNeu;
    }

}
```


----------



## javastudent25 (20. Feb 2016)

Tarrew hat gesagt.:


> Ich muss gestehen, ich habe mir nicht den ganzen Thread durchgelesen aber wenn ich das richtig verstehe möchtest du ein Array mit Zufallszahlen, dass keine doppelten Einträge enthält.
> Wenn du nur mit Arrays arbeiten willst, dann würde sowas klappen:
> 
> ```
> ...



Hallo Tarrew

Vielen Dank für deinen Beitrag, der hat endlich geholfen.. 
Die Beiträge von kneitzel finde, ich was meine Kenntnisse angeht auch immer sehr hilfreich und kann meistens damit auch etwas anfangen.
Aber den Code von kneitzel habe ich in diesem Fall irgendwie überlesen und finde ihn immer noch nicht.

Wie ich sehe, gab es schon einige Kommentare. Ich finds schön, wenn es Diskussionen gibt, da kann man dann nur lernen von den Experten , aber nur solange, wenn die Leute sich hier nicht gegenseitig fertig machen. 

Ich muss auch ehrlich gestehen, dass ich auf Codes wie HashSet oder Set, Lists etc. nicht eingegangen bin, da ja damit nicht direkt mein Problem gelöst ist.
Ich würde zwar schneller am Ziel sein, aber verstanden hätte ich Nichts.
Was das Programmieren angeht sind hier offensichtlich ein paar viele Einsteins.
Nur um deren Lösungen zu verstehen, müsste ich mich zuerst auf deren Niveau befinden.
Ich würde mich gerne mit der Thematik java viel mehr beschäftigen, aber leider fehlt mir einfach die Zeit dafür.

Deshalb sind mir Lösungen wie du, kneitzel und paar andere sie präsentiersen oder erklären meisten am Liebsten.
Denn so habe ich nicht nur das Problem gelöst, sonder auch verstanden..
Vor allem das mit der While-Schleifen-Bedingung..

Dann kann ich mich jetzt mal, um den nächsten Step kümmern 


```
import java.io.*;
import java.text.*;
import java.util.*;
import java.lang.String;

public class Lottozahlen {

    public static void main(String[] args) {
      
        Lotto lotto = new Lotto();
        lotto.getGesamtArray();
    }
}
```



```
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;

public class Lotto {
   
    private int[] zufallsZahlen = new int[6];
    private int[] gluecksZahl = new int[1];
    private int[] array = new int[zufallsZahlen.length + gluecksZahl.length];

    private void zahlenAusgeben() {
       
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + " ");
        }
    }
   
    private void erzeugeZahlenArray() {
       
           Random rand = new Random();
           int randomNumber;
           for(int i=0; i<zufallsZahlen.length; i++){
               do{
                   randomNumber = rand.nextInt(42) + 1;
               }while(containsValue(zufallsZahlen, randomNumber));
               zufallsZahlen[i]=randomNumber;
           }       
    }
   
    private void erzeugeGlueckszahl() {

        Random random = new Random();
        int zufall = random.nextInt(6) + 1;
        gluecksZahl[0] = zufall;

    }
   
    public void getGesamtArray(){
       
        erzeugeZahlenArray();
        Arrays.sort(zufallsZahlen);
        erzeugeGlueckszahl();
       
        for(int i=0;i<zufallsZahlen.length;i++){
           array[i]=zufallsZahlen[i];
        }
        for(int i=0;i<gluecksZahl.length;i++){
           array[zufallsZahlen.length+i]=gluecksZahl[i];
        }
        zahlenAusgeben();
       
       
    }
   
    private boolean containsValue(int[] array, int value){
           for(int i=0; i<array.length; i++){
               if(array[i]==value){
                   return true;
               }
           }
           return false;
    } 
}
```


----------



## Blender3D (20. Feb 2016)

```
import java.util.Random;

public class Lotto {
    public static int[] ziehen(int totalNumbers, int drawingQuantity) {
        boolean[] usedNumbers = new boolean[totalNumbers];
        int[] drawnNumbers = new int[drawingQuantity];
        int toDrawQuantity = drawingQuantity;
        Random rnd = new Random(System.currentTimeMillis());
        while (toDrawQuantity != 0) {
            int number = Math.abs(rnd.nextInt()) % (totalNumbers);
            drawnNumbers[drawingQuantity - toDrawQuantity] = getConcretNumber(usedNumbers, number);
            toDrawQuantity--;

        }
        return drawnNumbers;
    }

    private static int getConcretNumber(boolean[] usedNumbers, int number) {
        int nummerNeu = number;
        while (usedNumbers[nummerNeu])
            nummerNeu = (nummerNeu + 1) % (usedNumbers.length);
        usedNumbers[nummerNeu] = true;
        return nummerNeu + 1;
    }

}
```
Noch ein Fehler aber jetzt läuft es!
*Laufzeit  z.B 45 aus 45 ist konstant!  45 * 45/2*


----------



## javastudent25 (20. Feb 2016)

Blender3D hat gesagt.:


> ```
> import java.util.Random;
> 
> public class Lotto {
> ...



Blender, bist du dir jetzt wirklich sicher?


----------



## Blender3D (20. Feb 2016)

Probiere es aus !


----------



## Blender3D (20. Feb 2016)

```
public static void main(String[] args) {   
        int []z = Lotto.ziehen(45, 45);
        Arrays.sort(z);
        for( int i:z )
            System.out.print(i+ "\t");
    }
```
Teste mal so !


----------



## Blender3D (20. Feb 2016)

Laufzeit z.B 45 aus 45 ist *maximal* 45 * 45/2


----------



## Xyz1 (20. Feb 2016)

Das ist ja ein Durcheinander. Du nimmst einfach die nächsthöhere, die nicht besetzt ist, Zahl.

Ich hingegen nehme einfach eine Liste, mische sie, nehme zwei Listen und schiebe in die 2. 6 - oder halt eine Set, Vorkommen zählen.

Wer will, kann ja alle Möglichkeiten einmal aufschreiben, und sich profilieren.

Oder ich nehme eine Trommel, befülle sie mit 49 Kugeln und drehe ein paar Mal, das nennt sich auch Zufall.


----------



## Flown (20. Feb 2016)

Warum versucht ihr alle einen simplen Algorithmus mit Mikro-Optimierungen zu verbessern?
Regel für Software Engineers: `Readability > (Micro-)Optimization`

@Blender3D Dein Algorithmus hat trotz allem eine Laufzeitkomplexität von O(n²)


----------



## Tarrew (20. Feb 2016)

DerWissende hat gesagt.:


> Und ihr werft mir Spagetticode vor, wenn ich das schon sehe *kotz*
> Allein das neue Random Objekt ist unnötig.
> Genau wie do while usw.





DerWissende hat gesagt.:


> Math.random() ist bereits ein Singleton (über statische innere Klassen Fabrik)
> do while ist ein Schlüsselwort mehr, unleserlich und langsam
> 
> Muss ich dazu noch mehr schreiben? An meinem Text hätte er noch was
> lernen können.



Ein Random Objekt hat Vorteile gegenüber Math.random(). Das kannst du auch hier nochmal nachlesen:
http://stackoverflow.com/questions/738629/math-random-versus-random-nextintint

Warum dein restlicher Code eher schlecht ist, hat kneitzel ja schon ausführlich erläutert.


----------



## Tarrew (20. Feb 2016)

Auf der Stackoverflow Seite kann ich auch keinen Beitrag von dir erkennen, weil durchgehend die Meinung herrscht dass Random.nextInt() besser ist als Math.random(). Laut deiner Aussage ist Math.random() ja viel besser


----------



## InfectedBytes (20. Feb 2016)

Ist ja ok, wir haben alle gemerkt das du dich für allwissend hältst, aber tut mir leid dich enttäuschen zu müssen, das bist bei weitem nicht. Sieht man ja allein schon an deinem tollen code hier:

```
a: while (true) {
  // for...
  break a;
}
```
Eine endlosschleife per label break immer nach dem ersten durchlauf abbrechen...echt genial xD

Bezüglich dieses Beitrags wurde zudem schon mehrfach geschrieben das bereits alles erledigt ist. Aber du willst ja immer das letzte Wort haben...lass es doch einfach sein, das Thema ist schon längst beendet.


----------



## Xyz1 (20. Feb 2016)

Nö, erst unberechtigt Spaghetti vorwerfen und dann noch schlechteren Code posten, was soll daran erledigt sein, sehe ich hier eine Auflistung aller Möglichkeiten.


----------



## Saheeda (20. Feb 2016)

Könnt ihr nicht bitte damit aufhören? Ihr habt halt verschiedene Ansichten, was guter und was schlechter Code ist. Jeder hat seine Meinung dazu dargelegt, alles Weitere endet doch nur in einer Schlammschlacht.

Am Ende wird noch der Thread geschloßen, was dem TE am allerwenigsten hilft.


----------



## kneitzel (21. Feb 2016)

Also dem TE wurde schon geholfen und der Thread wurde von mind. 2 Anderen mit ähnlichem Anliegen 'gehijackt'.

Unterschiedliche Meinungen kann man haben aber gewisse Dinge sind einfach lachhaft! Und das Auftreten ist auch schon sehr interessant...

Ebenso wurde sachlich nicht auf meine Quellen geantwortet. Angeblich vertrete ich 40 Jahre alte Thesen ... Das Buch muss er ja nicht kennen aber clean-code-developer.de hätte er ja mal ansehen können ... Aber nein, das sind bestimmt auch nur Deppen wie wir, die keine Ahnung haben ...

Sorry, das musste leider raus.


----------



## Xyz1 (21. Feb 2016)

Ich lese nicht nach, wie etwas funktioniert, ich schreibe es anderen zum nachlesen auf, wie etwas funktioniert. Hoffentlich erkennst du den Unterschied. 

Aber ich will mal nicht so gemein sein, siehe dir doch api quelltext an, wenn du wissen möchtest, wie man aktuell und sauber etwas schreibt.


----------



## kneitzel (21. Feb 2016)

Und dann ist die Frage: Sollen falsche Behauptungen einfach so im Raum stehen bleiben?

Angeblich handelt es sich bei dem folgenden Code nicht um Spagetti Code:

```
int[] intArr =newint[6];// 6 bitte nicht ändern :-)
        a:while(true){
           for(int i =0; i < intArr.length; i++){
                intArr[i]=(int) func1(1, 49);
           }
           for(int i =0; i < intArr.length-1; i++){
               for(int j = i +1; j < intArr.length; j++){
                   if(intArr[i]== intArr[j]){
                       continue a;
                   }
               }
           }
           break a;
       }
       System.out.println(Arrays.toString(intArr));
```

Jetzt müssen wir uns einfach einmal fragen, was denn bitteschön Spagetticode ist. Dies mag manch einer einfach als "Nutzung von Goto Befehlen" oder so ansehen. Dies ist aber eine Definition, die so nicht haltbar ist. Also schauen wir doch einfach einmal auf Wikipedia - da wird sich dann ja schon eine Definition finden lassen: https://de.wikipedia.org/wiki/Spaghetticode
"*Spaghetticode* ist ein abwertender Begriff für Software-Quellcode, der verworrene Kontrollstrukturen aufweist."
Ok, jetzt müsste man klären, was verworrene Kontrollstrukturen sind. Aber Wikipedia führt das ja noch etwas weiter aus:
"Ein Indiz dafür kann etwa die übermäßige Verwendung von Sprunganweisungen (wie GOTO) sein, wobei _übermäßig_ bedeutet: Zum gleichen Ziel könnte man auch mit weniger Sprüngen gelangen."

Schauen wir uns doch einfach einmal an, was da so an Code vorliegt:
Wir haben mehrere verschachtelte Schleifen. Bei der äußeren Schleife fällt auf, dass die while Schleife eigentlich keine wirkliche Whileschleife ist. Dies ist eigentlich nur ein Konstrukt, um zwei Punkt anspringen zu können. Der Code entspricht von der Funktion her dem folgenden (nicht java code):

```
int[] intArr =newint[6];// 6 bitte nicht ändern :-)
        a:
           for(int i =0; i < intArr.length; i++){
                intArr[i]=(int) func1(1, 49);
           }
           for(int i =0; i < intArr.length-1; i++){
               for(int j = i +1; j < intArr.length; j++){
                   if(intArr[i]== intArr[j]){
                       goto a;
                   }
               }
           }

       System.out.println(Arrays.toString(intArr));
```

Und damit wird eigentlich deutlich, dass hier ein Kontrollkonstrukt gebaut wurde, welches ich schon als Spagetticode bezeichnen würde. Die Kollstrukturen sind auf jeden Fall verworren in meinen Augen. Aber ok, jedem seine Meinung.

Aber der Wikipedia-Beitrag zu Spagetticode hat ein paar nette Links. So z.B. zur McCabe Metrik. Eine niedrige Metrik wird als wünschenswert angesehen. Hier könnte man dann über diese Metrik die Codes vergleichen. Einmal so eine dreifache Staffelung von Schleifen mit einem if entgegen einfachen Schleifen mit einem Funktionsaufruf.

Das einfach einmal zur Erläuterung, wieso ich diese tödliche Beleidigung gegenüber dem Sourcecode ausgesprochen habe.


----------



## Xyz1 (21. Feb 2016)

Ich hab ja von Tarrew auch schon TreeSet gesehen - wegen der Umordnung usw. noch langsamer und schlimmer als HashSet.

Ich sollte echt mal den ganzen Thread von hinten nach vorne lesen, wenn ich mich amüsieren und/oder wen kritisieren möchte.


----------



## javastudent25 (21. Feb 2016)

DerWissende hat gesagt.:


> Ich lese nicht nach, wie etwas funktioniert, ich schreibe es anderen zum nachlesen auf, wie etwas funktioniert. Hoffentlich erkennst du den Unterschied.
> 
> Aber ich will mal nicht so gemein sein, siehe dir doch api quelltext an, wenn du wissen möchtest, wie man aktuell und sauber etwas schreibt.



Gut, wenn du bezüglich Java nichts mehr zu lernen hast und so perfekt bist, dann kannst du dich an die Orthographie machen...
zum Nachlesen schreibt man gross, Quelltext und Anderen auch..
Demnach solltest du Anderen besser nichts zum Nachlesen aufschreiben...


----------



## Xyz1 (21. Feb 2016)

anderen schreibt man klein, aber egal.

Edit: Ich weiß nicht wieso, aber dann halt noch eine Version nach kneitzel:

```
private static int[] aus49() {
        int[] irgendwas1 = new int[49]; // fuer Test
        for (int i = 0; i < irgendwas1.length;) {
            irgendwas1[i] = (int) (Math.random()*49.0)+1;
            for (int j = 0; j < i; j++) {
                if (irgendwas1[i] == irgendwas1[j]) {
                    i--;
                }
            }
            i++;
        }
        Arrays.sort(irgendwas1);
        System.out.println(Arrays.toString(irgendwas1)); // fuer Test
        return irgendwas1;
    }
```

Hier gefallen mir jetzt mehrere Dinge nicht, das Dekrementieren z. B. Aber ich soll ja nicht irgendwelche Sprünge einfügen.

Hat jemand Lust auf die Invariante aufzuschreiben=?


----------



## Meniskusschaden (21. Feb 2016)

DerWissende hat gesagt.:


> ```
> private static int[] aus49() {
> int[] irgendwas1 = new int[49]; // fuer Test
> for (int i = 0; i < irgendwas1.length;) {
> ...



Was soll das denn jetzt zeigen? Das liefert doch nur ein Array mit den Zahlen 1 bis 49. Dann kann man das doch auch gleich ganz normal machen:

```
private static int[] aus49() {
        int[] irgendwas1 = new int[49];
        for (int i = 0; i < irgendwas1.length; i++) {
            irgendwas1[i] = i+1;
        }
        System.out.println(Arrays.toString(irgendwas1));
        return irgendwas1;
    }
```


----------



## Flown (21. Feb 2016)

Wenn man eine Diskussion führt, dann bitte folgende Reihenfolge:
- These aufstellen
- Fakten darlegen (mit Referenzen)
- Argumentieren

Wenn jetzt von irgendeiner Seite nocheinmal beleidigt oder angestachelt wird, dann wars das mit diesem Thema!


----------



## Flown (21. Feb 2016)

Meine Damen und Herren, um jetzt mal ein offizielles Ranking der "besten" Lösungen zu geben, habe ich mal alle Snippets die hier gepostet wurden in einen Benchmark geworfen.
"Beste" Lösung heißt: Schnellster Methodendurchlauf (gegeben in Nanosekunden(ns)).

Benutzt wurde JMH mit folgenden Parameter:
- Warmup: 5 Iterationen
- Gemessen: 3 Forks zu je 10 Iterationen
- Random mit seed um gleiche Randomwerte zu erzielen

So sieht mal der Benchmarkcode aus:


Spoiler: Benchmarkcode





```
/*
* Copyright (c) 2014, Oracle America, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Oracle nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/

package test;

import java.util.Arrays;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.TimeUnit;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Threads;
import org.openjdk.jmh.annotations.Warmup;

@Fork(3)
@BenchmarkMode(Mode.AverageTime)
@Measurement(iterations = 10, timeUnit = TimeUnit.NANOSECONDS)
@State(Scope.Benchmark)
@Threads(1)
@Warmup(iterations = 5, timeUnit = TimeUnit.NANOSECONDS)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class MyBenchmark {

  public Random random;

  @Setup(Level.Iteration)
  public void setup() {
    random = new Random(10);
  }

  @Benchmark
  public int[] lottoStrammerMax93() {
    int[] zahlen = new int[49];
    for (int i = 0; i < 49; i++) {
      zahlen[i] = i + 1;
    }
    int h, z;
    for (int i = 0; i < 6; i++) {
      z = random.nextInt(49 - i);
      h = zahlen[z];
      zahlen[z] = zahlen[48 - i];
      zahlen[48 - i] = h;
    }
    return Arrays.copyOfRange(zahlen, 43, 49);
  }

  @Benchmark
  public int[] lottoVoid_Nutzer16() {
    int[] lottozahlen = new int[6];
    meinLabel: for (int i = 0; i < lottozahlen.length;) {
      int zwischenspeicher = random.nextInt(49) + 1;
      for (int k = 0; k < i; k++) {
        if (zwischenspeicher == lottozahlen[k]) {
          continue meinLabel;
        }
      }
      lottozahlen[i++] = zwischenspeicher;
    }
  
    return lottozahlen;
  }

  @Benchmark
  public int[] lottoThecain() {
    return random.ints(1, 50).distinct().limit(6).toArray();
  }

  @Benchmark
  public int[] lottoThorwine() {
    boolean[] gezogeneLottozahlen = new boolean[49];
    int[] result = new int[6];
    int zufallszahl = 0;
    for (int count = 0; count < 6; count++) {
      do {
        zufallszahl = random.nextInt(49);
      } while (gezogeneLottozahlen[zufallszahl]);
      gezogeneLottozahlen[zufallszahl] = true;
      result[count] = zufallszahl + 1;
    }
    return result;
  }

  @Benchmark
  public int[] lottoDerWissende() {
    int[] intArr = new int[6];
    a: while (true) {
      for (int i = 0; i < intArr.length; i++) {
        intArr[i] = random.nextInt(49) + 1;
      }
      for (int i = 0; i < intArr.length - 1; i++) {
        for (int j = i + 1; j < intArr.length; j++) {
          if (intArr[i] == intArr[j]) {
            continue a;
          }
        }
      }
      break a;
    }
    return intArr;
  }

  @Benchmark
  public int[] lottoTarrew() {
    Set<Integer> set = new TreeSet<>();
    do {
      set.add(random.nextInt(49) + 1);
    } while (set.size() != 6);
    int[] result = new int[set.size()];
    int i = 0;
    for (int s : set) {
      result[i++] = s;
    }
    return result;
  }

  @Benchmark
  public int[] lottoBlender3D() {
    boolean[] usedNumbers = new boolean[49];
    int[] drawnNumbers = new int[6];
    int toDrawQuantity = 0;
    while (toDrawQuantity < 6) {
      int number = random.nextInt(49);
    
      int nummerNeu = number;
      while (usedNumbers[nummerNeu]) {
        nummerNeu = (nummerNeu + 1) % usedNumbers.length;
      }
      usedNumbers[nummerNeu] = true;
    
      drawnNumbers[toDrawQuantity++] = nummerNeu + 1;
    }
    return drawnNumbers;
  }

}
```



Hier das Ergebnis:

```
# Run complete. Total time: 00:05:20

Benchmark                       Mode  Cnt    Score   Error  Units
MyBenchmark.lottoBlender3D      avgt   30   67,545 ± 0,548  ns/op
MyBenchmark.lottoDerWissende    avgt   30   93,476 ± 0,643  ns/op
MyBenchmark.lottoStrammerMax93  avgt   30   99,237 ± 0,918  ns/op
MyBenchmark.lottoTarrew         avgt   30  210,011 ± 1,866  ns/op
MyBenchmark.lottoThecain        avgt   30  326,354 ± 4,371  ns/op
MyBenchmark.lottoThorwine       avgt   30   70,558 ± 0,676  ns/op
MyBenchmark.lottoVoid_Nutzer16  avgt   30   66,025 ± 0,322  ns/op
```

Gewinner: void_nutzer16

Warum? Weil der Algorithmus fast linear läuft. Warum? Weil es wenig Kollisionen gibt und somit die Iterationen wenig bis nie wiederholt werden müssen (selbe gilt für die Lösung von Blender3D).
Fakt ist, dass beide quadratische Laufzeitkomplexität aufweisen O(n²).

Welche Lösung würde ich nehmen? Auf jedenfall den Einzeiler von thecain. Warum? Weil es für Normalsterbliche keinen Unterschied macht, ob man 66ns oder 300ns wartet. Beide Ergebnisse werden instant zurückgeliefert und die Intention ist auf den ersten Blick ersichtlich.


----------



## kneitzel (21. Feb 2016)

@DerWissende: Ich verstehe Deine Argumentation nicht. Ich habe klar begründet, wieso ich Deinen Code als Spagetti Code bezeichnet habe. Ich habe sogar extra die Definition von Spagetti Code dargelegt, damit es keine Probleme gibt mit unterschiedlichen Definitionen.

Die Verwendung von Sprunganweisungen sind nur ein Indiz. Das ist nichts Zwingendes. (Indiz: "Unter einem *Indiz* (von lat.: _indicare_ „anzeigen“) wird im Prozessrecht ein Hinweis verstanden, der für sich allein oder in einer Gesamtheit mit anderen Indizien den Rückschluss auf das Vorliegen einer Tatsache zulässt. Im Allgemeinen ist ein Indiz mehr als eine Behauptung, aber weniger als ein Beweis." - Wikipedia).

Die Definition sagte ganz klar aus, dass es um verworrene Kontrollstrukturen geht. In diesem Zusammenhang habe ich auf die McCabe Metrik hingewiesen. Diese Punkte scheinst Du zu ignorieren und komplett auszublenden.

Vor dieser Antwort habe ich Dich auch schon auf http://clean-code-developer.de und KISS hingewiesen. Darauf bist Du auch in keiner Weise eingegangen.

Ich habe kein Verständnis, wenn jemand in einer Diskussion um ein generelles Thema, das Thema ignoriert und meint in einzelnen Punkten auf Beispielen herum zu reiten. Das ist vergleich mit einer Diskussion bezüglich "Du darfst nicht töten". Da wird dann auf diversen Ebenen argumentiert (z.B. Kants kategorischer Imerativ, Strafgesetz u.s.w.) und eben auch ein Beispiel gebracht, dass es eben nicht ok ist, wenn jemand einen anderen mit einer Pistole erschießt. Deine Argumentation ist jetzt: Ach was - töten ist doch in Ordnung. Wenn ich keine Pistole nehmen darf, dann nehme ich halt einen Revolver. Sorry, es wurden einige Argumente gebracht, auf die Du nicht eingehst.

Und das tolle bei der Softwareentwicklung bezüglich Clean Code ist, dass man sich viele kleine Regeln aufstellen kann. Eine ganz einfache Regel könnte z.B. sein, dass man in einer for Schleife die Variable der Schleife nicht zusätzlich verändert. (Und wenn man meint, dass sowas notwendig ist, statt einer For-Schleife eine While-Schleife verwendet. Dies hätte dann den Vorteil, dass man Code schneller einschätzen kann. Aber solche einfachen Regeln sind einfache Gebote, die teilweise willkürlich festgelegt werden. Diese sind in etwa Vergleichbar mit Regeln des Straßenverkehrs. Ob man nun rechts oder links fährt ist egal - wichtig ist, dass man eine Regel aufstellt und alle sich daran halten. Das führt dann oft auch zu Folgeerscheinungen wie z.B. das Lenkrad kommt dann auf die linke Seite.

Aber an dem Beispiel wird evtl. deutlich, dass man gerne andere Regeln aufstellen kann. Aber es wird (hoffentlich) niemand bezweifeln, dass es solcher Regeln bedarf, um die Anforderungen zu erfüllen. Im Beispiel mit dem Straßenverkehr ist die Anforderung hat, dass eine hohe Anzahl Verkehrsteilnehmer mit teilweise hoher Geschwindigkeit auf begrenztem Raum unterwegs sein sollen und die Anzahl der Unfälle minimiert werden soll.
So übergeordnete Ziele gibt es auch in der Software-Entwicklung. So soll Code wartbar sein, arm an Fehlern / fehlerfrei, zügig erstellt worden sein, ....

Und die reine Code Entwicklung ist dabei auch nur ein kleiner Teil. Ein weiterer Bereich ist die Analyse und das Design. Es ist toll, wenn Du von Dortmund nach Hamburg fahren willst und Du auch ganz  schnell unterwegs sein willst um ganz schnell in Hamburg zu sein. Aber bei jedem Autobahnkreuz fährst Du ab und fährst erst auf die Autobahn, auf der Du weiter musst, wenn da auch gerade ein rotes Auto kommt. Beim zweiten Kreuz muss es ein rotes Mittelklasse-Auto sein. Beim dritten ein rotes Mercedes C-Klasse Auto. Wenn Du es bis zum vierten Kreuz schaffen solltest: da muss es natürlich ein roter Mercedes C-Klasse mit Münchener Kennzeichen sein!
Und weil es so toll ist: Jede zweite Ausfahrt fährst Du ab und in die Gegenrichtung wieder auf um dann bei der nächsten Ausfahrt zu wieder zu wenden um dann dieses Spiel wieder fortzusetzen. (Natürlich stellst Du sicher, dass nur Ausfahrten zählen, bei denen Du auch wenden kannst!)

Ja, mit diesen Regeln kommst Du zum Ziel. Als Beweis führst Du an, dass es auch mehrere rote Mercedes C-Klasse mit Münchener Nummernschild gibt und davon einige auch genau auf diesen Autobahnen von Zeit zu Zeit unterwegs sind. Und als Test: Du bist so schon mehrfach von Dortmund nach Hamburg gefahren.

Ja sehr gut. Super! Aber Du wolltest eigentlich nur von Dortmund nach Hamburg, dies relativ zügig, wolltest wenig Sprit verbrauchen u.s.w. Viele tolle Ziele. Aber als Vorschlag kommt dann so ein Vorgehen? Und wenn jemand sagt, dass dies nicht gut ist und mit Deinen Zielen nicht vereinbar: Ok, dann optimierst Du - Du hälst bei den Autobahnkreuzen und wartest auf das Erscheinen eines der gesuchten Fahrzeuge. Ahh ja. Interessant. Aber was soll man da noch argumentieren?

Argumente sind eigentlich alle genannt. Fakten liegen auf dem Tisch. Im Vergleich mit der Fahrt von Dortmund nach Hamburg liegen schon mehrere Fahrtrouten vor. Ok, manch einer holt sich im Kaufhaus in München erst noch einen Kühlschrank, weil er meint, dass der Laden dort toll ist, aber ok: Es gibt viele Fahrtrouten, die man betrachten kann. Die kann man vergleichen. Man kann Dinge kontrollieren wie Strecke, voraussichtlich benötigte Zeit, Funktionsfähigkeit (der 40t mit 3m Höhe wird evtl. nicht jede Strecke fahren können) und auch wie gut der Weg gefunden werden kann. Und es mag auch gute Argumente dafür geben, dass Du jede zweite Ausfahrt wendest um eine Ausfahrt zurück zu fahren: So kannst Du die Landschaft richtig gut betrachten! Aber wenn Du im professionellen Transportbereich tätig sein willst, dann wiegen die anderen Gründe doch deutlich höher.

Bezüglich Deines neuen Codes: Dazu gab es ja schon einen ersten Hinweis. Und wenn man die McCabe Metrik bedenkt: Evtl. findest Du ja auch bessere Lösungen 

Soviel einfach einmal von meiner Seite aus zu dieser Diskussion. Ab jetzt werde ich mich nur noch darauf beschränken, falsche Fakten zu korrigieren.


----------



## Xyz1 (21. Feb 2016)

Danke für die Müh des Tests. Aber fair bleiben, und hiermit testen
(war die neuste Version von mir, angepasst an das random Objekt):

```
public int[] lottoDerWissende() {
        int[] irgendwas1 = new int[6];
        for (int i = 0; i < irgendwas1.length;) {
            irgendwas1[i] = random.nextInt(49) + 1;
            for (int j = 0; j < i; j++) {
                if (irgendwas1[i] == irgendwas1[j]) {
                    i--;
                }
            }
            i++;
        }
        return irgendwas1;
    }
```

(Ohne Labels)

oder:

```
public int[] lottoDerWissende() {
        int[] irgendwas1 = new int[6];
        a: for (int i = 0; i < irgendwas1.length;) {
            irgendwas1[i] = random.nextInt(49) + 1;
            for (int j = 0; j < i; j++) {
                if (irgendwas1[i] == irgendwas1[j]) {
                    continue a;
                }
            }
            i++;
        }
        return irgendwas1;
    }
```

(Mit diesem gefährlichen Label, Ohne Zwischenvariable)

Das führt dann dazu, dass
1. genau so schnell wie lottoVoid_Nutzer16 und
2. ungefähr genau so schnell bis etwas schneller als lottoVoid_Nutzer16.

Aber ihr müsst mir nicht huldigen.

@ kneitzel : TL;DR


----------



## JStein52 (21. Feb 2016)

DerWissende hat gesagt.:


> Aber fair bleiben, und hiermit testen


Es wurde die Version von dir getestet auf die du so stolz warst


----------



## Flown (21. Feb 2016)

DerWissende hat gesagt.:


> Danke für die Müh des Tests. Aber fair bleiben, und hiermit testen


Mea culpa. Natürlich, hab den letzten Post übersehen.
Damit ist natürlich die Lösung an den von void_user16 dran/gleichwertig. Wer das überprüfen will, hat ja den Testcode oben.


----------



## Xyz1 (21. Feb 2016)

JStein52 hat gesagt.:


> Es wurde die Version von dir getestet auf die du so stolz warst



Es wurde (vorher) nichts von Mikrooptimierung oder Mikrobenchmark gesagt! Ich hatte zwei Versionen. Ich muss jetzt bewusst davon ausgehen, dass damit bewusst nicht getestet werden sollte.

@Flown: Ist schon okay, die echten Laufzeiten sind ungefähr gleich. Ich brauchte halt keine Zwischenvariable.


----------



## kneitzel (21. Feb 2016)

Also die Tests der Laufzeit sind recht nett und danke, dass Du Dir diese Arbeit gemacht hast.

Aber da kommen wir jetzt schnell zu einem Punkt, bei dem wir in eine Sackgasse rennen. Denn viele Streitereien gingen ja eben um den Punkt "Clean Code". Aber ehe ich hier wieder Zeit verschwende und lange Texte schreibe, gebe ich jetzt einfach nur einen Link weiter:
http://clean-code-developer.de/die-grade/roter-grad/#Vorsicht_vor_Optimierungen


----------



## Xyz1 (21. Feb 2016)

Ach Leute, eine Trommel befüllen und drehen dauert länger, insofern haben wir alle gewonnen.


----------



## Flown (21. Feb 2016)

Dieses Thema im Allgemeinen ist sehr unsinnig. Viele Leute hier reden von verschiedenen Sachen.
- Die einen reden von (Mikro-)Optimierungen (schneller, weniger Zeilen/Variablen, etc.)
- Die anderen reden von Clean-Code (Gliederung, Struktur, etc.)

Grundsätzlich sollte man Clean-Code als Richtlinie sehen und nicht als Gesetz, denn keiner kann von Anfang an perfekt Programmieren und Algorithmen perfekt strukturieren und abbilden. Das kommt alles mit der Zeit und Erfahrung -> haben alle selbst katastrophalen Code geschrieben, wo es einem gruselt!

Bitte bedenkt alle - ich wiederhole mich: Jeder der hier um Hilfe bittet ist meist kein Profi und es sind auch keine "schweren" Fragen für Fortgeschrittene+. Darum sollte man Hilfestellung geben, Verbesserungsvorschläge erbringen (am besten mit Links von Referenzen/Fakten - eben fundiert) und auch noch eine Erklärung hierzu abgeben, warum das in diesem Fall besser wäre. Hier kann man auch gerne Clean-Code ins Spiel bringen, um bei der Entwicklung des Programmierstils zu helfen.

Jeder Entwickler hat einen persönlichen Stil und bevorzugt gewisse Muster. Das soll heißen: Lasst andere Meinungen gelten und könnt gerne darüber diskutieren, aber immer mit einem gewissen Respekt.


----------



## DerUnwissende (21. Feb 2016)

Bei so einem Beispiel über Perfomace zu reden ist Unsinn. Wenn man mal die Lotto-App schreibt mit 1 Mio. Aufrufe pro Stunde, wird auch die Stelle mit der Gernerierung die kleinste Problem sein.

Ansonsten hat es hier im Anfängerbereich solche Lösungen mit Labels zu posten, den gleichen Charme als würde ein Architekturstudent im 5. Semester in den Legostore gehen um den Kids mal zu zeigen, wie man aus den Duplosteinen einen Turm richtig baut.


----------



## kneitzel (21. Feb 2016)

@Flown: Aber ich denke, dass Du es auch als sinnvoll ansiehst, wenn man Anfänger dort hin führt. Das läuft ja auch eigentlich immer ganz problemlos. So Diskussionen wie hier mit einer speziellen Person habe ich vorab auch nie erlebt. Denn wie soll ein Anfänger dies sonst lernen, wenn er nicht darauf hin gewiesen wird?


----------



## InfectedBytes (21. Feb 2016)

eine ganz spaßige Lösung ist es auch sich einen eigenen linearen kongruenzgenerator zu schreiben, welcher als maximale Periodenlänge 49 hat:

```
private static int last = 0;
public static int next() {
    last = (15 * last + 13) % 49;
    return last + 1; // 1-49 anstatt 0-48
}
```

Damit besteht das folgende Array aus 6 paarweise verschiedenen Zahlen im Bereich von 1-49

```
last = (int)(Math.random() * 49); // zufälligen seed setzen
int[] zahlen = {next(), next(), next(), next(), next(), next()};
```

*Vorteil:*
Super schnell (am besten noch inlinen)
Ergebnis erscheint auf den ersten blick zufällig.

*Nachteil:*
Im grunde nutzt der algorithmus nur eine *feste* *permutation *der zahlen von 1-49. Daher ist die reihenfolge der zahlen immer gleich und diese ist:
32 38 30 8 21 20 5 25 31 23 1 14 13 47 18 24 16 43 7 6 40 11 17 9 36 49 48 33 4 10 2 29 42 41 26 46 3 44 22 35 34 19 39 45 37 15 28 27 12
danach geht es dann wieder von vorne los

durch den seed bestimmt man nur wo man in dieser reihe beginnt.

*Ergo:*
Da immer die gleiche permutation genutzt wird, macht es natürlich keinen sinn das in einer "echten" Anwendung zu nutzen, in der man möglichst echt wirkenden zufall braucht.
Falls man jedoch nicht auf sowas aus ist, dann hat man damit natürlich einen sehr schnellen algorithmus.

p.s.
Natürlich könnte man sich auch gleich eine Permutation vorgenerieren und immer daraus ziehen 

edit:
hier einmal geinlined:

```
final int N = 6;
int[] zahlen = new int[N];
int x = (int)(Math.random() * 49);
for(int i = 0; i < N; i++) {
    x = (15 * x + 13) % 49;
    zahlen[i] = x + 1;
}
```


----------



## Flown (21. Feb 2016)

@InfectedBytes sehr unkonventionell gedacht. Gefällt mir!

@kneitzel Ich stimme dir zu, was ich auch geschrieben habe. Aber zuerst soll man sein eigenes abstraktes Denken fördern bevor man sich um Clean-Code kümmert. Wobei am besten wäre es, wenn sich sowas parallel entwickeln würde.


----------



## Xyz1 (21. Feb 2016)

Ich will mich nicht zu weit aus dem Fenster lehnen, aber:


DerWissende hat gesagt.:


> Er terminiert für höhere n nicht, weil Zufallszahlen nicht wirklich Zufallszahlen sind, müsste man schon das Hintergrundrauschen des Universums beobachten dafür.



das ist das Problem. Zufallszahlen sind nicht echte Zufallszahlen.

Meine Hypothese wäre jetzt, für n=36 terminiert er irgendwann, für n=37 nicht mehr, da es in der Folge von Zufallszahlen keine Teilfolge gibt, in der 37 Zufallszahlen ohne Wiederholung(en) gezogen werden.

Die Wahrscheinlichkeit lässt sich berechnen.

Deswegen bräuchte man echte Zufallszahlen, mit denen der Algorithmus für 0<=n<=49 IMMER terminieren wird, es dauert halt ein bisschen.

Auch 1,2,3,4,5,6,...,48,49 wird mit einer "bestimmten" Wahrscheinlichkeit gezogen werden, bei echten Zufallszahlen.

Das wäre nicht ohne Folgen für die "Lotto-Wirtschaft". Es gäbe einmal viele Gewinner und danach würden sich viele betrogen fühlen.


----------



## DerUnwissende (21. Feb 2016)

So auch wenn ich vorher gemeckert hab, will ich auch mal. Hier meine Lösung:


```
private Random random = new Random();

    public int[] lotto() {
        boolean[] lookup = new boolean[49];
        int[] result = new int[6];
        for (int i = 0; i < result.length;) {
            int zug = random.nextInt(49);
            if (!lookup[zug]) {
                lookup[zug] = true;
                result[i++] = zug + 1;
            }
        }
        return result;
    }
```

Ich verwalte die gezogenen Zahlen in einem boolean array. Eine viel performantere Möglichkeit, um nachzuschauen ob eine Zahl schon gezogen wurde, fällt mir nicht ein. Dafür verbraucht es aber auch ein bisschen mehr Speicher.


----------



## JStein52 (21. Feb 2016)

@DerUnwissende : ist keine Kritik, aber es gibt ja schon einige auch uralte Threads hier zu Lottozahlen und da gab es so eine Lösung mit einem Bool-Array auch schon mal. Und die gefällt mir gut. Bin gespannt was noch alles kommt


----------



## Jardcore (22. Feb 2016)

Finde diese Lösung immer schön leserlich und intuitiv. 

```
private static final int NUMBER_OF_NUMBERS_YOU_WANT = 6; // :)
    private static final int MAX_NUMBERS = 49;
    private static final int INDEX_OF_FIRST_NUMBER = 0;
  
    @Test
    public void drawTest() {
        System.out.println(drawNumbers(createNumbers()));
    }
  
    private List<Integer> drawNumbers(List<Integer> numbers) {
        List<Integer> result = new ArrayList<Integer>();
      
        for(int i = 1; i <= NUMBER_OF_NUMBERS_YOU_WANT; i++) {
            Collections.shuffle(numbers);
            result.add(numbers.remove(INDEX_OF_FIRST_NUMBER));
        }
      
        Collections.sort(result);
      
        return result;
    }
  
    private List<Integer> createNumbers() {
        List<Integer> zahlen = new ArrayList<Integer>();
      
        for(int i = 1; i <= MAX_NUMBERS; i++) {
            zahlen.add(i);
        }
        return zahlen;
    }
```


----------



## JStein52 (22. Feb 2016)

Dieser Thread hier ist soooo cool. Wir hatten einfach angefangen, sind dann in ein Einstein-Universum der Softwareentwicklung gerissen worden und kommen nun wieder zum Einfachen zurück. Wenn jetzt wieder einer mit einem Einzeiler kommt flip ich aus.


----------



## Jardcore (22. Feb 2016)

```
Random random = new Random();
IntStream.generate( () -> 1 + random.nextInt(49) ).limit(6).forEach(System.out::println);
```
2 Zeilen und Java 8. 

Quellen: http://www.straub.as/java/history/java8/workingwithstreams.html

Edit: da frage ich mich, werden hier wirklich 6 unique Zahlen gesucht?


----------



## InfectedBytes (22. Feb 2016)

nicht ganz, du musst noch verhindern, dass eine zahl nicht mehrfach vorkommt. Dazu gab es vor ein paar seiten einen schönen einzeiler mit java8

edit:
hier der einzeiler von @thecain 

```
final int[] ints =new Random().ints(1, 50).distinct().limit(6).toArray();
```


----------



## JStein52 (22. Feb 2016)

Jardcore hat gesagt.:


> 2 Zeilen und Java 8.


Ich werf mich weg  Aber InfectedBytes hat recht, das ist ja fast ein Plagiat !!


----------



## InfectedBytes (22. Feb 2016)

@JStein52 falls du unbedingt einen Einzeiler willst, hier mal der pseudo lotto zahlen generator mit Java8 

```
int[] arr = IntStream.iterate((int)(Math.random() * 49), x -> (15 * x + 13) % 49).limit(6).toArray();
```


----------



## Xyz1 (22. Feb 2016)

Jardcore hat gesagt.:


> Finde diese Lösung immer schön leserlich



Leserlich nicht, aber eine höhere Güte als Math.random()/Random, das stimmt schon.


----------



## Jardcore (22. Feb 2016)

*Realität*:
1. Schütte 49 Bälle in das Ziehgerät.
2. Ziehe 6 mal einen Ball.
    2.1. Mische die Bälle.
    2.2. Ziehe einen Ball.
3. Sortiere die gezogenen Bälle.

*Programm*:
1. Erstelle eine Liste mit 49 Zahlen.
2. Ziehe 6 mal eine Zahl.
    2.1. Shuffel die Liste der Zahlen.
    2.2. Ziehe die erste Zahl der Liste.
3. Sortiere die gezogenen Zahlen.

Das unleserliche liegt hier wohl eher an Java himself XD der Ablauf ist ja genau der gleiche wie beim Lotto 


DerWissende hat gesagt.:


> eine höhere Güte als Math.random()/Random


Collections.shuffle() benutzt übrigens auch den Zufall


----------



## JStein52 (22. Feb 2016)

DerWissende hat gesagt.:


> aber eine höhere Güte als Math.random()/Random


Wie ist diese Güte-Metrik definiert ??


----------



## javastudent25 (23. Feb 2016)

Ähmm, ich hoffe ich störe mal nicht 

Ich hab ein kleines Problem, dann wäre die Aufgabe endlich fertig..

Ich verstehe den Fehler einfach nicht, sprich ich weiss nicht warum er meckert, die Methoden gibt es ja schon

Multiple markers at this line
    - The method getKombiArray() is undefined for the type
    KombiArray
    - The method getrandomKombi() is undefined for the type
    RandomKombi

Betrifft die Zeile:
vergleich.vergleicheArrays(kombiArray.getKombiArray(), randomKombi.getrandomKombi());

im "Lottozahlen"


```
import java.io.*;
import java.text.*;
import java.util.*;
import java.lang.String;

public class Lottozahlen {

    public static void main(String[] args) {

        RandomKombi randomKombi = new RandomKombi();
        KombiArray kombiArray = new KombiArray();
        Vergleich vergleich = new Vergleich();
        vergleich.vergleicheArrays(kombiArray.getKombiArray(), randomKombi.getrandomKombi());
    }
  
}
```


```
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

//Programm, um 3 vorgegebene Arrays mit zufällig generierten zu vergleichen

public class KombiArray {

    private int[] kombiArray; // in der Liste vorkommender Array/Kombination

    private void importFile() {

        String zeile = ("");

        try {

            FileReader reader = new FileReader("lottozahlen.txt");
            BufferedReader br = new BufferedReader(reader);

            while ((zeile = br.readLine()) != null) {
                stringTointArray(stringTointArray(zeile));
            }

            br.close();

        } // end try
        catch (FileNotFoundException ex) {
            System.out.println("File nicht gefunden");
        } // end catch
        catch (IOException ex) {
            System.out.println("Lesefehler");
        } // end catch
        catch (IndexOutOfBoundsException ex) {
            System.out.println("der String[][] array ist zu klein für diese Textfilegroesse");
            System.out.println("maximal sind " + "900000" + " Zeilen moeglich");
            System.exit(1);
        } // end try

    } // end importFile

    private String[] stringTointArray(String z) { // wandelt den eingelesenen
                                                    // Text
                                                    // in StringArray

        String string = z;
        String[] strArray = string.split(" ");

        for (int i = 0; i < strArray.length; i++) {
            System.out.print(strArray[i] + " ");
        }
        return strArray;
    }

    private void stringTointArray(String[] x) {

        String[] strArray = x;
        kombiArray = new int[strArray.length];
        for (int i = 0; i < strArray.length; i++)
            kombiArray[i] = Integer.parseInt(strArray[i]);
    }

    public int[] getKombiArray() {
        importFile();
        return kombiArray;
    }


}
```


```
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Random;
import java.util.Set;

public class RandomKombi {

    private int[] zufallsZahlen = new int[6];
    private int[] gluecksZahl = new int[1];
    private int[] randomKombi = new int[zufallsZahlen.length + gluecksZahl.length];
  

    public int[] getrandomKombi() {
        getGesamtArray();
        return randomKombi;
    }

    private void zahlenAusgeben() {

        for (int i = 0; i < randomKombi.length; i++) {
            System.out.print(randomKombi[i] + " ");
        }
    }

    private void erzeugeZahlenArray() {

        Random rand = new Random();
        int randomNumber;
        for (int i = 0; i < zufallsZahlen.length; i++) {
            do {
                randomNumber = rand.nextInt(42) + 1;
            } while (containsValue(zufallsZahlen, randomNumber));
            zufallsZahlen[i] = randomNumber;
        }
    }

    private void erzeugeGlueckszahl() {

        Random random = new Random();
        int zufall = random.nextInt(6) + 1;
        gluecksZahl[0] = zufall;

    }

    private void getGesamtArray() {

        erzeugeZahlenArray();
        Arrays.sort(zufallsZahlen);
        erzeugeGlueckszahl();

        for (int i = 0; i < zufallsZahlen.length; i++) {
            randomKombi[i] = zufallsZahlen[i];
        }
        for (int i = 0; i < gluecksZahl.length; i++) {
            randomKombi[zufallsZahlen.length + i] = gluecksZahl[i];
        }
        zahlenAusgeben();

    }

    private boolean containsValue(int[] array, int value) {
        for (int i = 0; i < array.length; i++) {
            if (array[i] == value) {
                return true;
            }
        }
        return false;
    }


}
```


```
public class Vergleich {

public void vergleicheArrays(int[] x, int[] y) {
      
        int[] kombiArray = x;
        int[] RandomArray = y;
        boolean bool = true;
      
           for(int i=0; i<RandomArray.length; i++){
              if(kombiArray[i] != RandomArray[i]){
                  bool = false;
              }
              }
           if (bool == false){
                System.out.println("\n Der zufällig generierte Array kommt im File nicht vor");
           }else{
              System.out.println("Der zufällig generierte Array kommt im File vor");
           }
    }
  
}
```


----------



## Meniskusschaden (23. Feb 2016)

Ich finde dazu keinen passenden Fehler. Ist das wirklich derselbe Quelltext? Oder sind die letzten Änderungen der Datei KombiArray vielleicht noch nicht gespeichert?


----------



## javastudent25 (23. Feb 2016)

Ich habe es jetzt einfach mal kompiliert, jetzt sind die Fehler auf einmal weg..??
na gut, aber er findet mir das File irgendwie nicht..
es liegt aber in dem selben Ordner wie es bei einem anderen Programm, der Fall war, da hats auch funktioniert 

File nicht gefunden
5 6 11 14 19 20 4 Exception in thread "main" java.lang.NullPointerException
    at Vergleich.vergleicheArrays(Vergleich.java:11)
    at Lottozahlen.main(Lottozahlen.java:13)


----------



## javastudent25 (23. Feb 2016)

Ok, das FileProblem habe ich jetzt raus

irgendwie kommen mir jetzt ein Haufen Fehler

Exception in thread "main" java.lang.NumberFormatException: For input string: ""
    at java.lang.NumberFormatException.forInputString(Unknown Source)
    at java.lang.Integer.parseInt(Unknown Source)
    at java.lang.Integer.parseInt(Unknown Source)
    at KombiArray.stringTointArray(KombiArray.java:61)
    at KombiArray.importFile(KombiArray.java:23)
    at KombiArray.getKombiArray(KombiArray.java:65)
    at Lottozahlen.main(Lottozahlen.java:13)

Im Code habe ich noch einen kleinen Fehler ausgebessert


```
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

//Programm, um 3 vorgegebene Arrays mit zufällig generierten zu vergleichen

public class KombiArray {

    private int[] kombiArray; // in der Liste vorkommender Array/Kombination

    private void importFile() {

        String zeile = ("");

        try {

            FileReader reader = new FileReader("lottozahlen.txt");
            BufferedReader br = new BufferedReader(reader);

            while ((zeile = br.readLine()) != null) {
                stringTointArray(stringTostringArray(zeile));
            }

            br.close();

        } // end try
        catch (FileNotFoundException ex) {
            System.out.println("File nicht gefunden");
        } // end catch
        catch (IOException ex) {
            System.out.println("Lesefehler");
        } // end catch
        catch (IndexOutOfBoundsException ex) {
            System.out.println("der String[][] array ist zu klein für diese Textfilegroesse");
            System.out.println("maximal sind " + "900000" + " Zeilen moeglich");
            System.exit(1);
        } // end try

    } // end importFile

    private String[] stringTostringArray(String z) { // wandelt den eingelesenen
                                                    // Text
                                                    // in StringArray

        String string = z;
        String[] strArray = string.split(" ");

        for (int i = 0; i < strArray.length; i++) {
            System.out.print(strArray[i] + " ");
        }
        return strArray;
    }

    private void stringTointArray(String[] x) {

        String[] strArray = x;
        kombiArray = new int[strArray.length];
        for (int i = 0; i < strArray.length; i++){
            kombiArray[i] = Integer.parseInt(strArray[i]);
        }
    }

    public int[] getKombiArray() {
        importFile();
        return kombiArray;
    }


}
```


----------



## Meniskusschaden (23. Feb 2016)

Also, das ist jetzt vielleicht gemein von mir, aber zwischen deinen letzten beiden Posts liegen nur ca. 10 Minuten und in der Zeit hast du sogar, dass  FileProblem gelöst. Willst du nicht lieber etwas hartnäckiger versuchen, den anderen Fehler selbst zu beheben. Obwohl die Fehlermeldung so lang ist, ist es nur ein kleiner Fehler und die Meldung enthält alle nötigen Infos.


----------



## javastudent25 (23. Feb 2016)

ja das Fileproblem war nicht schwer, weil das eine Datei war und kein Textdokument.
Also kein direkter Programmierfehler.
Naja, ich weiss nicht, ab hier komme ich wirklich nicht weiter und übrigens bin ich schon eine Stunde da dran, den Fehler zu finden.


----------



## Meniskusschaden (23. Feb 2016)

Na ja, ich habe es vielleicht auch übertrieben. Ich weiß nämlich gar nicht, ob der Fehler leicht zu beheben ist, weil ich mir das nicht angesehen habe. Aber die Ursache ist leicht zu finden. Du musst nur nachsehen, in welcher Zeile das Problem auftritt. Die erkennst du, indem du in der langen Fehlermeldung die erste Zeile suchst, in der eine von dir programmierte Klasse genannt wird. Dort steht die Zeilennummer. Dann kannst du dir noch mal die allererste Meldung ansehen. Dort steht, was falsch gelaufen ist und auch mit welchen Eingabedaten es falsch gelaufen ist.


----------



## javastudent25 (23. Feb 2016)

ok, die ersten 4 Zeilen sagen mir nichts, ich weiss auch nicht was ich jetzt genau machen sollte.
gut gehen wir weiter:
at KombiArray.stringTointArray(KombiArray.java:61)
ok, 
kombiArray_ = Integer.parseInt(strArray);
ich seh da keinen Fehler..

import file zeile 24
stringArrayTointArray(stringTostringArray(zeile));
hmm, ich sehe keinen Fehler..

zeile 65
importFile();
auch nichts..

so was nun, ist ja alles richtig?

im main zeile 13
        vergleich.vergleicheArrays(kombiArray.getKombiArray(), randomKombi.getrandomKombi());
auch kein fehler..
alles ok

was nun?_


----------



## Meniskusschaden (23. Feb 2016)

javastudent25 hat gesagt.:


> ok, die ersten 4 Zeilen sagen mir nichts, ich weiss auch nicht was ich jetzt genau machen sollte.
> gut gehen wir weiter:
> at KombiArray.stringTointArray(KombiArray.java:61)
> ok,
> ...



Oft ist nur die erste Meldungszeile aus einer eigenen Klasse wichtig. Das ist hier bereits die Zeile, in der das Problem in Erscheinung tritt. Sie ist aber trotzdem korrekt. Du musst dir jetzt überlegen, was die Zeile eigentlich macht und das in Bezug zur eigentlichen Exception setzen, also der ersten Meldungszeile. Dann siehst du, was parseInt hier versucht und warum das nicht geht.


----------



## Jardcore (23. Feb 2016)

Du kannst kein StringArray mit Integer.parseInt () in einen Int Wert umwandeln. Du musst schon die einzelnen Werte des strArray nehmen und die einzeln parsen.


----------



## javastudent25 (24. Feb 2016)

ja was meinst du was ich mit der for schleife mache?
strarray(i)_ ist ja ein einzelelement_


----------



## Meniskusschaden (24. Feb 2016)

Ich glaube, die eckigen Klammern werden hier irgendwie weggefiltert, wenn man sie nicht in Code-Tags setzt. Oben im Quelltext sieht die Zeile wie folgt aus:

```
kombiArray[i] = Integer.parseInt(strArray[i]);
```


----------



## javastudent25 (24. Feb 2016)

leute kommt zum punkt
was soll denn da sein?
string index 1 2 3 wird umgeschrieben in index von int array
na und ist doch richtig
ich weiss nicht was ihr wollt. 
redet klartext bitte


----------



## Meniskusschaden (24. Feb 2016)

Hier steht bereits alles:


javastudent25 hat gesagt.:


> Exception in thread "main" java.lang.NumberFormatException: For input string: ""



Sieh dir doch mal an, was in strArray gespeichert ist.


----------



## kneitzel (24. Feb 2016)

Geh den Code im Debugger durch, damit Du genau siehst, wie die Datei eingelesen wird und welche Werte dann als Strings gefunden werden. Und dann wirst Du den Fehler evtl. finden - entweder im Code oder in der Datei, die Du einliest. Denn der Fehler ist ja ein Laufzeitfehler, denn zur Laufzeit versuchst Du einen String in einen Integer Wert umzuwandeln, der nicht umwandelbar ist (weil es der leere String ist).


----------



## Xyz1 (24. Feb 2016)

Ich hab mir (immer noch nicht) alles durchgelesen, aber diese Klasse könnte @javastudent25 bestimmt weiterhelfen:

```
import java.io.*;
import java.util.*;

/**
 */
public class Lotto {
    private static final Random rando = new Random();

    /*
     * Test all Methods... print/write/read 10 times random
     */
    public static void main(String[] args) throws IOException {
        for (int i = 0; i < 10; i++) {
            System.out.println(arrayToString(stringToArray(arrayToString(generateArray()))));
        }
        for (int i = 11111; i < 11121; i++) {
            arrayToFile(generateArray(), new File("" + i + ".txt"));
        }
        for (int i = 11111; i < 11121; i++) {
            System.out.println(arrayToString(arrayFromFile(new File("" + i + ".txt"))));
        }
    }

    private static int[] generateArray() {
        int[] intAry = new int[6];
        boolean[] boolAry = new boolean[49];
        for (int i = 0; i < intAry.length;) {
            int r = rando.nextInt(boolAry.length);
            if (!boolAry[r]) {
                boolAry[r] = true;
                intAry[i] = r + 1;
                i++;
            }
        }
        Arrays.sort(intAry);
        return intAry;
    }

    private static String arrayToString(int[] intAry) {
        String s = "";
        for (int i : intAry) {
            s += i + " ";
        }
        return s;
    }

    private static int[] stringToArray(String s) {
        int[] intAry = new int[6];
        String[] split = s.split("\\s+");
        for (int i = 0; i < intAry.length; i++) {
            intAry[i] = Integer.parseInt(split[i]);
        }
        return intAry;
    }

    private static void arrayToFile(int[] intAry, File file) throws IOException {
        stringToFile(arrayToString(intAry), file);
    }

    private static void stringToFile(String s, File file) throws IOException {
        FileWriter fw = new FileWriter(file);
        fw.write(s);
        fw.close();
    }

    private static int[] arrayFromFile(File file) throws IOException {
        return stringToArray(stringFromFile(file));
    }

    private static String stringFromFile(File file) throws IOException {
        FileReader fr = new FileReader(file);
        char[] cbuf = new char[(int) file.length()];
        fr.read(cbuf);
        fr.close();
        return new String(cbuf);
    }
}
```

Was passiert da? Es kann ein Array generiert werden und dieses kann in eine Datei geschrieben werden.

Frage nebenbei: Sollen Kolonnen von Zahlen in eine Datei geschrieben werden?

Über Kritik bin ich dankbar.


----------



## javastudent25 (24. Feb 2016)

ok, verstanden.
das liegt wohl dran, dass im Textdokument
die erste kombination in einer Zeile steht
dann 2 Leerzeilen kommen und dann erst wieder eine Kombi usw.

Denn das erste Mal funktioniert ja, aber Zeile 2 gibt es Probleme.

das heisst ich bastle jetzt mal ein if rein..
aber geht das irgendwie im Textfile bereits die Leerzeichen zu entfernen?

Edit: Ich habe jetzt mal das hier reingebastelt, aber irgendwie ignoriert er mir das if in der Methode importFile()


```
while ((zeile = br.readLine()) != null) {
                if (zeile != "") {
                    stringArrayTointArray(stringTostringArray(zeile));
                }
            }
```


----------



## InfectedBytes (24. Feb 2016)

strings vergleicht man eben mit equals


----------



## javastudent25 (24. Feb 2016)

ok, das hab ich auch schon zum x-ten Mal gehört.
Jetzt hab ich das auch mal intus 
danke


----------



## Xyz1 (24. Feb 2016)

Wie ist denn die Datei aufgebaut? Kannst du mal alles posten, was du im Moment hast, innerhalb von Java tags?


----------



## javastudent25 (24. Feb 2016)

Das Programm sieht so aus:

Ich weiss jetzt nur noch nicht, warum mich das Programm anlügt und den Zaehler in der Klasse Vergleich auf 5 setzt, obwohl nur 2 Arrays gleich sind.
Ich habe die Schleife so gemacht, dass ich sie zuerst ganz durchgehe und dann schaue, ob bool immer noch true ist, wenn ja setze ich den zaehler hoch.

Das Textdokument lottozahlen.txt sieht so aus:

4 11 22 30 32 37 1


1 4 20 25 30 31 8


9 16 23 25 30 34 3


9 16 23 25 30 34 3




```
import java.io.*;
import java.text.*;
import java.util.*;
import java.lang.String;

public class Lottozahlen {

    public static void main(String[] args) {

       
        KombiArray kombiArray = new KombiArray();
        kombiArray.importFile();
       
    }
   
}
```



```
public class Vergleich {

    private int zaehler = 0;

    Vergleich() {

    }

    public void vergleicheArrays(int[] x, int[] y) {

        int[] kombiArray = x;
        int[] RandomArray = y;
        boolean bool = true;
        int i = 0;

        while (bool == true) {
            for (i = 0; i < RandomArray.length; i++) {
                if (kombiArray[i] != RandomArray[i]) {
                    bool = false;
                }
            }
            if (bool == true) {
                bool = false;
                zaehler++;
            }
        }

    }

    public int getZaehler() {
        return zaehler;
    }
}
```



```
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Random;
import java.util.Set;

public class RandomKombi {

    private int[] zufallsZahlen = new int[6];
    private int[] gluecksZahl = new int[1];
    private int[] randomKombi = new int[zufallsZahlen.length + gluecksZahl.length];
   

    public int[] getrandomKombi() {
        getGesamtArray();
        return randomKombi;
    }

    private void zahlenAusgeben() {

        for (int i = 0; i < randomKombi.length; i++) {
            System.out.print(randomKombi[i] + " ");
        }
        System.out.println("\n");
        System.out.println("Dies ist die zufällig generierte Kombination \n");
    }

    private void erzeugeZahlenArray() {

        Random rand = new Random();
        int randomNumber;
        for (int i = 0; i < zufallsZahlen.length; i++) {
            do {
                randomNumber = rand.nextInt(42) + 1;
            } while (containsValue(zufallsZahlen, randomNumber));
            zufallsZahlen[i] = randomNumber;
        }
    }

    private void erzeugeGlueckszahl() {

        Random random = new Random();
        int zufall = random.nextInt(6) + 1;
        gluecksZahl[0] = zufall;

    }

    private void getGesamtArray() {

        erzeugeZahlenArray();
        Arrays.sort(zufallsZahlen);
        erzeugeGlueckszahl();

        for (int i = 0; i < zufallsZahlen.length; i++) {
            randomKombi[i] = zufallsZahlen[i];
        }
        for (int i = 0; i < gluecksZahl.length; i++) {
            randomKombi[zufallsZahlen.length + i] = gluecksZahl[i];
        }
        zahlenAusgeben();

    }

    private boolean containsValue(int[] array, int value) {
        for (int i = 0; i < array.length; i++) {
            if (array[i] == value) {
                return true;
            }
        }
        return false;
    }


}
```



```
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.*;

//Programm, um 3 vorgegebene Arrays mit zufällig generierten zu vergleichen

public class KombiArray {
   
    private int[] kombiArray; // in der Liste vorkommender Array/Kombination
    //private int[] randomKombination = {7, 22, 25, 29, 31, 40, 6};
    private int[] randomKombination = {9, 16, 23, 25, 30, 34, 3 };
    Vergleich vergleich = new Vergleich();
   
    KombiArray(){
           
    RandomKombi randomKombi = new RandomKombi();
    //randomKombination = randomKombi.getrandomKombi();
    }

    public void importFile() {

        String zeile = ("");

        try {

            FileReader reader = new FileReader("lottozahlen.txt");
            BufferedReader br = new BufferedReader(reader);

            while ((zeile = br.readLine()) != null) {
                if (!zeile.equals( "")) {
                    stringArrayTointArray(stringTostringArray(zeile));   
                }
                vergleich.vergleicheArrays(kombiArray, randomKombination);
            }

            br.close();

        } // end try
        catch (FileNotFoundException ex) {
            System.out.println("File nicht gefunden");
        } // end catch
        catch (IOException ex) {
            System.out.println("Lesefehler");
        } // end catch
        catch (IndexOutOfBoundsException ex) {
            System.out.println("der String[][] array ist zu klein für diese Textfilegroesse");
            System.out.println("maximal sind " + "900000" + " Zeilen moeglich");
            System.exit(1);
        } // end try
        System.out.println("Der zufällig generierte Array kommt im File insgesamt " + vergleich.getZaehler() + " mal vor");
    } // end importFile

    private String[] stringTostringArray(String z) { // wandelt den eingelesenen
                                                        // Text
                                                        // in StringArray

        String string = z;
        String[] strArray = string.split(" ");

        for (int i = 0; i < strArray.length; i++) {
            System.out.print(strArray[i] + " ");
        }
        System.out.println("\n");
        return strArray;
    }

    private void stringArrayTointArray(String[] x) {

        String[] strArray = x;
        kombiArray = new int[strArray.length];
        for (int i = 0; i < strArray.length; i++) {
            kombiArray[i] = Integer.parseInt(strArray[i]);
        }

    }

}
```


----------



## Meniskusschaden (24. Feb 2016)

Es wäre besser, die Testdatei in Code-Tags zu posten. Ich glaube, das hat DerWissende in seinem Post gemeint. Sind da wirklich Leerzeilen enthalten? Dann solltest du dir noch mal ansehen, unter welchen Bedingungen du vergleicheArrays aufrufst:


```
while ((zeile = br.readLine()) != null) {
     if (!zeile.equals( "")) {
          stringArrayTointArray(stringTostringArray(zeile));
     }
     vergleich.vergleicheArrays(kombiArray, randomKombination);
}
```


----------



## javastudent25 (24. Feb 2016)

Meniskusschaden hat gesagt.:


> Es wäre besser, die Testdatei in Code-Tags zu posten. Ich glaube, das hat DerWissende in seinem Post gemeint. Sind da wirklich Leerzeilen enthalten? Dann solltest du dir noch mal ansehen, unter welchen Bedingungen du vergleicheArrays aufrufst:
> 
> 
> ```
> ...



Hab den Fehler soeben auch gefunden.
Was meinst du mit Code-Tags
Ich habe ja den Code der TestVersion innerhalb von code=Java und /code mit eckigen Klammern

und durch if (!zeile.equals( "")) spielt ja vergleicheArrays ja keine Rolle mehr.
Da ich damit ja garantiere, dass immer Arrays verglichen werden oder hab ich da irgendwo einen Denkfehler??
Es funktioniert so jetzt.


----------



## javastudent25 (24. Feb 2016)

Übrigens, meine Java Note der Abschlussprüfung ist nur demotivierend (2,9). 6 ist die beste Note.
Ich hab die Note zwar mit anderen Fächern raufgezogen, aber ja es vermasselt mir halt den scheiss Schnitt.
Aber es regt mich mehr auf, dass ein Klassenkamerad, der einen sechser hat und zufällig neben mir sitzt, bei dem Lottoprogramm überhaupt keinen Schimmer hat und nur dumme Fragen stellt...
Da frag ich mich nur was ich falsch mache..


----------



## Meniskusschaden (24. Feb 2016)

javastudent25 hat gesagt.:


> Hab den Fehler soeben auch gefunden.
> Was meinst du mit Code-Tags
> Ich habe ja den Code der TestVersion innerhalb von code=Java und /code mit eckigen Klammern


Ich meinte die Textdatei mit den Testdaten, damit man genau sieht, ob da Leerzeilen oder Leerzeichen enthalten sind.



javastudent25 hat gesagt.:


> und durch if (!zeile.equals( "")) spielt ja vergleicheArrays ja keine Rolle mehr.
> Da ich damit ja garantiere, dass immer Arrays verglichen werden oder hab ich da irgendwo einen Denkfehler??
> Es funktioniert so jetzt.


Wundert mich, dass es funktioniert, denn der Aufruf von vergleicheArrays() steht ja ausserhalb der Bedingung. Hätte erwartet, dass der Vergleich für jede Leerzeile noch einmal mit dem vorherigen Array durchgeführt wird.


----------



## InfectedBytes (24. Feb 2016)

schön das dein programm nun funktioniert, allerdings würde ich dir sehr empfehlen es nochmal komplett zu überarbeiten, oder es vielleicht sogar einfach neu zu schreiben.
Es ist sehr unübersichtlich und durcheinander.
Manche sachen können auch sehr stark vereinfacht werden, wie z.b. dieses code fragment:

```
public void vergleicheArrays(int[] x, int[] y){
       int[] kombiArray = x;
       int[] RandomArray = y;
       boolean bool =true;
       int i =0;
       while(bool ==true){
           for(i =0; i < RandomArray.length; i++){
               if(kombiArray[i]!= RandomArray[i]){
                    bool =false;
               }
           }
           if(bool ==true){
                bool =false;
                zaehler++;
           }
       }
   }
```
zum einen prüfst du sowas wie: while(bool == true)
es reicht aber vollkommen aus: while(bool)
nebenbei ist bool natürlich auch ein unglücklicher name^^
Weiterhin ist die gesamte while schleife unnötig, da du sie *immer *nach dem ersten durchlauf abbrichst.
Kurzum, dein obiger code könntest du auf folgendes vereinfachen:

```
public boolean vergleicheArrays(int[] x, int[] y) {
  for(int i=0; i<x.length; i++) {
    if(x[i] != y[i]) return false;
  }
  return true;
}
```

Den eigenen Code nochmal zu überarbeiten oder neu zuschreiben kann dem Verständnis sehr helfen


----------



## javastudent25 (24. Feb 2016)

InfectedBytes hat gesagt.:


> schön das dein programm nun funktioniert, allerdings würde ich dir sehr empfehlen es nochmal komplett zu überarbeiten, oder es vielleicht sogar einfach neu zu schreiben.
> Es ist sehr unübersichtlich und durcheinander.
> Manche sachen können auch sehr stark vereinfacht werden, wie z.b. dieses code fragment:
> 
> ...



ich hab deinen Code mal eingegeben, weiss aber überhaupt nicht warum dieser jetzt auch funktioniert.
1. brauche ich ja jetzt so das boolean nicht mehr, man könnte ja jetzt das return auch weglassen
2. gehe ich alles durch, die Schleife endet und danach setze ich den zaehler nach jedem Durchgang hoch.
troztdem aber ist so das Ergebnis 11

übrigens funktioniert das Programm nur, weil ich den vergleichArray() in die if genommen habe.
hatte ja geschrieben, dass ich den Fehler raus habe..

hier nochmals die Codes:

Das Textdokument lottozahlen.txt sieht so aus:


```
4 11 22 30 32 37 1


1 4 20 25 30 31 8


9 16 23 25 30 34 3


9 16 23 25 30 34 3


9 16 23 25 30 34 3


9 16 23 25 30 34 3


9 16 23 25 30 34 3


9 16 23 25 30 34 3


9 16 23 25 30 34 3


9 16 23 25 30 34 3


9 16 23 25 30 34 3


9 16 23 25 30 34 3


9 16 23 25 30 34 3
```




```
import java.io.*;
import java.text.*;
import java.util.*;
import java.lang.String;

public class Lottozahlen {

    public static void main(String[] args) {

      
        KombiArray kombiArray = new KombiArray();
        kombiArray.importFile();
      
    }
  
}
```



```
public class Vergleich {

    private int zaehler = 0;

    Vergleich() {

    }

//    public void vergleicheArrays(int[] x, int[] y) {
//
//        int[] kombiArray = x;
//        int[] RandomArray = y;
//        boolean bool = true;
//        int i = 0;
//
//        while (bool == true) {
//            for (i = 0; i < RandomArray.length; i++) {
//                if (kombiArray[i] != RandomArray[i]) {
//                    bool = false;
//                }
//            }
//            if (bool == true) {
//                bool = false;
//                zaehler++;
//            }
//        }
//
//    }
   
    public boolean vergleicheArrays(int[] x, int[] y) {
   
             for(int i=0; i<x.length; i++) {
               if(x[i] != y[i]) return false;
             }
             zaehler++;
             return true;
    }

    public int getZaehler() {
        return zaehler;
    }
}
```



```
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Random;
import java.util.Set;

public class RandomKombi {

    private int[] zufallsZahlen = new int[6];
    private int[] gluecksZahl = new int[1];
    private int[] randomKombi = new int[zufallsZahlen.length + gluecksZahl.length];
  

    public int[] getrandomKombi() {
        getGesamtArray();
        return randomKombi;
    }

    private void zahlenAusgeben() {

        for (int i = 0; i < randomKombi.length; i++) {
            System.out.print(randomKombi[i] + " ");
        }
        System.out.println("\n");
        System.out.println("Dies ist die zufällig generierte Kombination \n");
    }

    private void erzeugeZahlenArray() {

        Random rand = new Random();
        int randomNumber;
        for (int i = 0; i < zufallsZahlen.length; i++) {
            do {
                randomNumber = rand.nextInt(42) + 1;
            } while (containsValue(zufallsZahlen, randomNumber));
            zufallsZahlen[i] = randomNumber;
        }
    }

    private void erzeugeGlueckszahl() {

        Random random = new Random();
        int zufall = random.nextInt(6) + 1;
        gluecksZahl[0] = zufall;

    }

    private void getGesamtArray() {

        erzeugeZahlenArray();
        Arrays.sort(zufallsZahlen);
        erzeugeGlueckszahl();

        for (int i = 0; i < zufallsZahlen.length; i++) {
            randomKombi[i] = zufallsZahlen[i];
        }
        for (int i = 0; i < gluecksZahl.length; i++) {
            randomKombi[zufallsZahlen.length + i] = gluecksZahl[i];
        }
        zahlenAusgeben();

    }

    private boolean containsValue(int[] array, int value) {
        for (int i = 0; i < array.length; i++) {
            if (array[i] == value) {
                return true;
            }
        }
        return false;
    }


}
```



```
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.*;

//Programm, um 3 vorgegebene Arrays mit zufällig generierten zu vergleichen

public class KombiArray {
   
    private int[] kombiArray; // in der Liste vorkommender Array/Kombination
    //private int[] randomKombination = {1, 4, 20, 25, 30, 31, 8};
    private int[] randomKombination = {9, 16, 23, 25, 30, 34, 3 };
    Vergleich vergleich = new Vergleich();
   
    KombiArray(){
           
    RandomKombi randomKombi = new RandomKombi();
    //randomKombination = randomKombi.getrandomKombi();
    }

    public void importFile() {

        String zeile = ("");

        try {

            FileReader reader = new FileReader("lottozahlen.txt");
            BufferedReader br = new BufferedReader(reader);

            while ((zeile = br.readLine()) != null) {
                if (!zeile.equals( "")) {
                    stringArrayTointArray(stringTostringArray(zeile));   
                    vergleich.vergleicheArrays(kombiArray, randomKombination);
                }
               
            }

            br.close();

        } // end try
        catch (FileNotFoundException ex) {
            System.out.println("File nicht gefunden");
        } // end catch
        catch (IOException ex) {
            System.out.println("Lesefehler");
        } // end catch
        catch (IndexOutOfBoundsException ex) {
            System.out.println("der String[][] array ist zu klein für diese Textfilegroesse");
            System.out.println("maximal sind " + "900000" + " Zeilen moeglich");
            System.exit(1);
        } // end try
        System.out.println("Der zufällig generierte Array kommt im File insgesamt " + vergleich.getZaehler() + " mal vor");
    } // end importFile

    private String[] stringTostringArray(String z) { // wandelt den eingelesenen
                                                        // Text
                                                        // in StringArray

        String string = z;
        String[] strArray = string.split(" ");

        for (int i = 0; i < strArray.length; i++) {
            System.out.print(strArray[i] + " ");
        }
        System.out.println("\n");
        return strArray;
    }

    private void stringArrayTointArray(String[] x) {

        String[] strArray = x;
        kombiArray = new int[strArray.length];
        for (int i = 0; i < strArray.length; i++) {
            kombiArray[i] = Integer.parseInt(strArray[i]);
        }

    }

}
```


----------



## Meniskusschaden (24. Feb 2016)

javastudent25 hat gesagt.:


> übrigens funktioniert das Programm nur, weil ich den vergleichArray() in die if genommen habe.
> hatte ja geschrieben, dass ich den Fehler raus habe..


Dann leuchtet es mir auch ein. Danke für den Hinweis.


----------



## javastudent25 (25. Feb 2016)

kann mir nun noch jemand sagen, warum das so tut mit dem zaehler??
das sollte ja eigentlich nicht funktionieren...


----------



## Meniskusschaden (25. Feb 2016)

javastudent25 hat gesagt.:


> kann mir nun noch jemand sagen, warum das so tut mit dem zaehler??
> das sollte ja eigentlich nicht funktionieren...


Wenn die if-Bedingung zutrifft, verlässt du die Methode mittels `return false` und erreichst `zaehler++;` nicht mehr. Meinst du das?

```
public boolean vergleicheArrays(int[] x, int[] y) {
 
             for(int i=0; i<x.length; i++) {
               if(x[i] != y[i]) return false;
             }
             zaehler++;
             return true;
    }
```


----------



## javastudent25 (25. Feb 2016)

ahhh, ok, sobald das return kommt ist die methode vorbei.. jep danke 
ich seh mal, was ich programmtechnisch verbessern kann.


----------



## Xyz1 (25. Feb 2016)

Meniskusschaden hat gesagt.:


> Es wäre besser, die Testdatei in Code-Tags zu posten. Ich glaube, das hat DerWissende in seinem Post gemeint.



Ja, das meinte ich. Alles, was er braucht, steht schon in Post #114.  Ich helfe morgen mal.


----------

