Zufälligen Zahlencode, ohne mehrfacher Verwendung einer Ziffer

liamprog

Mitglied
Hallo,
ich möchte einen 4stelligen Zufallscode zwischen 1 und 8 ausgeben, das klappt auch, allerdings tritt der Code teilweise mit doppelten Ziffern auf, was nicht passieren soll. Was kann ich da eingeben? 🙂

import java.util.Random;

public class Zufallscode {
/**
* Prints random numbers between 1 and 8 (inklusiv)
*/
public static void main(String[] args) {
Random random = new Random();
int zufallsZahl;

for(int i=0; i<4; i++){
zufallsZahl = 1+ random.nextInt(8);
System.out.println(zufallsZahl);
}
}
}
 
Du kannst dir eine Liste mit den gewünschten Ziffern anlegen. Dann erzeugst du eine Zufallszahl zwischen 0 und Länge der Liste -1. Im Anschluss entfernst du das Listenelement mit dem gezogenen Index und und merkst es dir. Im Anschluss erzeugst du wieder eine Zufallszahl zwischen 0 und Länge der Liste - 1 usw...
 
Letztens war hier ein Thread, bei dem es um 36 unterschiedliche (eindeutig/unique) Zahlen ging, einfach da mal nachlesen.
 
Genau an den Thread habe ich auch gedacht, war nicht das Ende vom lied das man anfangs ein Array mit den zahlen 1-36 hatte,
dann mit for schleife von index=0 bis länge-2 ging und das element an der aktuellen indexstelle mit einem random element aus den rest-array vertauschte?

war ne echt coole und simple variante, ein array "durchzumischen" 🙂

Dürfte auch hier funktionieren, könnte man die durchmischmethode von dort fast unverändert wiederbenutzen 🙂
 
Zuletzt bearbeitet:
Richtig, im Prinzip funktioniert das wie beim Lottospielen. Man "zieht" aus einem Array mit n Elementen einfach zufällig m Zahlen und platziert die gezogenen Zahlen durch Vertauschen z. B. an den Beginn des Arrays (nacheinander, versteht sich), um sie beim nächsten Zug aus dem Spiel nehmen zu können. Gilt m >= n-2, dann hat man das komplette Array gemischt.
 
Hab die Problemstellung mit den sich wiederholenden Ziffern übernommen und als Übung (bin auch Anfänger) genutzt.
Eure Meinung zu meinem Lösungsvorschlag würde mich freuen.


Java:
import java.util.Random;

public class Main {

    public static void main(String[] args) {

        final int MIN_ZIFFER = 1;
        final int MAX_ZIFFER = 9;
        final int ANZAHL_ZIFFER = MAX_ZIFFER - MIN_ZIFFER + 1;
        final int ANZAHL_ZIFFER_CODE = 4;

        int aktuelleZahl = MIN_ZIFFER;

        int[] auswahlArray = new int[ANZAHL_ZIFFER];
        int[] codeArray = new int[ANZAHL_ZIFFER_CODE];

        for (int i = 0; i < ANZAHL_ZIFFER; i++) {
            auswahlArray[i] = aktuelleZahl;
            aktuelleZahl++;
        }

        for (int i = 0; i < ANZAHL_ZIFFER_CODE; i++) {
            boolean istZahlNeu = false;
            int neueCodeZahl = 0;
            
            while (!istZahlNeu) {
                Random zufallZahl = new Random();
                int indexNR = zufallZahl.nextInt(ANZAHL_ZIFFER);
                System.out.print(indexNR + ",");
                neueCodeZahl = auswahlArray[indexNR];
                istZahlNeu = true;
                
                for (int j = 0; j < i + 1; j++) {
                    if (codeArray[j] == neueCodeZahl) {
                        istZahlNeu = false;
                    }
                }
                
                if (istZahlNeu) {
                    codeArray[i] = neueCodeZahl;
                }
            }
        }

        System.out.println("\n");
        System.out.println("Ziffern im Auswahl Array");
        
        for (int element : auswahlArray) {
            System.out.print(element+",");
        }

        System.out.println("\n");
        System.out.println("Der generierte Code");

        for (int element : codeArray) {
            System.out.print(element);
        }
    }
}
 
Für einen Einsteiger ist das schon sehr ordentlich. Die Schleifenbedingung in Zeile 33 geht eins zu weit, dadurch wird auch codeArray[i] überprüft. Da dieser Eintrag aber erst später gesetzt wird, brauchst Du das an der Stelle nicht abzuprüfen. Kurz: j < i reicht.

Ansonsten könnte man bemängeln, dass Variablen immer so spät wie möglich und so früh als nötig deklariert werden sollten.

Wir können das ja mal kurz durchgehen:

Zeilen 7 bis 10: Konstanten zu Beginn definiert: sehr gut!

Zeile 12: kann unmittelbar vor die for-Schleife. aktuelleZahl wird ausschließlich in der for-Schleife benötigt. Theoretisch wäre aktuelleZahl (wie i) eine lokale Variable der for-Schleife. Die könnte man sogar so schreiben, dann wird der Code aber hässlich:
Java:
for (int i = 0, aktuelleZahl = MIN_ZIFFER; i < ANZAHL_ZIFFER; i++, aktuelleZahl++) {
    auswahlArray[i] = aktuelleZahl;
}
Hier würde ich aus Gründen der Lesbarkeit auch zu Deiner Variante greifen, aber aktuelleZahl eben unmittelbar vor der for-Schleife deklarieren.

Zeile 15: vor die nächste for-Schleife schieben. codeArray wird erst später benötigt.

Zeile 24: die kann ganz raus, denn bei neueCodeZahl handelt es sich um eine Variable, die lokal innerhalb der while-Schleife verwendet wird. Dazu muss man Zeile 30 lediglich schreiben als
Java:
int neueCodeZahl = auswahlArray[indexNR];

Zeile 27: vor die while-Schleife ziehen, da man nicht in jeder Wiederholung einen neuen Zufallsgenerator braucht.

Das wars eigentlich auch schon, was die Variablen betrifft.

Dass die Ausgaben mit einem Komma enden ist nicht schön, das könntest Du als Übung ändern. Wenn Du sattelfest bist, kannst Du den Code auch auf Methoden aufteilen.

Und bitte nicht von der Fülle des Texts verunsichern lassen. Ich betreibe hier z. T. Jammern auf hohem Niveau. Dein Code ist echt ok.
 
@JensXF

Es wäre besser, die Variable random ausserhalb der Schleife anzulegen.

1. kostet das Anlegen des Random-Objekts einiges an Laufzeit.

2. Benutzt Random die Systemzeit als seed, also wird möglicherweise immer die selbe Zahl geliefert, weil das Programm schneller als der Zeitwechsel sein kann.
 
@mihe7 @Barista

Vielen Dank für die Mühe - gar nicht mit so detaillierten Kommentaren gerechnet.
Die Variablen habe ich wie empfohlen an die entsprechenden Plätze verschoben.

Random zufallZahl steht jetzt vor der for-Schleife und wird nur einmal deklariert.

Die Sache mit Kommata setzen habe ich wie folgt gelöst:
Java:
System.out.println("Ziffern im Auswahl Array");

        int kommaCounter = 0;

        for (int element : auswahlArray) {
            System.out.print(element);
            if (kommaCounter < auswahlArray.length - 1) {
                System.out.print(",");
                kommaCounter++;
            }
        }

Den Code auf Methoden aufzuteilen werde ich sicher auch noch versuchen.
 
@mihe7 @Barista

Vielen Dank für die Mühe - gar nicht mit so detaillierten Kommentaren gerechnet.
Die Variablen habe ich wie empfohlen an die entsprechenden Plätze verschoben.

Random zufallZahl steht jetzt vor der for-Schleife und wird nur einmal deklariert.

Die Sache mit Kommata setzen habe ich wie folgt gelöst:
Java:
System.out.println("Ziffern im Auswahl Array");

        int kommaCounter = 0;

        for (int element : auswahlArray) {
            System.out.print(element);
            if (kommaCounter < auswahlArray.length - 1) {
                System.out.print(",");
                kommaCounter++;
            }
        }

Den Code auf Methoden aufzuteilen werde ich sicher auch noch versuchen.
Wenn Du beim Aufteilen auf Methoden aufmerksam bist, siehst Du ggf. auch einen Zusammenhang mit den Positionen der Variablen im Code 🙂

Was die Sache mit dem Komma betrifft, so ist die recht interessant. Dein Ansatz ist naheliegend (wobei man eine normale for-Schleife verwenden könnte, da man ja sowieso eine Laufvariable hat), hat allerdings einen Nachteil: man muss wissen, wie viele Elemente es insgesamt sind. Hat man eine Struktur, wo das nicht bekannt ist, funktioniert er nicht mehr. Interessant ist nun, dass das auch anders funktioniert. Dazu schaut man sich nicht an, was nach einem Element kommt, sondern was vor einem Element steht. Vor jedem Element steht ein Komma, nur vor dem ersten nicht. Das erste Element lässt sich immer bestimmen.

Dazu braucht man noch nicht einmal eine Laufvariable, hier reicht ein boolean:
Java:
boolean komma = false;
for (int element : auswahlArray) {
    if (komma) {
        System.out.print(",");
    }
    System.out.print(element);
    komma = true;
}

Weiß man, dass das Array mindestens ein Element besitzt, kann man mit einer Laufvariablen schreiben:
Java:
System.out.print(auswahlArray[0]); // erstes Element
for (int i = 1; i < auswahlArray.length; i++) { // Rest des Arrays
    System.out.print("," + auswahlArray[i]);
}
 
. . . hat allerdings einen Nachteil: man muss wissen, wie viele Elemente es insgesamt sind. Hat man eine Struktur, wo das nicht bekannt ist, funktioniert er nicht mehr.
Aber hat nicht jedes Array eine bestimmte Größe?
Also ich meine zum Zeitpunkt des Aufrufes der Methode array.length . . . egal ob kein Element enthalten ist (dann sollte nichts passieren),
10 oder 1000.

Sorry für die Nachfragen, aber ich weiß gerade nicht warum die Größe nicht bekannt sein sollte. Bei array.length wird doch das entsprechende Array gefragt: "Ey Array, sag mal, wie groß bist du eigendlich?" (Keine Ahnung ob das der genaue Wortlaut ist.🙂)
 
Hier dann wie versprochen mein Versuch den Code als eigene Klasse mit Methoden zu schreiben.
Ich lasse die Methode befuelleArray() direkt vom Konstruktor ausführen, hätte ich sicher dann direkt mit reinschreiben können, oder?

Main
Java:
public class Main {

    public static void main(String[] args) {
        
        CodeGenerator neuerCode = new CodeGenerator(0, 9, 4);
        neuerCode.generiereCode();
        neuerCode.ausgabeCode();
    }
}

Klasse CodeGenerator
Java:
import java.util.Random;

public class CodeGenerator {

    private int minZiffer;
    private int maxZiffer;
    private int anzahlZiffer;
    private int anzahlZifferCode;
    private int[] auswahlArray;
    private int[] codeArray;

    public CodeGenerator(int minZiffer, int maxZiffer, int anzahlZifferCode) {
        this.minZiffer = minZiffer;
        this.maxZiffer = maxZiffer;
        this.anzahlZifferCode = anzahlZifferCode;

        this.anzahlZiffer = this.maxZiffer - this.minZiffer + 1;

        if (this.anzahlZiffer < this.anzahlZifferCode) {
            System.out.println("Die Anzahl der zur Verfügung stehenden Ziffern reicht nicht aus \n"
                    + "um einen Code dieser Größe mit sich nicht wiederholenden Ziffern zu generieren.");
        } else {
            this.auswahlArray = new int[this.anzahlZiffer];

            befuelleArray();
        }
    }

    private void befuelleArray() {
        int aktuelleZahl = this.minZiffer;

        for (int i = 0; i < this.anzahlZiffer; i++) {
            this.auswahlArray[i] = aktuelleZahl;
            aktuelleZahl++;
        }
    }

    public void generiereCode() {
        this.codeArray = new int[this.anzahlZifferCode];
        Random zufallZahl = new Random();

        for (int i = 0; i < this.anzahlZifferCode; i++) {
            boolean istZahlNeu = false;

            while (!istZahlNeu) {
                int indexNR = zufallZahl.nextInt(this.anzahlZiffer);
                int neueCodeZahl = this.auswahlArray[indexNR];
                istZahlNeu = true;

                for (int j = 0; j < i; j++) {
                    if (this.codeArray[j] == neueCodeZahl) {
                        istZahlNeu = false;
                    }
                }

                if (istZahlNeu) {
                    this.codeArray[i] = neueCodeZahl;
                }
            }
        }
    }

    public void ausgabeCode() {
        System.out.println("Ziffern im Auswahl Array");

        boolean komma = false;

        for (int element : this.auswahlArray) {

            if (komma) {
                System.out.print(",");
            }
            System.out.print(element);
            komma = true;
        }

        System.out.println("\n");
        System.out.println("Der generierte Code");

        for (int element : this.codeArray) {
            System.out.print(element);
        }
    }

    public int getMinZiffer() {
        return minZiffer;
    }

    public void setMinZiffer(int minZiffer) {
        this.minZiffer = minZiffer;
    }

    public int getMaxZiffer() {
        return maxZiffer;
    }

    public void setMaxZiffer(int maxZiffer) {
        this.maxZiffer = maxZiffer;
    }

    public int getAnzahlZifferCode() {
        return anzahlZifferCode;
    }

    public void setAnzahlZifferCode(int anzahlZifferCode) {
        this.anzahlZifferCode = anzahlZifferCode;
    }

    public int getAnzahlZiffer() {
        return anzahlZiffer;
    }

    public int[] getAuswahlArray() {
        return auswahlArray;
    }

    public int[] getCodeArray() {
        return codeArray;
    }

}
 

Zurück
Oben