52 Karten Mischen und an Spieler austeilen



  • unskilled schrieb:

    void mischen(std::vector<karte::T>::iterator first, std::vector<karte::T>::iterator last)
    { //wuerde ich vermutlich eher mit nem template-parameter anstatt des iterators lösen, aber das nur am rande
      std::random_shuffle(first, end);
    }
    
    mischen(karten.begin(), karten.end());
    

    Warum nicht

    std::random_shuffle(karten.begin(), karten.end());
    

    ? Sparst du viel Code und blöden Kommentar. 🤡



  • evtl. möchte ich ja später das mischen verändern...

    template<typename RandomAccessIter>
    void mischen(RandomAccessIter first, RandomAccessIter end)
    {
      std::random_shuffle(first, end);
    }
    

    ist nicht wirklich länger, als direkt im quelltext ein random_shuffle zu haben.

    vermutlich wäre so gar ein

    template<typename RandomAccessContainer>
    void mischen(RandomAccessContainer& content)
    {
      std::random_shuffle(content.begin(), content.end());
    }
    

    in diesem zusammenhang besser

    vll möchte ich auch später so etwas machen:

    template<typename RandomAccessContainer>
    void mischen(RandomAccessContainer& content, int spiel_id)
    {
      std::srand(spiel_id);
      std::random_shuffle(content.begin(), content.end());
    }
    

    evtl. möchte ich auch später einen eigenen misch-algorithmus nutzen, weil ich feststelle, dass random_shuffle in meiner stl eine "unglückliche" implementierung für meine belange hat.

    kurz: weil ichs kann 😉
    oder eher, weil es keine nachteile hat - und nebenbei ist es auch für einen anfänger im quellcode besser zu verstehen.

    bb



  • unskilled schrieb:

    evtl. möchte ich ja später das mischen verändern...

    template<typename RandomAccessIter>
    void mischen(RandomAccessIter first, RandomAccessIter end)
    {
      std::random_shuffle(first, end);
    }
    

    ist nicht wirklich länger, als direkt im quelltext ein random_shuffle zu haben.

    Doch, und zwar 5 Zeilen länger (das sind +500%). Viel schlimmer ist aber, dass man den Code trennt für eine Indirektion, die nichts tut.

    unskilled schrieb:

    vermutlich wäre so gar ein

    template<typename RandomAccessContainer>
    void mischen(RandomAccessContainer& content)
    {
      std::random_shuffle(content.begin(), content.end());
    }
    

    in diesem zusammenhang besser

    Viel besser! Und wahrscheinlich ist es nicht mal nötig, das zu templatisieren. Oder wie viele verschiedene Deck-Container verwendest du gleichzeitig? Mit der Zeit wird es vielleicht auch in eine eigene Klasse kommen.

    void Deck::Mische();
    

    unskilled schrieb:

    oder eher, weil es keine nachteile hat

    Es hat, siehe oben 🙂

    unskilled schrieb:

    und nebenbei ist es auch für einen anfänger im quellcode besser zu verstehen.

    Denke ich nicht. Der wird sich eher wundern, warum man da eine zusätzliche Funktion aufruft, und wird einen funktionellen Unterschied zu einem direkten std::random_shuffle() -Aufruf suchen.

    unskilled schrieb:

    evtl. möchte ich ja später das mischen verändern...
    [...]
    vll möchte ich auch später so etwas machen:
    [...]
    evtl. möchte ich auch später [...]

    Du kannst nicht immer alles im Voraus machen. Oder es ist zumindest oft fragwürdig – sehr gut möglich, dass es sowieso anders kommt. Oder machst du auch alle Destruktoren präventiv virtuell, weil du die Klasse möglicherweise mal polymorph benutzen könntest? Oder alle Funktionen als Templates, weil du vielleicht verschiedene Typen benötigen könntest?

    Es ist natürlich was ganz Anderes, wenn du ernsthaft planst, ins Mischen neue Features einzubauen. 😉
    Und es geht auch immer ums Abwägen. Aber ich würde mich davor hüten, alles maximal generisch zu overengineeren, weil es vielleicht eines Tages nützlich sein könnte. Mach etwas nicht unnötig kompliziert, solange dir die einfache Variante das Gleiche bietet und auch in näherer Zukunft das Gleiche bieten wird.



  • Nexus schrieb:

    Oder machst du auch alle Destruktoren präventiv virtuell, weil du die Klasse möglicherweise mal polymorph benutzen könntest? Oder alle Funktionen als Templates, weil du vielleicht verschiedene Typen benötigen könntest?

    Sind aber beides Dinge, die man später nur an einer Stelle ändern muss...
    Das mischen braucht man nicht nur an einer Stelle - bei vielen Skat-Spielen wird neben dem mischen vorm Austeilen auch das nochmalige Mischen nach dem Reizen(zu dem die Karten meist automatisch geordnet wurden) angeboten - damit ein Gegner aus der Position der Karte, die man wählt keine Vorteile bekommen könnte.

    Außerdem ist es in meinen Augen eine Sache der Symmetrie:
    Das Ordnen bekommt logischerweise eine extra Fkt(weil spielabhängig) und damit sollte auch das Mischen eine Fkt. bekommen.

    Templates würde ich hier definitiv nutzen, alleine schon weil ich nicht weiß, ob ich dem Spieler einen vector oder ein tr1::array oder am besten ein Array auf dem Stack spendiere.
    Und auch hier sehe ich wieder keinen Nachteil zum typedef auf den Container oder diesen jedesmal auszuschreiben.

    Ist wohl geschmackssache - und ich wil jz den Thread auch nicht so lang vollspammen, bis wir ganz vom Thema abgekommen sind (huch, zu spät ;D)

    bb



  • Ich Danke euch für die Antworten werde mir mal die Links von Nexus vornehmen.

    @Nexus: Wie würde man die Befehle konkret verwenden?

    operator[] und erase()

    std::random_shuffle()



  • operator[] und erase() sind Memberfunktionen deines STL-Containers, z.B. std::vector . Der STL-Algorithmus std::random_shuffle() ist eine freie Funktion.

    Codebeispiele und Dokumentation findest du hier:

    Nexus schrieb:

    Als Nachschlagewerk zur Standardbibliothek kannst du www.cplusplus.com konsultieren.

    Aber damit du diese auch richtig verstehst, solltest du vielleicht zuerst die Artikel lesen (mindestens Teil 1 und 2). Zögere nicht, bei Problemen Fragen zu stellen!



  • Ich werd' mir mal die Artikel durchlesen und schauen, ob ich durchsteige.
    Habe lange nicht mehr in c++ programmiert. aber wird schon gehen.
    Ich komme sicher auf das Angebot zurück und frage 🙂



  • Hab auch mal mit std::random_shuffle nen Kartenspiel gemacht. Hab dabei gemerkt, dass sehr oft die selbe Reihenfolge vorkam bei 52 Karten. Also habe ich die Funktion eine zufällige oft zwischen 1-50 durchgeführt. Diese Zufallszahl kam vom Mersenee Twister. Damit habe ich gute Mischergebnisse erreicht.
    lg



  • L33TF4N schrieb:

    Hab auch mal mit std::random_shuffle nen Kartenspiel gemacht. Hab dabei gemerkt, dass sehr oft die selbe Reihenfolge vorkam bei 52 Karten. Also habe ich die Funktion eine zufällige oft zwischen 1-50 durchgeführt. Diese Zufallszahl kam vom Mersenee Twister. Damit habe ich gute Mischergebnisse erreicht.
    lg

    welche stl? die vom msvc?



  • unskilled schrieb:

    L33TF4N schrieb:

    Hab auch mal mit std::random_shuffle nen Kartenspiel gemacht. Hab dabei gemerkt, dass sehr oft die selbe Reihenfolge vorkam bei 52 Karten. Also habe ich die Funktion eine zufällige oft zwischen 1-50 durchgeführt. Diese Zufallszahl kam vom Mersenee Twister. Damit habe ich gute Mischergebnisse erreicht.
    lg

    welche stl? die vom msvc?

    Nutze Visual C++ 2008 Prof.



  • L33TF4N schrieb:

    Hab auch mal mit std::random_shuffle nen Kartenspiel gemacht. Hab dabei gemerkt, dass sehr oft die selbe Reihenfolge vorkam bei 52 Karten.

    Hast du mit srand() gesät?

    Ich habe bisher meist rand() benutzt, unter anderem in Spielen – es reicht eigentlich für sehr viele Alltagsdinge. Aber je nach Anwendung ist die Zufälligkeit vielleicht ungenügend.

    Übrigens kannst du als drittes Argument von std::random_shuffle einen Zufallsgenerator übergeben, damit du den Algorithmus nicht neu programmieren musst.



  • Hallo Sticky36,

    KARTEN KartenOBJ[51]; //initialisierung eines Arrays aus 52 Objekten der Klasse KARTEN

    Hast du vorher evtl. in BASIC programmiert?

    In C sowie in C++ wird immer die Anzahl der Elemente angegeben (nicht der oberste Index!), d.h. du müßtest dann auch

    KARTEN  KartenOBJ[52];         //initialisierung eines Arrays aus 52 Objekten der Klasse KARTEN
    

    schreiben.

    Setze dich jedoch besser mit std::vector<>, std::list<> etc. aus der STL auseinander.
    Auch dort wird dann immer die Anzahl angegeben:

    std::vector<KARTEN> Karten(52); // Hinweis: nur als lokale Variable so zu benutzen
    
    // als Member:
    // in Klassendeklaration
    std::vector<KARTEN> Karten;
    // in Konstruktor
    Spieler::Spieler()
     : Karten(52) // <- Initialisierungsliste
    {
    }
    


  • Nein. habe ich nicht. Iss einfach ein ein Denkfehler gewesen den ich bereits geändert habe. aber danke 🙂

    Ich bin gerda dabei mich schlau zu machen 😉


Anmelden zum Antworten