Lotto-Programm [war: C++]



  • Hallo kann mir jemand helfen???? Ich muß für die Schule ein Lotto Programm schreiben. Ich habe 12 Lottofelder mit je 6 Zahlen, ich gebe 6 Zahlen ein wo jede einzelne Zahl mit den 12 mal 6 Zahlen verglichen wird. Ausgabe soll dann so sein das ich sehen kann wieviel richtige ich in jedem der 12 blöcke habe, ein wenig hab ich schon.

    #include<iostream>
    using namespace std;
    int main()
    {
    	setlocale(LC_ALL,"German");
    	// Lottoschein Zahlen
    	int LOTTO[12][6] = {{2,18,21,38,41,46},{3,11,17,25,31,39},{4,10,16,26,33,42},{2,11,25,37,39,41},{3,14,18,24,39,43},{7,11,26,31,40,43},{7,10,23,34,40,46},{3,16,20,26,32,48},{13,18,22,33,37,48},{2,15,19,25,37,46},{1,11,17,27,29,47},{3,7,17,33,44,48}};
    	int i=0,m=0,n=0;
    
    	//Eingabe der Gezogenen Zahlen
    	int Lottozahl[6];
    
    	bool b;
    	int s=0;
    
    	for (int i=0;i<6;i++)
    	{
    		do
    		{
    			cout <<i<< ". "<<"Zahl: ";
    			cin >> Lottozahl[i];
    			b=false;
    			for(int k=0;k<i;++k)
    			{
    				if(Lottozahl[k] == Lottozahl[i])
    				{
    					b=true;
    
    				}
    			}
    		}while((Lottozahl[i]<1) || (Lottozahl[i] > 49) || b);
    	}
    
    		int Zaehler=0, r=0,Z=0;
    		i=0;
    		m=0;
    		n=0;
    		while (m<12)
    		{
    			i=0;
    
    			while (n<6 && i<6)
    			{
    				Zaehler=0;
    				Z=0;
    				while (Zaehler<6)
    				{
    					if (Lottozahl[i] == LOTTO[m][n])
    					{
    						r=r+1;
    						cout << r << "Richtige"<<endl;
    
    					}
    					Zaehler++;
    					n++;
    					Z++;
    
    				}
    				if (Z==6)
    				{
    					i++;
    					n=0;
    				}
    			}
    
    			if (i==6)
    			{
    				m++;
    			}
    		}
    
    	return 0;
    }
    


  • Ohne den Wust jetzt genau studiert zu haben (was ich auch gar nicht tun werde) solltest du eine konkrete Frage stellen, wo genau du Probleme hast. Was dir mit Sicherheit weiterhelfen wird, ist, wenn du dein Problem in Teilprobleme zerlegst. Funktionen sind eine feine Sache, die man dafür sehr gut verwenden kann.

    So könntest du eine Funktion schreiben, welche zunächst nur prüft, ob eine bestimmte Zahl in einer Sequenz vorkommt.

    Eine weitere Funktion könnte nun die Übereinstimmungen der beiden Sequenzen zählen und dafür praktischerweise die erstgenannte Funktion verwenden.

    Das verleiht deinem Programm gleiche eine ganze Potenz mehr Übersichtlichkeit.

    Grüße ... Heiko



  • Das Programm läuft ja so weit aber als ausgabe bekomme ich die gesamt anzahl der richtig getippten Zahlen. Was ich aber brauch:

    1. ausgabe = richtige vom ersten Block
    2. ausgabe = richtige vom zweiten Block
    u.s.w.

    also ich brauche einen array mit 12 blöcken wo ich die menge der richtigen zahlen speichere so weit bin ich auch aber ich kann dies nicht umsetzten das es auch funktioniert.


  • Mod

    Bis auf einen grausigen Codestil sieht das schonmal gut aus. Dein Codestil verhindert leider, dass du die Fehler in der Zählschleife einfach findest - die ist nämlich VIEL zu kompliziert. Ich habe das mal verbessert (ungetestet, aber ich glaube es sollte richtig sein):

    while (m < 12)
     {
      i = 0;
      Z = 0;
      while (i < 6)
       {
        Zaehler = 0;
        while (Zaehler < 6)
         {
          if (Lottozahl[i] == LOTTO[m][Zaehler])
           {
            Z = Z + 1;
           }
          Zaehler++;
         }
        i++;
       }
      cout << Z << " Richtige in Feld " << m << endl;
      m++;
     }
    

    Den Stil habe ich jetzt nicht verbessert, das wäre zu viel Arbeit.



  • Danke funktioniert... Sorry wenn das ein wenig unübersichtlich ist aber c++ habe ich erst seid 3 Wochen.


  • Mod

    KaiR schrieb:

    Danke funktioniert... Sorry wenn das ein wenig unübersichtlich ist aber c++ habe ich erst seid 3 Wochen.

    Die Unübersichtlichkeit ist deine Schwäche, das solltest du dir möglichst sofort abgewöhnen:
    - Nimm for-Schleifen, wo sie angebracht sind. Du hast sehr oft unnötig while benutzt
    - Deklariere Variablen dort, wo sie das erste Mal benutzt werden. Insbesondere kann man auch innerhalb des for-Blocks Zählvariablen deklarieren: for(int i=0;i<6;++i)
    - Verwende NIEMALS Variablen mehrmals für einen unterschiedlichen Zweck
    - Und das Wichtigste: Wähle sprechende Variablennamen! Ein bisschen Schreibarbeit hat noch nie jemandem geschadet (wenn sie einem nicht ohnehin von einer Autovervollständigung abgenommen wird). Dafür kann man sehr viel einfacher Logikfehler wie hier finden. Hättest du deine Variablen nicht i,m,n,r,Z,b,s,Zaehler genannt, hätte man die Fehler Ruckzuck gesehen. Zaehler als Variablenname ist an sich noch ok, aber in diesem Programm gab es zu viele verschiedene Sachen die gezählt wurden (der Block, die Zahl im Block, die Zahl in der Tippliste, die Anzahl der Richtigen), als dass man sofort wüsste, was gemeint ist.
    - Ein paar Kommentare sind immer gut, wenn andere (wie hier) den COde lesen sollen oder man selber ein paar Wochen später nochmal einen Blick darauf werfen will.



  • KaiR schrieb:

    Ich habe 12 Lottofelder mit je 6 Zahlen, ich gebe 6 Zahlen ein wo jede einzelne Zahl mit den 12 mal 6 Zahlen verglichen wird. Ausgabe soll dann so sein das ich sehen kann wieviel richtige ich in jedem der 12 blöcke habe, ...

    ja - es ist Freitag; also Zeit für ungewöhnliche Lösungen!
    @KaiR frag' doch mal Deinen Lehrer, was er davon hält? 😉

    #include <algorithm> // set_intersection
    #include <cassert>
    #include <iomanip>
    #include <iostream>
    #include <iterator>
    #include <set>
    #include <sstream>
    #include <vector>
    
    // --   Einlesen eines Lottoscheins
    std::istream& operator>>( std::istream& in, std::vector< std::set< int > >& lottoschein )
    {
        std::vector< std::set< int > > ls;
        for( ; (in >> std::ws).good(); )    // Lesen bis EOF
        {
            std::set< int > tipp;
            for( int z; tipp.size() < 6 && in >> z; )
                if( !tipp.insert( z ).second )
                    in.setstate( std::ios_base::failbit );  // Fehler, da Zahl doppelt vorkommt
            if( in )
                ls.push_back( tipp );
        }
        if( in ) 
            swap( ls, lottoschein );
        return in;
    }
    
    // --   ein zählender Ausgabeiterator
    struct Counter : public std::iterator< std::output_iterator_tag, void, void, void, void >
    {
        Counter() : m_cnt(0) {}
        Counter& operator*() { return *this; }
        Counter& operator++() { ++m_cnt; return *this; }
        Counter operator++( int ) { Counter tmp(*this); ++m_cnt; return tmp; }
        template< typename T >
        Counter& operator=( const T& ) { return *this; }
        int Count() const { return m_cnt; }
    private:
        int m_cnt;
    };
    
    int main()
    {
        using namespace std;
        vector< set< int > > lottoschein;
        istringstream in(
            "2 18 21 38 41 46\n"
            "3 11 17 25 31 39\n"
            "4 10 16 26 33 42\n"
            "2 11 25 37 39 41\n"
            "3 14 18 24 39 43\n"
            "7 11 26 31 40 43\n"
            "7 10 23 34 40 46\n"
            "3 16 20 26 32 48\n"
            "13 18 22 33 37 48\n"
            "2 15 19 25 37 46\n"
            "1 11 17 27 29 47\n"
            "3 7 17 33 44 48\n"
            );
        in >> lottoschein;
        assert( in );
    
        set< int > tipp;
        cout << "geben Sie sechs unterschiedliche Zahlen ein:" << endl;
        for( int zahl, nr=1; tipp.size() < 6 && (cout << nr << ".Zahl ", cin >> zahl); )
            if( tipp.insert( zahl ).second ) ++nr;
    
        cout << endl;
        int feldNr = 1;
        for( vector< set< int > >::iterator iFeld = lottoschein.begin(); iFeld != lottoschein.end(); ++iFeld, ++feldNr )
            cout << setw(2) << feldNr << ".Feld: " 
                << set_intersection( iFeld->begin(), iFeld->end(), tipp.begin(), tipp.end(), Counter() ).Count() << " Richtige" << endl;
    
        return 0;
    }
    

    Für die Freunde von boost kann man den Counter noch schreiben als

    #include <boost/iterator/iterator_adaptor.hpp>
    
    struct Counter : public boost::iterator_adaptor< Counter, int, const int, boost::forward_traversal_tag, const Counter& >
    {
        Counter() : iterator_adaptor_(0) {}
        const Counter& dereference() const { return *this; }
        template< typename T >
        const Counter& operator=( const T& ) const { return *this; }
        int Count() const { return base(); }
    };
    

    Viel Spaß damit
    Werner



  • Werner Salomon schrieb:

    for( int zahl, nr=1; tipp.size() < 6 && (cout << nr << ".Zahl ", cin >> zahl); )
    

    Zu schlichte obfucation. Man hat gar nicht den Eindruck, als passiere das Chaos als Folge des Entwurfs, wie sonst immer.



  • volkard schrieb:

    Zu schlichte obfucation.

    Du meinst sicher obfuckation.

    Back to topic:
    Habt ihr schon Klassen/Strukturen behandelt? Das Ganze wird immens übersichtlicher, wenn man die Daten in eigene Datenstrukturen kapselt, z.B. :
    - Klasse Tipp: enthält alle getippten Zahl des Lottospielers
    - Klasse Lottoschein: enthält 1..N Tipps
    - Klasse Lottoziehung: enthält die gezogenen Lottozahlen

    Das Auswerten könnte vielleicht so aussehen:
    - Funktion auswerten( Lottoziehung, Lottoschein ) liefert die Anzahl aller getroffenen Zahlen je Tippfeld des Lottoscheins zurück.

    - Funktion auswerten( Lottoziehung, Tipp ) liefert die Anzahl der getroffenen Zahlen des Tipps zurück.

    Damit kann man schon etwas Struktur in den Code bekommen...



  • DocShoe schrieb:

    volkard schrieb:

    Zu schlichte obfucation.

    Du meinst sicher obfuckation.

    volkard meint sicher 'obfuscation' auf deutsch 'Benebelung, Verwirrung'.

    volkard schrieb:

    ... als passiere das Chaos als Folge des Entwurfs, wie sonst immer.

    Das find' ich gut! 😃

    Gruß
    Werner



  • Werner Salomon schrieb:

    volkard meint sicher 'obfuscation' auf deutsch 'Benebelung, Verwirrung'.

    to confuse the russians, nehme ich an? Mir war schon klar, was er meinte...


Anmelden zum Antworten