Lottozahlen ohne Wiederholung



  • Guten Tag,

    unsere Aufgabe ist, ein Programm zu erstellen, dass die Lottozahlen 6 aus 49 zufällig ausgibt.
    Das Problem ist nun, dass es Zahlen doppelt anzeigt...
    Wo liegt da der Fehler?

    Schon mal vielen lieben Dank im Voraus!!!

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    int main()
    {
        int array[6]={0};
        int i;
        int x=0;
    
        srand(time(NULL));              //Zufallszahlengenerator
    
        while(x<10)                     // Schleife zur Überprüfung, ob Zahlen doppelt vorkommen
        {
            for(i=0; i<6; i++)          // Schleife zur Bestimmung der 6 Felder
            {
                array[i]=rand()%49+1;
                if(array[0]==array[i+1])        // wenn eine Zahl doppelt vorkommt, soll sie hier neu generiert werden
                {
                    array[i+1]=rand()%49+1;
                }
            }
            printf("Lotto-Zahlen: %d  %d  %d  %d  %d  %d\n", array[0], array[1], array[2], array[3], array[4], array[5]);       // Ausgabe der 6 Lottozahlen
        x++;
        }
    
    }
    


  • Warum i+1 im Vergleich?
    Du überprüfst außerdem immer nur gegen das erste Element in deinem Array.



  • Das +1 habe ich weggenommen, dachte das Programm könnte damit die Felder abklappern...
    Der Code soll möglichst kurz sein, daher weiß ich nicht, wie ich den so gestalte.



  • @Luckyingmar
    Warum x<10?
    Was ist, wenn alle Zahlen nur einmal vorkommen?

    Also Zahl ziehen,
    nachschauen ob schon vorhanden, wenn ja -> nochmal ziehen.
    wenn nein -> weiter

    Das Ganze 6 mal.

    Beim Überprüfen, ob die Zahl schon vorhanden ist, wirst du eine Schleife brauchen.



  • x<10 dient zur Überprüfung, ob Zahlen doppelt vorkommen.
    Bevor ich jedes Mal das Programm neu starte, wirft er mir direkt 10 Durchgänge aus.
    Danke, ich werde es versuchen!



  • @Luckyingmar Erstmal so dass es funktioniert. Dann kann man noch darüber nachdenken, ob man das ordentlicher oder kürzer hinbekommt.

    Du musst deine gezogene Zahl immer gegen alle bereits abgelegten Zahlen überprüfen. D.H. du wirst eine zweite Schleife programmieren müssen, die alle breits gespeicherten Zahlen durch geht und überprüft ob die neue Zahl schon mal vorkommt.



  • Soweit war ich auch schon einmal, dass es funktioniert hat. Aber den Teil wusste ich nicht zu kürzen.



  • Bin schon die ganze Zeit am Ausprobieren...
    wie vergleicht man die bereits gezogene Zahl mit der neuen?



  • Mit einer Funktion. Der übergibst du das array und die Kandidatenzahl und sie liefert ob vorhanden oder nicht.
    Sowas nennt man auch Programmstrukturierung.



  • Hallo,

    typischer Algorithmus für Lottozahlen ziehen ist:

    
    Array a mit Zahlen 1 bis 49
    for i=0 bis 5
    {
      x = rand(49-i)
      result[i] = a[x];
      swap(a[x], a[49-i]); // gezogene Zahl aus dem rand-Bereich raus nehmen
    }
    
    


  • Leider komme ich immer noch nicht weiter... eure Denkanstöße haben mich schon ein kleines Stückchen weitergebracht, aber letztendlich bräuchte ich noch Hilfe.
    Die Erstellung einer Funktion gelingt mir nicht.



  • Kürzer wirst du es nicht hinkriegen.

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    enum {MYSIZE=6,MYASIZE=49};
    
    int enthaelt(const int *a,int z)
    {
    	int i;
    	for(i=0;i<MYSIZE;++i)
    	if(a[i]==z) return 1;
    	return 0;
    }
    
    int main()
    {
        int i, x, array[MYSIZE]={0};
    
        srand(time(0));              //Zufallszahlengenerator
    
        for(i=0; i<MYSIZE; i++)          // Schleife zur Bestimmung der 6 Felder
        {
        	while( enthaelt(array,x=rand()%MYASIZE+1) );
        	printf(" %d ",array[i]=x);
        }
    
        return 0;
    }
    

    https://ideone.com/PUziXy



  • Vielen Dank! Das ist genau so, wie ich es haben soll.
    Könntest du einmal kurz erklären was enum bedeutet?


  • Mod

    @Luckyingmar sagte in Lottozahlen ohne Wiederholung:

    Vielen Dank! Das ist genau so, wie ich es haben soll.

    Mag zwar sein, dass dein Lehrer das so akzeptiert, aber wenn du wirklich etwas lernen möchtest, dann arbeite lieber den Vorschlag von Jockelx durch. Warum hat Jockelx das wohl vorgeschlagen? Wo liegen die Vorteile? Wieso ist bei 6 aus 49 die andere Lösung von Wutz auch ganz gut?



  • Ich habe versucht, den Vorschlag von Wutz und Jockelx durchzuarbeiten. Allerdings bin ich nicht weit gekommen. Ich konnte mit den Denkanstößen nicht viel anfangen, ich bin auch noch ziemlich unerfahren in der Thematik.
    Ich versuche die Lösung von Wutz an meine Schreibweise anzupassen und diese zu verstehen!



  • Ich möchte nochmal SeppJs Frage zum Vergleich der beiden Lösungen erweitern, vielleicht hilft dir das auch weiter bei der Beantwortung:

    Was passiert, wenn ich statt 6 aus 49 ein neues Spiel entwerfe mit

    • 6 aus 49000
    • 48900 aus 49000


  • also ich würde es so machen:

    #define NUMNUMBERS 6
    #define NUMBERMIN 1
    #define NUMBERMAX 49
    
    int main()
    {
         //Deklarationen
         unsigned int numbers[NUMBNUMBERS];
         int i, j;
         //Schleife zur Bestimmung der Zufallszahlen
         for(i = 0; i < NUMNUMBERS; i++)
         {
              numbers[i] = NUMBERMIN + (rand() % (NUMBERMAX - NUMBERMIN + 1)); //Zufallszahl in [NUMBERMIN, NUMBERMAX] bestimmen
    
              for(j = 0; j < i; j++) //Schleife zum Abgleich aller bisherigen Zahlen mit der neuen
              {
                   if(numbers[j] == numbers[i]) //Bisherige Zahl ist vorhanden
                   {
                        break
                   }
               }
    
              if(numbers[i] == numbers[j])
              {
                        i--; //continue bewirkt Sprung ans Schleifenende, d.h. i wird inkrementiert. Um wieder an die gleiche Stelle im Array zu schreiben, wird i daher hier dekrementiert.
                        continue;
              }
         }
    }
    

  • Mod

    @Wade1234 : Das ist ja das gleiche wie von Wutz, aber in schlechter lesbar. Da muss man ja erst einmal gründlich nachdenken, was Zeile 25 bezwecken soll und ob das überhaupt legal ist. Der lange Kommentar, der zur Erklärung von vier Zeichen nötig ist, sollte ein Alarmzeichen sein.

    Du hast dich übrigens auch prompt gleich mehrmals verschrieben, es funktioniert so nicht. Und damit sind nicht nur Syntaxfehler gemeint. Selbst nach deren Korrektur ist dein Programm eine Endlosschleife.

    Als Vorbild daher denkbar schlecht geeignet, aber @Luckyingmar kann sich ja mal daran versuchen, die Fehler zu finden, verstehen, und zu beheben. Daher sage ich auch absichtlich nicht, wo die Fehler liegen. Die meisten sollten für den geübten Leser offensichtlich sein (und falls nicht-offensichtliche Fehler drin sind, kenne ich sie schließlich selber nicht 😃 )



  • @SeppJ ich habs nochmal korrigiert und dieses mal auch getestet.

    #include <stdlib.h>
    
    #define NUMNUMBERS 6
    #define NUMBERMIN 1
    #define NUMBERMAX 49
    
    int main()
    {
         unsigned int numbers[NUMNUMBERS];
         int i, j;
    
         for(i = 0; i < NUMNUMBERS; i++)
         {
              numbers[i] = NUMBERMIN + rand() % (NUMBERMAX - NUMBERMIN + 1);
    
              for(j = 0; j < i; j++)
              {
                   if(numbers[j] == numbers[i])
                   {
                        i--;
                        continue;;
                   }
               }
         }
    
         return 0;
    }
    

    ich glaube, dass ich es vorher auch so (mit den fehlern) geschrieben hatte, aber irgendwie hatte ich dann plötzlich einen einfall oder so. das von wutz halte ich eigentlich für sehr unsauber, also eine zuweisung in printf geht z.b. gar nicht.


  • Mod

    So ist das auch schon wesentlich verständlicher. Aber die Zeilen 20 und 21 finde ich immer noch fies. Die logische Anforderung "ziehe so lange eine neue Zahl, bis diese nicht in der Liste der schon gezogenen Zahlen ist" lässt sich nahezu 1:1 in richtig feines C hin und zurück übersetzen. Deine Lösung hingegen ergibt sich nicht als direkte Übersetzung der logischen Beschreibung, und die Rückübersetzung ist erst recht verwirrend.