36 Zufallszahlen die sich nicht wiederholen

Hag2bard

Bekanntes Mitglied
Hallo,

Ich versuche mich mit Denkaufgaben fit zu halten.
Gestern beim Musik hören, stellte ich mal wieder fest dass die Shuffle Funktion manche Lieder nicht spielt und manche doppelt gespielt werden.
Sowas kann doch garnicht so schwer zu programmieren sein, dachte ich mir.
Ist es auch nicht, aber ich bekomme es trotzdem nicht hin.
Manche Zahlen wiederholen sich .
Ich möchte in einem 36 int großem Array 36 verschiedene Zahlen haben. Aber nur im Bereich von 1-36.

Dies ist mein Code dazu, der bei Erfolg natürlich noch deutlich übersichtlicher gestaltet wird.

Java:
package calculator;

import java.util.Scanner;
import java.util.Random;

public class randmusic {

public static void rand(){

Random mus = new Random();
int max=36;
int[] lieder = new int[max];
for (int i=0; i<max; i++){
  lieder[i]=mus.nextInt(max);
}

for (int i=0;i<max;i++){
  for (int j=0;j<max;j++){
    if (lieder[i]==lieder[j]&&i!=j){
    lieder[i]=mus.nextInt(max);
      i=0;
      j=0;
      
    }
  }
}
for (int i=0;i<max; i++){
System.out.println (lieder[i]+i);
}
}
}

Anstatt i und j auf 0 zu setzen werde ich die Funktion rekursiv aufrufen, aber das kommt später.
Wo liegt hier der Hund begraben ?

Danke im Voraus
 

Robert Zenz

Top Contributor
Klugscheiszerei an dieser Stelle: 36 Zahlen welche sich nicht wiederholen duerfen, koennen nicht zufaellig sein, es sind also keine Zufallszahlen.

Was du willst ist ein Fisher-Yates shuffle. Also du willst ein Array mit den Zahlen 1-36 und vertauscht dann darin zufaellig die Zahlen. Also im simpelsten:

Java:
for (int index = 0; index < array.length; index++) {
    int currentValue = array[index];
    int swapIndex = randomNumberGeneratorGoesHere(array.length);
    
    array[index] = array[swapIndex];
    array[swapIndex] = currentValue;
}
 
K

kneitzel

Gast
Also d würde ich gerne einmal mit Dir einen Schritt zurück gehen um da den Ansatz generell neu zu denken.

Das Problem, das ich hier glaube zu sehen, ist: Du hast Dir eine Komplexität geschaffen, die Du selbst nicht mehr überblicken kannst. Also zumindest in dem Sinne, dass Du da stärker Dir Gedanken machen musst. Und das ist ein generelles Problem, welches unabhängig von dem eigentlichen Algorithmus ist.

Aus meiner Sicht ist die Lösung, dass man ein Problem mehr unterteilt. Das Ergebnis muss sein, dass Du viele kleine, einfach zu verstehende Methoden bekommt. Code, der einfach zu verstehen ist.

Und dazu gehört, dass Du dir ein klares Model überlegst, wie dies funktionieren soll. Wie genau, ist dabei egal. Ich sehe auf Anhieb viele Möglichkeiten:

a) "Mischen" Lösung:
Du hast n Element und diese mischt Du einfach. Das könnte also recht einfach so formuliert sein:
- Array aufbauen
- Array mischen
==> fertig. Das sind dann neue Methoden. Array aufbauen geht einfach hin und erzeugt ein Array und füllt die Zahlen von 1...36 Array mischen kannst Du Dir überlegen. Du kannst z.B. das Array einmal durchgehen und jedes Element mit einem zufälligen Element tauschen.

b) "Array zufällig füllen" Lösung:
- Solange nicht genug Zufallszahlen gezogen wurden:
---> Zufallszahl ermitteln
---> Wenn Zufallszahl noch nicht im Array enthalten: Zufallszahl hinzufügen.
==> Hier erkennt man auch die einzelnen Methoden. Komplexität sehr gering und das was ich da geschrieben habe, ist dann unter dem Strich auch schon fast der Code - also ordentliche Bezeichner wählen!

c) "Karten ziehen" Lösung.
- Menge an Möglichkeiten Aufbauen
- So lange weitere Elemente benötigt werden:
---> Zufälliges Element auswählen und aus Menge entfernen.

Jeder der drei Wege hat Vor- und Nachteile. Wenn du n Elemente aus m Möglichkeiten brauchst, dann ist Mischen super, wenn n = m ist oder nahe dran. n << m würde für b sprechen. n = m oder n nahe m bei großem m spricht ganz klar gegen b.

Das wäre einfach einmal meine Hilfestellung zu dieser Problematik. Denn mit dem generellen Vorgehen und der Ansatz eben mit "Divide and Conquer" die Komplexität vom Code gering zu halten ist in der Softwareentwicklung eine absolute Notwendigkeit.
 

Blender3D

Top Contributor
Dies ist mein Code dazu, der bei Erfolg natürlich noch deutlich übersichtlicher gestaltet wird.
Dazu gibt es bekannte Strategien.
Statt eines boolean Arrays wäre Bitset effizienter.
[CODE lang="java" title="TestRndtakeDontPutBack"]public class TestRndtakeDontPutBack {

public static void main(String[] args) {
RndTakeDontPutBack rnd = new RndTakeDontPutBack(10);
while (rnd.hasNext()) {
System.out.println("song number " + rnd.next());
}
}
}[/CODE]
[CODE lang="java" title="RndTakeDontPutBack" highlight="13-20"]import java.util.Random;

public class RndTakeDontPutBack {
private static Random rnd = new Random(System.currentTimeMillis());

private boolean[] used;

public RndTakeDontPutBack(int size) {
used = new boolean[size];
}

public int next() {
if (!hasNext())
throw new IllegalStateException("All numbers are used!");
int num = 0;
do {
num = rnd.nextInt(used.length);
} while (used[num]);
used[num] = true;
return num + 1;
}

public boolean hasNext() {
for (int i = 0; i < used.length; i++) {
if (!used)
return true;
}
return false;
}

public void reset() {
for (int i = 0; i < used.length; i++)
used = false;
}

}
[/CODE]
 

Hag2bard

Bekanntes Mitglied
Hallo, danke für die vielen Antworten.
Ich schreibe und lese eure Beiträge über mein Handy, genau so benutze ich eine Java IDE fürs Handy, deshalb ist meine Formatierung wahrscheinlich nicht die beste.

Ich habe es jetzt so gelöst

Java:
package calculator;
import java.util.Random;

public class randmusic {

public static void rand(){

Random mus = new Random();
int max=36;
int[] lieder = new int[max];
for (int i=0; i<max; i++){
  lieder[i]=i;
}
int gem;
int[] gemischt = new int[max];

for (int i=0;i<max;i++){
gem=mus.nextInt(max);
if (lieder[gem]!=666){
lieder[gem]=666;
gemischt[i]=gem;
}
else if (lieder[gem]==666){
  i--;
}
}
for (int h=0;h<max;h++){
  System.out.println (lieder[h]);
}
System.out.println (" ");
for (int j=0;j<max;j++){
  System.out.println (gemischt[j]);
}




}
}

Ich habe also ein Array erstellt von 0-35 in sortierter Reihenfolge.
Von diesem habe ich dann in zufälliger Reihenfolge die Zahlen geholt und in ein neues Array gespeichert.
Das alte Array habe ich an den Stellen die ich bereits geholt habe mit dem Wert 666 gefüllt.

So funktioniert es auf alle Fälle.
Wenn ich mich auf den Beitrag von Blender kurz beziehen darf:

Nicht falsch verstehen, diese Frage kommt von einem Anfänger:

Warum so komplizierter Code?
Ist das Performanter, für einen Profi übersichtlicher?
Wieviele Jahre programmierst du schon ?
Machst du das beruflich?
 

temi

Top Contributor
Warum so komplizierter Code?
Also mir erscheint dein Code komplizierter, als der von @httpdigest. Die Aufteilung in Methoden hat schon mal den Vorteil, dass ich aus der Benennung der Methode erkennen kann, was die Methode tun soll. Außerdem führt eine Aufteilung dazu, dass die einzelnen zu lösenden Probleme kleiner werden.

Ganz allgemein handelt es sich bei RndTakeDontPutBack um eine recht universell einsetzbare Klasse, nicht nur für Songs. Du kannst sie einfach verwenden ohne interne Details kennen zu müssen und die Schnittstelle (hasNext(), next() und reset()) ist ziemlich selbsterklärend.
 
K

kneitzel

Gast
Also bei Deinem Code sind mehrere Dinge, die auffallen:
a) Die Performance ist schlecht. Dazu nur einmal schauen: Am Ende hast Du nur noch einen Wert und du gehst mit Zufallszahlen ran, um diesen zu bekommen. Das ist schon recht schlecht, wobei die 36 Möglichkeiten da natürlich dafür sorgen, dass es nicht zu lange dauert. Aber setz mal das max hoch und schau, wie es sich verändert. Setz es mal auf 1000, 10000, 100000, ... (Dabei ist dann die 666 natürlich auch zu ändern so Du nicht Punkt b mit berücksichtigst.)
b) Du speicherst in dem Array Lieder einen int, aber der interessiert Dich nicht. Dich interessieren eigentlich nur zwei Dinge: 666 oder nicht 666. => Damit wärst Du mit einem boolean evtl. besser dran.
=> Die Initialisierung könntest Du Dir sparen ... Werte von 1...36 braucht es nicht - da könnte auch alles weiter 0 bleiben.

Und die Unterteilung in Methoden solltest Du Dir wirklich überlegen und dir angewöhnen! Das wird Dir Dein Leben vereinfachen und dafür sorgen, dass Du Fehler einfacher finden kannst. Das ist leider ein Thema, das bei Anfängern viel zu oft total ignoriert wird. Clean Code ist extrem wichtig und da sollte man von Anfang an zumindest immer drauf angesprochen werden!
 

Blender3D

Top Contributor
Warum so komplizierter Code?
Der Code zu Lösung der Aufgabe ist lediglich.
[CODE lang="java" title="TestRndtakeDontPutBack" highlight="4-7"]public class TestRndtakeDontPutBack {

public static void main(String[] args) {
RndTakeDontPutBack rnd = new RndTakeDontPutBack(36);
while (rnd.hasNext()) {
System.out.println("song number " + rnd.next());
}
}
}[/CODE]
1) Erzeuge eine Zufallsobjekt, dass Zahlen im Bereich von 1 - 36 nur einmal zur Verfügung stellt.
2) Solange das die Zahlen nicht verbraucht sind, also das Objekt noch nicht verwendete Zahlen hat, entnimm eine verbleibende Zahl und gib sie aus.
Die verwendete Klasse RndTakeDontPutBack musst du dir dabei so vorstellen wie die auch dabei verwendete Klasse System.
Der Benutzer interessiert sich nicht dafür wie es gemacht wurde, sondern nur was es macht und wobei man es verwenden kann.
Ich programmiere schon etliche Jahre und habe auch an einigen größeren Projekten gearbeitet. Der Code den du gemacht hast würde unter die Kategorie nicht verwendbar fallen. Das muss dich nicht grämen, da du ja Anfänger bist.
Wichtig ist, es zu lernen, dass ein größeres Problem, immer in kleiner Probleme aufgeteilt werden kann und muss. Die Strategie nennt sich Teile und Herrsche. ( @kneitzel hat dir diesbezüglich bereits ein paar gute Tipps gegeben. ;) )
Das verbleibende Problem ist dann einfach zu lösen. Außerdem sind gefundenen Teillösungen wo anders wieder verbwendbar.
z.B. Könnte man die Klasse RndTakeDontPutBack für das zufällige ziehen von Karten aus einem Kartenspiel in einem anderem Projekt verwenden.
In deiner zukünftigen Laufbahn als Programmierer, wirst du auf viele Probleme stoßen, die es zu lösen gilt. Wenn du sauberen Code machst, diesen entsprechen dokumentierst und testest, entsteht daraus eine Sammlung die dir hilft, zukünftige Projekte einfacher und schneller zu lösen.
 

berndoa

Top Contributor
Ich werfe mal meine Noob mässige Idee dazwischen:
Ich würde zum einen ein boolean array anlegen, länge 36, und das überall mit true initialisieren.

dann ein leeres int array, länge 36, das wir der reihe nach von vorne nahc hinten befüllen wollen (man denke an das as der schule mit den 36 bällen in 36 fächer verteilen und so)

wir erzeugen eine zufallszahl Z aus dem Bereich 1-36.
wir gucken ob boolarray[Z-1] true ist.
falls ja, setzen wir Z an die erste stelle vom int array, also intarray[0]=Z
ebenso setzen wir boolarray[Z-1]=false, denne jene zahl Z ist nunn "verbraucht".

nun gehen wir zur nächsten stelle.
welche stelle im intarrax wir gerade befüllen, hätte ich einfach durch eine variable int counter fewstgehalten die mit jeder neubelegung um 1 höher gesetzt wird.


sollte hingegen bei unserer eingänglichen bool-prüfung false rauskommen, wir die gerade gefundene zahl also schon verwendet haben, dann würfeln wir direkt eine neue zufallszahl und gucken bei der ob sie verwendbar ist. dann vorgehen wie oben.

und klar, das vorgehen dauert so ewig weil gegen ende vielleicht noch 2 der 36 zahlen unbenutzt sind und der zufallsalgorithmus aber immer wieder nur schon benutzte zahlen findet.

----------------------------------------------------------


andere idee, die aber im prinzip gleich ist:
wir bilden anfangs ein array mit den zahlen 1-36, also wirklich int[] array={1,2,3,....,35,36}.
dieses hält zu jedem zeitpunkt die zahlen bereit die wir noch nicht benutzt haben.

benutzen wir eine zahl, so wird diese zahl aus dem array gestrichen (sprich: array durch ein neues array aber ohne jene zahl drin ersetzt).
und natürlich hängt das was der zufallsgenerator würfeln kann von der menge der unbenutzten zahlen ab.

konkret würfelt der randomizer eine zahl aus 0 bis (array.length-1) und die zahl, die letztlich an die stelle des zielarrays eingeführt wird, ist dann
zielarray[zahlenarray[zufallszahl]].


anmerkung: grundsätzlich würde man das erstellen eines neuen arrays, in dem im gegensatz zum vorgängerarray eine bestimmte zahl fehlt, mittels einer methode schreiben.
sowas schreibt man einfach nicht direkt in die main methode, sowas lagert man aus :)

Java:
import java.lang.Math;
//ich benutze lieber die Math Klasse weil da die random() Funktion drin ist
// diese liefert ein double im bereich (0,1[
// und nicht wie dein random stream irgendwelche int zahlen,
//die auch mal -354636636 oder so sein können

public class blabla{

//Hauptmethode halt
    public static void main(string[] args){
        int[] startarray=build36array();
        int[] zielarray=new int[36];

        
        int index=0;
        int randnumber;
        
        while(index<zielarray.length){
            //bestimmt int zufallszahl zwischen 0 und startarray.length-1
            randnumber=(int)(random()*startarray.length);
            //weist der aktuell betrachteten zielarray stelle
            //das element aus startarray mit index=randnumber zu
            zielarray[index]=startarray[randnumber];
            //entfernt faktisch jenes element aus dem startarray, da ja nun benutzt
            startarray=createcopywithoutcertainindex(startarray,randnumber);
            //index+1, um letztlich zur nächsten stelle im zielarray zu hüpfen
            index++;
        }
        
        //an dem Punkt hier ist den Zielarray mit den random
        //verteilten zahlen 136 fertig.
        //Du kannst nun damit tun was du willst.
        //Und ja, diese ganze prozedere hätte man auch in eine methode auslagern
        //können, die einem nur das fertige zielarray zurückgibt
    }
    
//baut das anfängliche Array mit den 36 verfügbaren Zahlen
    public static int[] build36array(){
        int[] array=new int[36];
        for(int i=0;i<array.length;i++){
            array[i]=i+1;
        }
        return array;
    }

//baut kopie des übergebenen arrays, in dem das Element an indexstelle=nopeindex nicht mehr vorkommt
    public static int[] createcopywithoutcertainindex(int[] array, int nopeindex){
        int[] dummy=new int[array.length-1];
        int zielindex=0;
        int laufindex=0;
        while(zielindex<array.length){
            if(laufindex!=nopeindex){
                dummy[zielindex]=array[laufindex];
                zielindex++;
            }
            laufindex++;
        }
        return dummy;
    }

}
 

Steven Hachel

Bekanntes Mitglied
Huhu,

und wie wäre es damit, oder zuviel Overhead?

Java:
        ThreadLocalRandom random = ThreadLocalRandom.current();
        Set<Long> set = new HashSet<>();
        int setLength = 36;
        while (set.size() < setLength) {
            set.add(random.nextLong(100));
        }

Steven
 

berndoa

Top Contributor
K

kneitzel

Gast
benutzen wir eine zahl, so wird diese zahl aus dem array gestrichen (sprich: array durch ein neues array aber ohne jene zahl drin ersetzt).
Es ist unnötig ein neues Array zu erstellen und alle Werte zu kopieren. Einfach statt der Länge des Arrays eine weitere Variable nutzen und dann wird das gewählte element mit dem letzten Element getauscht und dann die Variable, die das ende markiert, um eins verringert.
 

berndoa

Top Contributor
Es ist unnötig ein neues Array zu erstellen und alle Werte zu kopieren. Einfach statt der Länge des Arrays eine weitere Variable nutzen und dann wird das gewählte element mit dem letzten Element getauscht und dann die Variable, die das ende markiert, um eins verringert.
Dazu müsste ich dann erst mal eine Variable einführen die das Ende signalisiert.
Aber stimmt, wäre wohl wesentlich eifnacher, nur 2 Elemente im Array verttauschen und nen indexzeiger eins runter schieben :O
 

berndoa

Top Contributor
Habe mal meinen Code dahingehend ausgebessert:

Java:
import java.lang.Math;
//ich benutze lieber die Math Klasse weil da die random() Funktion drin ist
// diese liefert ein double im bereich (0,1[

public class blabla{

//Hauptmethode halt
    public static void main(string[] args){
        int[] startarray=build36array();
        int[] zielarray=new int[36];
        int endzeiger=zielarray.length-1;
        
        int zielindex=0;
        int randnumber;
        
        while(zielindex<zielarray.length){
            //bestimmt int zufallszahl zwischen 0 und endzeiger
            randnumber=(int)(random()*(endzeiger+1);
            //weist der aktuell betrachteten zielarray stelle
            //das element aus startarray mit index=randnumber zu
            zielarray[zielindex]=startarray[randnumber];
            //entfernt faktisch jenes element aus dem startarray, da ja nun benutzt
            switch(startarray,endzeiger,randnumber);
            endzeiger--;
            //index+1, um letztlich zur nächsten stelle im zielarray zu hüpfen
            zielindex++;
        }
        
        //an dem Punkt hier ist den Zielarray mit den random
        //verteilten zahlen 136 fertig.
        //Du kannst nun damit tun was du willst.
        //Und ja, diese ganze prozedere hätte man auch in eine methode auslagern
        //können, die einem nur das fertige zielarray zurückgibt
    }

//vertauscht im array die elemente an den indexstellen a und b miteinander
    public static void switch(int[] array, int a, int b){
        int dummy=0;
        dummy=array[a];
        array[a]=array[b];
        array[b]=dummy;
    }
                        
//baut das anfängliche Array mit den 36 verfügbaren Zahlen
    public static int[] build36array(){
        int[] array=new int[36];
        for(int i=0;i<array.length;i++){
            array[i]=i+1;
        }
        return array;
    }


}
 

X5-599

Top Contributor
@berndoa So wie ich das sehe brauchst du nicht mal ein neues Ziel-Array. Durch das Tauschen der Werte ist das original Array doch schon "gemischt".

Also so in etwa:
Code:
public static void shuffle(int[] array)
{
    Random r = new Random();
    
    int lastIndex = array.length-1;
    while(lastIndex > 0)
    {
        // get random index
        int randomIndex = r.nextInt(lastIndex);
        
        // swap values at lastIndex with the one at randomIndex
        int temp = array[lastIndex];
        
        array[lastIndex] = array[randomIndex];
        array[randomIndex] = temp;
        
        // decrement lastIndex to "freeze" the now random value(s) at the end of the array
        lastIndex--;
    }
}
 

Vivien

Mitglied
Ich weiß jetzt nicht genau ob das hierhin gehört (wenn nicht dann Entschuldigung), aber da ich noch am Anfang mit meinen Kenntnissen stehe, habe ich mich selbst auch mal gestern an dem Problem (als Übung sozusagen) versucht.
Folgendes ist dabei herausgekommen:

[CODE lang="java" title="ShufflePlayer.java"]public class ShufflePlayer {
SongSync sync;
Songmixer mix;
public ShufflePlayer(SongSync sync) {
this.sync = sync;
}
public ShufflePlayer(Songmixer mix) { //Wer ist im ShufflePlayer?
this.mix = mix; //ein mix ist im ShufflePlayer!
}

//main method
public static void main(String[] args) {

//Lese Anzahl der Songs auf Gerät ein
SongSync meineSynchronisation = new SongSync(0,0);
ShufflePlayer meineSongs = new ShufflePlayer(meineSynchronisation);
int TitelAufGerät = meineSongs.sync.getAnzahlTitel();
//hole aktuelle Songlänge
int AktuelleSongLaenge = meineSongs.sync.getDauer();



Songmixer meinSongmixer = new Songmixer(TitelAufGerät, AktuelleSongLaenge);
ShufflePlayer meineShuffleListe = new ShufflePlayer(meinSongmixer);
System.out.println("Es wurden " + meineShuffleListe.mix.getTitelAufGerät() + " Songs gespielt. Ende der Wiedergabe.");


}

}[/CODE]

[CODE lang="java" title="Songmixer.java"]import java.util.ArrayList;
import java.util.Random;

class Songmixer {
private int TitelAufGerät;
private int SongLaenge;


public Songmixer(int TitelAufGerät, int SongLaenge) {
this.TitelAufGerät = TitelAufGerät;
//Vorbereiten
ArrayList<Integer> songs = new ArrayList<Integer>();
int a = 1;
int i;
//Titelnummern vergeben
for (i=1; i<=TitelAufGerät; i++) {
songs.add(i);
}
//mischen & gespielte entfernen
while(a<i) {
/*System.out.println(songs);*/

Random r = new Random();
int zufallssong = songs.get(r.nextInt(songs.size()));
System.out.println("Spiele aktuell Song " + zufallssong + " von " + TitelAufGerät + " Song(s).");

try {
Thread.sleep(SongLaenge);
} catch(InterruptedException e) {}


songs.remove(songs.indexOf(zufallssong));
a++;
}

}

////////////////////////////////////////////

public int getTitelAufGerät() {
return this.TitelAufGerät;
}

}
[/CODE]

[CODE lang="java" title="SongSync.java"]class SongSync {

private int VerfügbareTitel;
private int SongDauer;

public SongSync(int VerfügbareTitel, int SongDauer) {
this.VerfügbareTitel = VerfügbareTitel;
//hier passende Methode einfügen um Audiodateien zu zählen? - erstmal statisch gelöst
this.VerfügbareTitel = 36;
//hier passende Methode einfügen um von jedem Song die Länge in millisekunden zu ermitteln - hier erstmal statisch gelöst - jeder Song dauert beispielhaft 2000 millisekunden = 2 Sekunden
this.SongDauer = 2000;

}

public int getAnzahlTitel() {
return this.VerfügbareTitel;
}

public int getDauer() {
return this.SongDauer;
}


}[/CODE]

Aber nachdem was ich hier sehe scheint mir mein Code irgendwie zu lang zu sein? 🤔 Über Feedback, Verbesserungsvorschläge & Kritik würde ich mich freuen :)🤔
Lg
 

berndoa

Top Contributor
Ich weiß jetzt nicht genau ob das hierhin gehört (wenn nicht dann Entschuldigung), aber da ich noch am Anfang mit meinen Kenntnissen stehe, habe ich mich selbst auch mal gestern an dem Problem (als Übung sozusagen) versucht.
Folgendes ist dabei herausgekommen:
....

Aber nachdem was ich hier sehe scheint mir mein Code irgendwie zu lang zu sein? 🤔 Über Feedback, Verbesserungsvorschläge & Kritik würde ich mich freuen :)🤔
Lg
öh, also zumindest ich habe mich mit dem eigentlichen songs hin und her tauschen gar nicht so beschäftigt,
sondern lediglich mit dem unterproblem "wie kann ich in einem gegeben array die werte zufällig hin und hertauschen und das mäglichst effizient?" .
Insofern sind unsere codes auch relativ kurz da. den eigentlichen song teil haben wir noch gar nicht angeguckt :)
 

berndoa

Top Contributor
@berndoa So wie ich das sehe brauchst du nicht mal ein neues Ziel-Array. Durch das Tauschen der Werte ist das original Array doch schon "gemischt".

Also so in etwa:
Code:
public static void shuffle(int[] array)
{
    Random r = new Random();
   
    int lastIndex = array.length-1;
    while(lastIndex > 0)
    {
        // get random index
        int randomIndex = r.nextInt(lastIndex);
       
        // swap values at lastIndex with the one at randomIndex
        int temp = array[lastIndex];
       
        array[lastIndex] = array[randomIndex];
        array[randomIndex] = temp;
       
        // decrement lastIndex to "freeze" the now random value(s) at the end of the array
        lastIndex--;
    }
}
Altes Thema, ich weiß, aber eins muss ich doch fragen:
Gibt es eigentlich einen praktishcen grund warum man wie hier ein Randomgenerator objekt erzeugt und dann die nextint() methode immer wieder aufruft?
und nicht einfach, wo benötigt Math.random() verwendet, halt jedes mal wieder wo ein int benötigt wird?

Hat das irgendwie performance Gründe oder so?
 

mihe7

Top Contributor
Oh, da gibt es sicher verschiedene Gründe (z. B. ist nextInt() anders implementiert, als man sich das vorstellen würde, um möglichst Gleichverteilung in allen Situationen zu erreichen), für mich gibt es zwei:
  1. Lesbarkeit: rand.nextInt(limit) vs (int)(Math.random() * limit)
  2. Testbarkeit: Random kann man einen seed mitgeben, um reproduzierbare Zahlenfolgen zu erhalten.
Wobei ich dazusagen muss, dass ich der Einfachheit halber durchaus gerne Math.random() verwende, insbesondere wenn man halt "mal eben" eine Zufallszahl braucht.
 

Hag2bard

Bekanntes Mitglied
Etwas unsauber aber vom Prinzip her sehr performant

Java:
import java.util.Random;
public class Main {


  public static void main(String[] args) {
  Random rnd = new Random();
   int [] songs = new int[36];
   for (int i=0; i<36; i++){
     songs[i]=i+1;
   }
   for (int i=0; i<500; i++){
   int rd = rnd.nextInt(36);
   int rd2 = rnd.nextInt(36);
   int temp=0;
   temp=songs[rd];
    
     songs[rd]=songs[rd2];
     songs[rd2]=temp;
   }
   for (int i=0;i<36;i++){
   System.out.println (songs[i]);
  
  }
  }
}
 

berndoa

Top Contributor
Etwas unsauber aber vom Prinzip her sehr performant

Java:
import java.util.Random;
public class Main {


  public static void main(String[] args) {
  Random rnd = new Random();
   int [] songs = new int[36];
   for (int i=0; i<36; i++){
     songs[i]=i+1;
   }
   for (int i=0; i<500; i++){
   int rd = rnd.nextInt(36);
   int rd2 = rnd.nextInt(36);
   int temp=0;
   temp=songs[rd];
 
     songs[rd]=songs[rd2];
     songs[rd2]=temp;
   }
   for (int i=0;i<36;i++){
   System.out.println (songs[i]);

  }
  }
}
soweit ich das sehe, gehst du also hin und machst 2 vertauschungen von willkürlich gewählten 2 zahlen aus deinem array.
Und das an die 500 mal.

okay, kann man.
wenn du aber sehr viel pech hast, werden trotz aller wahrhscheinlichkeit immer nur die ersten 5 zahlen vertauscht miteinander und die restlichen zahlen stehen schön aufsteigend da.

Da hat unsere letzte variante den vorteil dass auf jeden fall jede zahl an eine andere stelle gebracht wird.
also wirklich Alles "durchgemicht" ist.

Wobei ich bei längerem Überlegen, bei unserer Variante, ein Problem dabei sehe dass man die aktuelle zahl nur mit einer zahl aus dem rest array vertauscht.

Sagen wir mal wir haben ein array mit den zahlen 1-36 und analog dazu die indexstellen 0-35.

betrachten wir bspw. die zahl an index=33.

wohin wird die getauscht?
obwohl random, kann es nur an indexstelle 34 oder 35 kommen.

heißt die 34 würde mir der 35 oder 36 vertauscht werden.

heißt dann auch dass grundsätzlich die größeren zahlen immer noch tendenziell immer noch weiter rechts stehen.
eine möglichkeit wäre es , das array so zu mischen, umzudrehen und nochmal zu mischen.

dann wäre es richtig gut durch :)
 
Zuletzt bearbeitet:

Barista

Top Contributor
Ich habe in meiner IDE (Eclipse) einfach mal in den Quellcode von Collections.shuffle geschaut.

Da steht:
[CODE lang="java" title="aus java.util.Collections#shuffle"]for (int i=size; i>1; i--)
swap(arr, i-1, rnd.nextInt(i));
[/CODE]

Ich gehe davon aus, dass dies die bestmögliche Implementierung ist, weil dort viele Leute drauf schauen.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
H Zufallszahlen generieren Java Basics - Anfänger-Themen 5
J Zufallszahlen generieren und Werte vergleichen Java Basics - Anfänger-Themen 3
S Hilfe : Unendlich viele Zufallszahlen erstellen? Java Basics - Anfänger-Themen 8
J Fehler beim generieren von 4 Zufallszahlen Zahl doppelt ist eigentlich ausgeschlossen Java Basics - Anfänger-Themen 9
S Aus gleichverteilte Zufallszahlen normalverteilte Zufallszahlen generieren ? Java Basics - Anfänger-Themen 1
N Array mit Zufallszahlen und Divison Java Basics - Anfänger-Themen 7
A Mit Rekursion Zufallszahlen erstellen und größte finden Java Basics - Anfänger-Themen 5
S Schiffe versenken - Zufallszahlen in einem Array Java Basics - Anfänger-Themen 6
A Dreidimensionales Array mit Zufallszahlen befüllen Java Basics - Anfänger-Themen 18
J Klassen Math && Random: wie zufällig sind Zufallszahlen? Java Basics - Anfänger-Themen 19
T Methoden HashSet Objekt mit Zufallszahlen befüllen Java Basics - Anfänger-Themen 3
L Array-Problem/Zufallszahlen Java Basics - Anfänger-Themen 7
V Array mit Zufallszahlen - Anfänger - Hilfe Java Basics - Anfänger-Themen 12
B Zufallszahlen ohne Wiederholung Java Basics - Anfänger-Themen 10
D Array mit Zufallszahlen, dann sortieren: Hilfe gesucht! Java Basics - Anfänger-Themen 1
B Zufallszahlen unabhängig von Intervallen Java Basics - Anfänger-Themen 2
J Ungerade Zufallszahlen in JAVA Java Basics - Anfänger-Themen 31
B Zufallszahlen & Laufzeitmessung (insertionSort) Java Basics - Anfänger-Themen 7
W Zufallszahlen Java Basics - Anfänger-Themen 3
R Arrays Zufallszahlen Java Basics - Anfänger-Themen 10
W 10x10 Feld mit Zufallszahlen erstellen Java Basics - Anfänger-Themen 4
B Array erstellen,ausgeben,mit zufallszahlen füllen aber wie ? Java Basics - Anfänger-Themen 1
T Zufallszahlen von x bis 80 Java Basics - Anfänger-Themen 10
P Zufallszahlen ohne zahlen einer List Java Basics - Anfänger-Themen 21
K Keine doppelten Zufallszahlen im Array Java Basics - Anfänger-Themen 17
G Zufallszahlen Gewichten Java Basics - Anfänger-Themen 3
J Zufallszahlen Häufigkeit Java Basics - Anfänger-Themen 8
L 6stellige Zufallszahlen erzeugen & auf einzigartigkeit prüfen Java Basics - Anfänger-Themen 3
W Java 2 Teams mit Zufallszahlen Java Basics - Anfänger-Themen 2
R Keine doppelten Zufallszahlen Java Basics - Anfänger-Themen 2
F Array mit Zufallszahlen sortieren Java Basics - Anfänger-Themen 7
G Methoden BigInteger Zufallszahlen erzeugen Java Basics - Anfänger-Themen 5
X write() und Zufallszahlen Java Basics - Anfänger-Themen 2
L Zufallszahlen addieren Java Basics - Anfänger-Themen 6
J Mehrere Zufallszahlen erzeugen, aber keine darf doppelt erzeugt werden - Wie? Java Basics - Anfänger-Themen 5
T Problem mit Zufallszahlen Java Basics - Anfänger-Themen 2
T Matrizzen addition mit zufallszahlen Java Basics - Anfänger-Themen 10
E Zufallszahlen Java Basics - Anfänger-Themen 7
R Probleme mit Zufallszahlen Java Basics - Anfänger-Themen 10
K Datentypen Gleiche Zufallszahlen in verschiedenen Datenstrukturen Java Basics - Anfänger-Themen 6
C Zufallszahlen mit Arrays Java Basics - Anfänger-Themen 8
P Array mit Zufallszahlen von einem Wuerfel Java Basics - Anfänger-Themen 15
B Zufallszahlen in ein Array eintragen. Java Basics - Anfänger-Themen 7
P Zufallszahlen fuer Lotto generieren Java Basics - Anfänger-Themen 28
L Hilfe, doppelte Zufallszahlen Java Basics - Anfänger-Themen 13
S Wie Zufallszahlen in txt speichern? Java Basics - Anfänger-Themen 4
K zufallszahlen in Array Speichern = Nullpointer exception Java Basics - Anfänger-Themen 24
F Aus Regulären Ausdrücken Zufallszahlen bilden Java Basics - Anfänger-Themen 6
M Zufallszahlen mit Random Java Basics - Anfänger-Themen 4
S Summe von Zufallszahlen Java Basics - Anfänger-Themen 9
B Zufallszahlen Java Basics - Anfänger-Themen 5
M Zufallszahlen aus einem bestimmten Intervall Java Basics - Anfänger-Themen 5
N Normalverteilte Zufallszahlen mit benutzerdefiniertem/r EW/Var Java Basics - Anfänger-Themen 5
C Zufallszahlen Problem Java Basics - Anfänger-Themen 6
C Zufallszahlen Java Basics - Anfänger-Themen 3
C Frage zur Generierung von Zufallszahlen Java Basics - Anfänger-Themen 9
W Zufallszahlen für Array Java Basics - Anfänger-Themen 3
G Problem mit Zufallszahlen Java Basics - Anfänger-Themen 6
G Zufallszahlen die alles einmal vorkommen Java Basics - Anfänger-Themen 15
G Lotto Zufallszahlen zählen Java Basics - Anfänger-Themen 3
A Zufallszahlen generieren Java Basics - Anfänger-Themen 2
A Problem mit dem Zufallszahlen-Generator Java Basics - Anfänger-Themen 17
J Zufallszahlen einmalig ausgeben Java Basics - Anfänger-Themen 6
B Int Array mit Zufallszahlen füllen Java Basics - Anfänger-Themen 8
G Zufallszahlen ohne doppelten Wert Java Basics - Anfänger-Themen 5
R Zufallszahlen mit Java Java Basics - Anfänger-Themen 11
N Zufallszahlen wiederholungslos erzeugen Java Basics - Anfänger-Themen 8
G Zufallszahlen erraten Java Basics - Anfänger-Themen 8
K zufallszahlen int / double, gerade / ungerade problem . Java Basics - Anfänger-Themen 2
X Lotto Zufallszahlen mit ArrayList erstellen Java Basics - Anfänger-Themen 3
M Zufallszahlen fertig! aber nice to have noch offen Java Basics - Anfänger-Themen 5
M generierung von zufallszahlen Java Basics - Anfänger-Themen 4
B Zufallszahlen erzeugen die nicht gleich sind ;/ Java Basics - Anfänger-Themen 10
M Zufallszahlen Java Basics - Anfänger-Themen 3
B Satz Zufallszahlen ohne Wiederholung Java Basics - Anfänger-Themen 14
G Zufallszahlen Java Basics - Anfänger-Themen 4
N ganzzahlige Zufallszahlen Java Basics - Anfänger-Themen 13
B Zufallszahlen je einmal in Array einfügen Java Basics - Anfänger-Themen 4
H Zufallszahlen Java Basics - Anfänger-Themen 2
N Klassen Hintergrundfarbe in JPanel ändert sich nicht Java Basics - Anfänger-Themen 3
KogoroMori21 Wann ist der richtige Zeitpunkt, um sich Hilfe zu suchen? (Bin Informatik-Student) Java Basics - Anfänger-Themen 10
N Hey Leute und zwar versuche ich gerade ein 2D Spiel zu Programmieren aber die Figur will sich nicht nach links oder rechts bewegen :( Java Basics - Anfänger-Themen 12
T code so schreiben das er von sich selber anpasst (code soll die anzahl aller bustaben bestimmen) Java Basics - Anfänger-Themen 16
P Probleme mit NetBeans: Wie lässt sich jar. Datei an einem MacBook öffnen Java Basics - Anfänger-Themen 21
G Variable aktualisiert sich nicht in rekursiver Methode Java Basics - Anfänger-Themen 4
F abbruch Exception lässt sich nicht erstellen Java Basics - Anfänger-Themen 2
G jar file lässt sich nicht öffnen Java Basics - Anfänger-Themen 1
xaerez Threads Boolean Wert verändert sich nicht Java Basics - Anfänger-Themen 5
xaerez Threads Boolean Wert verändert sich nicht Java Basics - Anfänger-Themen 4
berserkerdq2 Spiel hängt sich immer in der 4 Runde auf, obwohl ich jede Runde das gleiche mache Java Basics - Anfänger-Themen 1
GoenntHack Java Text von JLabel verändert sich nicht Java Basics - Anfänger-Themen 1
E multiple Timer die sich nicht summieren Java Basics - Anfänger-Themen 12
J Mein Java Programm lässt sich nicht mehr bearbeiten Java Basics - Anfänger-Themen 2
A Konsolenausgabe verschiebt sich Java Basics - Anfänger-Themen 8
M Wie lassen sich Konstanten in Bedingung stellen? Java Basics - Anfänger-Themen 1
M Wie lassen sich Objektkonstanten initialisieren, wenn sie eine Bedingung erreichen? Java Basics - Anfänger-Themen 6
P Mein Programm wird zwar erfolgreich Compiliert, öffnet sich aber nicht Java Basics - Anfänger-Themen 6
I Probleme mit OutputStream - Datei lässt sich nicht öffnen Java Basics - Anfänger-Themen 4
B Programm beendet sich nicht und weiteres seltsames Verhalten Java Basics - Anfänger-Themen 9
Nina Pohl Ein Vorgang bezog sich auf ein Objekt, das kein Socket ist Java Basics - Anfänger-Themen 6

Ähnliche Java Themen

Neue Themen


Oben