Frage von BillHatayu, 36

Programmieren C/C++. In einem Array sollen zufällig Zahlen von 1-20 verteilt sein, aber jede Zahl nur einmal. Wer weiß weiter?

Mein Ansatz bis jetzt: 

//Für den Zufallsgenerator (rand...)

include <time>

include <stdio.h>

include <stdlib.h>

//...

time_t t;

time(&t);

/* Zufallsgenerator initialisieren */

srand((unsigned int)t);              

//... //Der Array bekommt zufällige Zahlen, auch doppelte

for (int i = 0; i < 20; i++)
{ S1.EigeneRoute[i] = (rand() % 20); }

    int i1, i2;
    for (int i1 = 0; i1 < 20; i1++)  //jetzt möchte ich prüfen, ob die Zahl bereits
    {                                            //vergeben ist und wenn ja, eine neue 
                                                         //Zufallszahl vergeben
        for (int i2 = 0; i2 < 20; i2++)
        {
            while (S1.EigeneRoute[i1] == S1.EigeneRoute[i2])
            {
                S1.EigeneRoute[i1] = (rand() % 20);
            }
        }
    }

ANMERKUNG: S1. ist eine Klasse. Ich glaube ich habe mich da etwas verlaufen, die letzte While-Schleife würde zwar einen neuen Zufallswert vergeben, aber dieser könnte wieder an einer anderen Stelle doppelt sein. Für einen intelligenteren Ansatz wäre ich euch sehr dankbar.

Hilfreichste Antwort - ausgezeichnet vom Fragesteller
von TeeTier, Community-Experte für programmieren, 9

Diese Frage kommt hier in letzter Zeit fast jede Woche. :)

Hier ist meine Antwort bzgl. C vom letzten mal:

https://www.gutefrage.net/frage/array-mit-zufallswerten-fuellen-jede-zahl-von1-9...

Allerdings solltest du meinen peinlichen Fehler und die Kommentare darunter beachten, und die Wertvertauschung auf jeden Fall mit einer Temporären Variablen erledigen, also so:

int tmp = arr[i];
arr[i] = arr[idx];
arr[idx] = tmp;

Davon abgesehen bezieht sich deine Frage auf C und C++, also beides.

Allerdings würde ich die Aufgabe in C und C++ VÖLLIG anders realisieren, denn die beiden Sprachen haben eigentlich nur ein gemeinsames "C" im Namen und sollten ansonsten als unterschiedliche Dinge betrachtet werden, auch wenn viele Leute behaupten, dass es kaum Unterschiede gäbe!

Hier ist eine Version in C++ ab Version 11 (!), die ziemlich exzessiven Gebrauch von der STL macht:

#include <algorithm> // copy
#include <chrono> // system_clock
#include <iostream> // cout
#include <iterator> // ostream_iterator
#include <numeric> // iota
#include <random> // default_random_engine

int main(void) {
using namespace std;

// beide Enden inklusive: [start,end]
constexpr int start = 1;
constexpr int end = 20;

// Anzahl Elemente im abgeschlossenen Intervall
constexpr int elems = end - start + 1;

// Vektor anlegen und fuellen
vector values(elems);
iota(values.begin(), values.end(), start);

// nur zu Debug-Zwecken
ostream_iterator out(cout, " ");
copy(values.begin(), values.end(), out);
cout << endl;

// aktuelle Zeit als Seed verwenden
auto now = chrono::system_clock::now();
auto seed = now.time_since_epoch().count();

// Vektor durcheinander wuerfeln
auto prng = default_random_engine(seed);
shuffle(values.begin(), values.end(), prng);

// nochmal Debug-Output
copy(values.begin(), values.end(), out);
cout << endl;
}

Das ganze ist recht effizient (bis auf die Initialisierung des Vektors, was mit einem back_inserter_iterator noch mal deutlich besser geht) und macht im Grunde genommen das Selbe wie die verlinkte C-Version, nur eben "auf C++ Art".

Die Ausgabe sieht z. B. so aus:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 
16 10 14 13 20 8 11 1 4 17 19 18 3 6 15 7 9 5 2 12

Oben noch frisch initialisiert und sortiert, unten hingegen durcheinander gewürfelt, wobei jede der gewünschten Zahlen zwangsläufig nur ein einziges mal vorkommt.

Wie gesagt, das ist die C++11 Version. Achte beim Übersetzen auf die entsprechenden Compiler-Flags!

Wenn du einen älteren Compiler verwendest, musst du neben einigen anderen Änderungen anstelle von shuffle() die Funktion random_shuffle() mit einem anderen Zufallszahlengenerator verwenden. (die beiden letzten Punkte gelten in neuen C++ Versionen als veraltet, und sollten nicht mehr verwendet werden)

Der Code sollte eigentlich selbsterklärend sein, aber wenn du etwas nicht verstehst, dann suche dir einfach die entsprechende Funktion in der Referenz deiner Wahl raus, z. B.:

http://www.cplusplus.com/

Viel Spaß! ;)

Antwort
von ceevee, 18

Nimm ein Array mit den Zahlen von 1-20 sortiert und misch das dann zufällig durch ("shuffle"). 

Ein vollständiger C++-Ansatz dafür wäre 

http://www.cplusplus.com/reference/algorithm/shuffle/

Antwort
von UncelBens, 18

Ich würde die Sache anders angehen.

Nim lieber die zahlen von 1-20 und dann verteile sie zufällig in die arrays und nicht anders herum.

Keine passende Antwort gefunden?

Fragen Sie die Community