Lottoziehung mithilfe einer Liste

user1234569

Mitglied
Hallo! Für die Klausurvorbereitung mache ich grade ein paar Aufgaben und eine lautet wie folgt: "Implementieren Sie die Ziehung der Lottozahlen (6 aus 49) mit Hilfe einer Liste! Die Liste soll aus den Zahlen von 1 bis 49 bestehen. Wenn eine Zahl gezogen wurde, soll sie aus der Liste ausgekettet werden." - dabei ist die Verwendung der Collection-Klassen untersagt.

Nach ewig langem Hin und Her habe ich jetzt auch eine Lösung, die auf den ersten Blick gut aussah - sich auf den zweiten allerdings als falsch herausstellte - irgendwie werden manchmal 5 oder auch 7 Zahlen "gezogen" und das sind dann auch noch andere als meine Math.random() Methode erstellt hat. Hier ist mein Code: (Pastebin Link: https://pastebin.com/cuq3QYaF)
Java:
public class Aufg1LottoZahl {
    int zahl;
    Aufg1LottoZahl next;
    Aufg1LottoZahl prev;
 
    public Aufg1LottoZahl(int zahl) {
        this.zahl = zahl;
    }
 
    public Aufg1LottoZahl() {
        this.zahl = -1;
    }
 
    public int getZahl() {
        return zahl;
    }
 
    public void setNext(Aufg1LottoZahl next) {
        this.next = next;
    }
 
    public Aufg1LottoZahl getNext()  {
        return next;
    }
    public void setPrev(Aufg1LottoZahl next) {
        this.next = next;
    }
 
    public Aufg1LottoZahl getPrev()  {
        return next;
    }
}
Java:
public class Aufg1LottoMain {
    public static void main(String[] args) {
        Aufg1LottoZahl[] lottozahlen = new Aufg1LottoZahl[49];
        for (int i = 0; i < lottozahlen.length; i++) {
            lottozahlen[I] = new Aufg1LottoZahl(i + 1);
            if (i > 0 && i < 48) {
                lottozahlen[I].setNext(lottozahlen[i + 1]);
                lottozahlen[I].setPrev(lottozahlen[i - 1]);
            }
            else if (i == 48) {
                lottozahlen[I].setNext(lottozahlen[0]);
                lottozahlen[I].setPrev(lottozahlen[i - 1]);
            }
            else if (i == 0) {
                lottozahlen[I].setPrev(lottozahlen[48]);
                lottozahlen[I].setNext(lottozahlen[i + 1]);
            }
        }
        ziehung(lottozahlen);
    }
  
    public static void ziehung(Aufg1LottoZahl[] lottozahlen) {
        int randomZahl;
        for (int i = 0; i < 6; i++) {
            randomZahl = (int) (Math.random() * 49);
            while (lottozahlen[randomZahl].getNext() == null && lottozahlen[randomZahl].getPrev() == null) {
                randomZahl = (int) (Math.random() * 49);
            }
            System.out.print(randomZahl + "  "); //Ausgabe der 6 erstellten Random Zahlen zum Abgleich mit den eigentlichen 6 Zahlen
            (lottozahlen[randomZahl].getPrev()).setNext(lottozahlen[randomZahl].getNext());
            (lottozahlen[randomZahl].getNext()).setPrev(lottozahlen[randomZahl].getPrev());
            lottozahlen[randomZahl].setNext(null);
            lottozahlen[randomZahl].setPrev(null);
        }
        System.out.println();
        for (int i = 0; i < 49; i++) {
            if (lottozahlen[I].getNext() == null && lottozahlen[I].getPrev() == null) {
                System.out.print(lottozahlen[I].getZahl() + "  ");
            }
        }
    }
}
 
Zuletzt bearbeitet:

Robat

Top Contributor
Ich würde sagen, es ist eher Zufall, dass dein Programm funktioniert.
Suche hier mal die 2 Fehler. ;)
Java:
    public void setPrev(Aufg1LottoZahl next) {
        this.next = next;
    }
 
    public Aufg1LottoZahl getPrev()  {
        return next;
    }
Wenn du die Fehler verbessert hast, sollten dir die Exceptions nur so um die Ohren fliegen :p
 

user1234569

Mitglied
Super danke das war wirklich ein dummer Fehler, sowas kommt davon wenn man einfach die Getter und Setter von Next kopiert und für Prev einfügt haha! Habe das jetzt korrigiert und zusätzlich noch den Code in der Main Methode geändert und aus der einen for Schleife zwei gemacht; siehe hier:
Java:
public static void main(String[] args) {
        Aufg1LottoZahl[] lottozahlen = new Aufg1LottoZahl[49];
        for (int i = 0; i < lottozahlen.length; i++) {
            lottozahlen[i] = new Aufg1LottoZahl(i + 1);
        }
        for (int i = 0; i < lottozahlen.length; i++) {
            if (i > 0 && i < 48) {
                lottozahlen[i].setNext(lottozahlen[i + 1]);
                lottozahlen[i].setPrev(lottozahlen[i - 1]);
            }
            else if (i == 48) {
                lottozahlen[i].setNext(lottozahlen[0]);
                lottozahlen[i].setPrev(lottozahlen[i - 1]);
            }
            else if (i == 0) {
                lottozahlen[i].setPrev(lottozahlen[48]);
                lottozahlen[i].setNext(lottozahlen[i + 1]);
            }
        }
        ziehung(lottozahlen);
    }

Jetzt habe ich auch immer nur genau 6 Zahlen - das passt also soweit! Allerdings sind die ausgegebenen Random Zahlen immer noch unterschiedlich zu den ausgegeben "ausgeketteten" (also quasi gezogenen) Zahlen. Warum?
 

user1234569

Mitglied
Allerdings sind die ausgegebenen Random Zahlen immer noch unterschiedlich zu den ausgegeben "ausgeketteten" (also quasi gezogenen) Zahlen. Warum?
Okay hat sich auch geklärt! Die Zahlen sehen nur auf den ersten Blick unterschiedlich aus - auf den zweiten fällt auf, dass sie nur sortiert werden und +1 addiert wird (da es ja Zahlen von 1-49 sind; in der Math.random() Funktion aber Zahlen von 0-48).
Danke nochmal für die Hilfe!
 

mihe7

Top Contributor
@user1234569 Du arbeitest ausschließlich mit einem Array, in dem Elemente einer verketteten Liste stecken. Die ganze Logik fußt auf dem Array und nebenher passt Du (weil es halt gefordert ist) noch die internen Verkettungen der "Liste" an.

Ich denke nicht, dass das Sinn der Aufgabe ist:
a) Du übergibst an ziehung() ein Array und keine Liste
b) die Elemente einer verketteten Liste sind ein Implementierungsdetail, auf das du von außen keinen Zugriff hast oder haben solltest.

Davon einmal abgesehen brauchst Du keine doppelt verkettete Liste.

Neue Herausforderung: wie sieht die Lösung aus, wenn Du auf Arrays vollständig verzichtest?
 

user1234569

Mitglied
@user1234569 Du arbeitest ausschließlich mit einem Array, in dem Elemente einer verketteten Liste stecken. Die ganze Logik fußt auf dem Array und nebenher passt Du (weil es halt gefordert ist) noch die internen Verkettungen der "Liste" an.

Ich denke nicht, dass das Sinn der Aufgabe ist:
a) Du übergibst an ziehung() ein Array und keine Liste
b) die Elemente einer verketteten Liste sind ein Implementierungsdetail, auf das du von außen keinen Zugriff hast oder haben solltest.

Davon einmal abgesehen brauchst Du keine doppelt verkettete Liste.

Neue Herausforderung: wie sieht die Lösung aus, wenn Du auf Arrays vollständig verzichtest?
Das hat mir mein Prof auch gesagt haha, ich arbeite derzeit an einer solchen Lösung
 

user1234569

Mitglied
Wir sind schon gespannt.
Ich komme einfach nicht drauf. Habe jetzt die LottoZahl Klasse minimal abgeändert sodass es eine einfach verkettete Liste wird siehe hier:
Java:
public class LottoZahl {
    int zahl;
    LottoZahl next;
  
    public LottoZahl(int zahl) {
        this.zahl = zahl;
    }
  
    public void setZahl(int zahl) {
        this.zahl = zahl;
    }
    public int getZahl() {
        return zahl;
    }
  
    public void setNext(LottoZahl next) {
        this.next = next;
    }
    public LottoZahl getNext() {
        return next;
    }
}
Die Main Klasse habe ich nahezu komplett geändert; die Ziehung findet in einem Array statt. Dann wird jedes Listen Element auf Gleichheit mit einem der Array Werte überprüft und falls es gleich ist wird es (in der Theorie) aus der Liste ausgekettet.
Am Ende wird die Liste ohne ausgekettete Elemente ausgegeben.
Allerdings scheint er bei mir nicht die Elemente auszuketten, denn es werden einfach alle Zahlen von 1-49 ausgegeben.
Java:
public class LottoListe {
    public static void main(String[] args) {
       //Erstellen der Liste mit den 49 verketteten Elementen
        LottoZahl start = null;
        start = new LottoZahl(1);
        LottoZahl temp = start;
        for (int i = 1; i < 49; i++) {
            LottoZahl k = new LottoZahl(i + 1);
            temp.setNext(k);
            temp = k;
        }
        //Würfeln der 6 random Zahlen
        int[] randomZahlen = new int[6];
        for (int i = 0; i < 6; i++) {
            randomZahlen[i] = (int) (Math.random() * 49 + 1);
            if (i == 0);
            else {
                for (int j = 0; j < i; j++) {
                    while (randomZahlen[i] == randomZahlen[j]) {
                        randomZahlen[i] = (int) (Math.random() * 49 + 1);
                    }
                }
            }
        }
      //gezogene Zahlen ausklinken
        LottoZahl durchlaufen = start;
        while (durchlaufen != null) {
            for (int i = 0; i < 6; i++) {
                if (durchlaufen.getZahl() == randomZahlen[i]) {
                    //dann klinke diese Zahl aus
                    LottoZahl zuloeschen = durchlaufen;
                    LottoZahl einsvorloeschen = start;
                    while (einsvorloeschen.getNext() != zuloeschen) {
                        einsvorloeschen = einsvorloeschen.getNext();
                    }
                    einsvorloeschen.setNext(zuloeschen.getNext());
                    zuloeschen.setNext(null);
                }
            }
            durchlaufen = durchlaufen.getNext();
        }
       //Ausgabe aller Listenelemente
        LottoZahl ausgeben = start;
        while (ausgeben != null)   {
            System.out.print(ausgeben.getZahl() + " ");
            ausgeben = ausgeben.getNext();
        }
//Ausgabe der 6 gezogenen Zahlen (optional)
//        System.out.println();
//        for (int i = 0; i < 6; i++) {
//            System.out.print(randomZahlen[i] + " ");
//        }
    }
}
 

mihe7

Top Contributor
die Ziehung findet in einem Array statt.
Kein Array verwenden. Deine Klasse LottoZahl stellt ein Element der Liste dar. Die Listen-Semantik (size, get, remove, ...) musst Du natürlich schon noch irgendwie implementieren. Der Ziehungs-Algorithmus ist dann trivial:
Code:
wiederhole 6 mal
    n := Zufallszahl zwischen 0 und size (excl.)
    gib n-tes Element aus Liste aus
    entferne n-tes Element aus Liste
 

temi

Top Contributor
Das ganz erscheint mir nicht sehr logisch. Deine Klasse "LottoZahl" ist in Wirklichkeit keine einzelne Zahl (wie der Name der Klasse suggeriert) sondern eine Art Liste. Eine Klasse "LottoZahl" müsste eigentlich ungefähr so aussehen:
Code:
public class Lottozahl {
    private int value;

    public Lottozahl(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

Dann solltest du dir auf jeden Fall einmal anschauen, welche Methoden eine Liste haben sollte und einen Teil davon (size, add, get, remove) implementieren.

Code:
public class LottozahlenListe {

    public void add(Lottozahl zahl) {
        // ...
    }

   // usw...
}

Diese Klassen kannst du dann in der Main verwenden.

Edit: Die oben beschriebene Klasse "Lottozahl" ist natürlich so trivial, dass man auf sie verzichten kann und gleich "int" nimmt. Deine Klasse "LottoZahl" entspricht damit der Listenklasse, nur solltest du das "setNext" und "getNext" weglassen und in den Methoden "add", "remove" usw. kapseln. Und den Namen solltest du auch anpassen.
 
Zuletzt bearbeitet:

temi

Top Contributor
@temi seine Aufgabe besteht darin, eine verkettete Liste zu verwenden :)
Schon klar. Ich wollte nur auf die ungünstig benannten Klassen hinweisen, denn seine Klasse "LottoZahl" ist keine einzelne Zahl, sondern eine Art von Liste, während die Klassse "LottoListe" keine Liste ist, sondern das Hauptprogramm.

Vermutlich habe ich jetzt erreicht, dass der TO komplett verwirrt ist :confused:
 

Rah2k

Mitglied
Also bei verketten Listen machen ich mir immer 2 Klassen: "Node" und "List". Node enthält eben alle benötigten Attribute während List Methoden zur Listen-Erstellung enthält. Damit bin ich immer ganz gut klar gekommen :)
 

mihe7

Top Contributor
Also bei verketten Listen machen ich mir immer 2 Klassen
Du brauchst dafür auch zwei Klassen. Was bei Dir Node ist, ist bei ihm Lottozahl und Deine List-Klasse fehlt ihm komplett. Dagegen heißt seine Main-Klasse LottozahlenListe. Anders formuliert: nimmt man an, dass seine Klasse Lottozahl Dein Node ist und weiter, dass LottozahlenListe die List sein soll, dann fehlt seiner Main-Klasse die List-Semantik.
 

Neue Themen


Oben