Kann jemand den quellcode so verändern, dass keine doppelten Zufallszahlen vorkommen?

8 Antworten

Hi,

das Problem ist dass du das Random und die Schleifen falsch benutz!

Jedes mal wenn du eine neue Instanz von "Random" erzeugst, wird vermutlich die aktuelle Systemzeit als Seed (also als Ursprungswert für den Zufallszahlen Algorithmus) genutzt. Wenn die Systemzeit sich zwischen zwischenzeitlich nicht Ändert, kommt natürlich auch das selbe dabei raus!

Ein Array fängt immer bei 0 an!

So sollte es gehen:

public void Lottozahlen(int k, int n)
{

    Lottozahl = new int [n+1];
    Random r new Random();

    // Erzeugt k Zufallszahlen
    for(int i = 0;i <= k;i++)
    {
        Lottozahl [i] = r.nextInt(n)+1;
    }
  
    // Verhindert, dass Zahlen doppelt vorkommen
    for(int i = 0; i <= k; i++) // <- Bedingung war falsch
    {
        for(int j = 0; j <= k; j++)
        {
            while(Lottozahl [i] == Lottozahl [j] & i != j)
            {
                Lottozahl [j] = r.nextInt(n)+1;
            }
        }
    }
    
    // Sortiert die Zahlen
    for(int i = 0;i <= k; i++)
    {
        for(int j = 1;j <= k; j++)
        {
            if(Lottozahl [j] > Lottozahl [j+1])
            {
                x = Lottozahl [j];
                Lottozahl [j] = Lottozahl [j+1];
                Lottozahl [j+1] = x;
            }
        }
    }
    
    //Ausgabe
    for (int i = 1; i <= k; i++)
    {
       System.out.println("Lottozahl "+i+": " + Lottozahl[i]);
    }
}

Habs aber nicht getestet!

Ich glaube in der while-Schleife meinst du "&&" statt "&". Ich weiß nicht, wie es in der verwendeten Sprache dort mit Klammerung aussieht (ob "==" stärker bindet als "&&" oder umgekehrt). Die äußere For-Schleife wird nur einmal durchlaufen (solange "i == k", also bei der letzten Lottozahl).

Es kommt darauf an, wie groß das Feld ist, in dem die Zufallszahlen liegen sollen. Also, wenn du zwischen  1 und 20 willst, dann könntest du dein Programm auch ganz real Kugeln ziehen lassen. (Natürlich würde es für größere Zahlen auch gehen, aber ab ein paar 1000 wird es langsam werden - je nachdem, wie gut dein Rechner ist.)

Dazu machst du folgendes: Zunächst erzeugst du eine LinkedList<Integer> (!), in die du jede Zahl zwischen 0 und k  einmal hinzufügst. Am besten mit einer for-Schleife.

Anschließend lässt du dir n-mal eine Zufallszahl zwischen der Länge der Liste und 0 geben. Anschließend machst du folgendes: neue_liste.append(altelist.get(zufallszahl)) [oder: neue_liste.append(zufallszahl+1) - das geht nur, wenn du die zahlen geordnet hinzugefügt hast] und alteliste.remove(zufallszahl).

Die neue Liste wird alle deine gezogenen Zahlen enthalten.

Was Dein Programm in der jetzigen Form tut, ist dies: Es ignoriert zunächst die Wirklichkeit und zieht die Lottozahlen einfach drauflos, als ob es keine Doppelten gäbe. Hinterher versucht es dann, die wirklich gezogene Zahlenliste mit einer umständlichen Aktion zu reparieren.

Einfacher wäre, wenn Dein Programm das täte, was Du ja eigentlich willst: die doppelten Zufallszahlen vermeiden. Vermeiden muß man sie an der Stelle, wo sie erzeugt werden.

Dein Programm sollte bei jeder gezogene Zahl gleich überprüfen, ob sie schon einmal gezogen wurde, und falls ja, solange weiterziehen, bis es eine hat, die noch nicht gezogen wurde. Das geht besonders bequem, wenn Du zur Aufbewahrung der gezogenen Zahlen anstatt des Arrays einen Mengentyp verwendest, z.B. ein HashSet.

Hier ist ein Beispiel, an dem Du die dadurch erzielte Vereinfachung auf den ersten Blick sehen kannst: http://www.mpi-inf.mpg.de/departments/d5/teaching/ss05/is05/java/GoToJava2.2/html/k100097.html


Franz1957  17.03.2014, 13:44

Eine logisch besonders saubere Lösung bekommst Du, wenn Du zu Beginn für den Wertevorrat eine Menge vorbereitest, in der die zulässigen Zahlen bereitliegen wie die Kugeln in der Lottomaschine. Anschließend wird bei jeder einzelnen Ziehung ein Wert dieser Menge entnommen und der Menge der gezogenen Zahlen hinzugefügt. Auf diese Weise können an keiner Stelle des Ablaufs Doppelte auftreten und es sind keine Prüfungsschleifen erforderlich.

0

Man muss berücksichtigen, dass mit jeder neuen Ziehung die Zahl der vorhandenen Kugeln um 1 weniger wird. Wenn man das nicht macht, funktioniert das zwar auch einigermaßen, die Zufallszahl ist aber keine echte Zufallszahl mehr. Hat man nur noch noch 48 Kugeln und zieht die Zufallszahl 48, so entspricht dies der gezogenen Zufallszahl 49. Diese Verschiebung muss man im Array lösen, indem man z.B. jedesmal durchzählt und die bereits gezogenen und entsprechend markierten dabei überspringt. Praktisch hätte das kaum Bedeutung, wenn dies aber eine Prüfungsaufgabe ist, dann schon.