Programm stürzt ab



  • Hallo
    Ich fange gerade an, ein konsolenbasiertes Romme-Spiel zu schreiben.
    Als erstes habe ich mich um die Karten gekümmert, doch schon beim Mischen stürzt das Programm ab. Hier der Quelltext:

    #include <iostream>
    #include <cstdlib> 
    #include <ctime>
    
    using namespace std;
    
    struct Card
    {
    	short int value;
    	char name;
    	char color;
    };
    
    struct Card deck[110];
    
    int main (void)
    {
    	srand(time(0));
    
    	for(int i = 0; i <26; i++)
    	{
    		deck[i].color = 'h';
    	}
    
    	for(int i = 26; i <52; i++)
    	{
    		deck[i].color = 'c';
    	}
    
    	for(int i = 52; i <78; i++)
    	{
    		deck[i].color = 'k';
    	}
    
    	for(int i = 78; i <104; i++)
    	{
    		deck[i].color = 'p';
    	}
    
    	deck[0].value = 2; //Karte Herz 2
    	deck[1].value = 3; //Karte Herz 3
    	deck[2].value = 4; //Karte Herz 4
    	deck[3].value = 5; //Karte Herz 5
    	deck[4].value = 6; //Karte Herz 6
    	deck[5].value = 7; //Karte Herz 7
    	deck[6].value = 8; //Karte Herz 8
    	deck[7].value = 9; //Karte Herz 9
    	deck[8].value = 10; //Karte Herz 10
    	deck[9].value = 10; //Karte Herz Bube
    	deck[10].value = 10; //Karte Herz Dame
    	deck[11].value = 10; //Karte Herz König
    	deck[12].value = 11; //Karte Herz Ass
    	deck[13].value = 2; //Karte Herz 2
    	deck[14].value = 3; //Karte Herz 3
    	deck[15].value = 4; //Karte Herz 4
    	deck[16].value = 5; //Karte Herz 5
    	deck[17].value = 6; //Karte Herz 6
    	deck[18].value = 7; //Karte Herz 7
    	deck[19].value = 8; //Karte Herz 8
    	deck[20].value = 9; //Karte Herz 9
    	deck[21].value = 10; //Karte Herz 10
    	deck[22].value = 10; //Karte Herz Bube 
    	deck[23].value = 10; //Karte Herz Dame
    	deck[24].value = 10; //Karte Herz König
    	deck[25].value = 11; //Karte Herz Ass
    	deck[26].value = 2; //Karte Caro 2
    	deck[27].value = 3; //Karte Caro 3 
    	deck[28].value = 4; //Karte Caro 4
    	deck[29].value = 5; //Karte Caro 5
    	deck[30].value = 6; //Karte Caro 6
    	deck[31].value = 7; //Karte Caro 7
    	deck[32].value = 8; //Karte Caro 8
    	deck[33].value = 9; //Karte Caro 9
    	deck[34].value = 10; //Karte Caro 10
    	deck[35].value = 10; //Karte Caro Bube
    	deck[36].value = 10; //Karte Caro Dame
    	deck[37].value = 10; //Karte Caro König
    	deck[38].value = 11; //Karte Caro Ass
    	deck[39].value = 2; //Karte Caro 2
    	deck[40].value = 3; //Karte Caro 3
    	deck[41].value = 4; //Karte Caro 4
    	deck[42].value = 5; //Karte Caro 5
    	deck[43].value = 6; //Karte Caro 6
    	deck[44].value = 7; //Karte Caro 7
    	deck[45].value = 8; //Karte Caro 8
    	deck[46].value = 9; //Karte Caro 9
    	deck[47].value = 10; //Karte Caro 10
    	deck[48].value = 10; //Karte Caro Bube
    	deck[49].value = 10; //Karte Caro Dame
    	deck[50].value = 10; //Karte Caro König
    	deck[51].value = 11; //Karte Caro Ass
    	deck[52].value = 2; //Karte Kreuz 2
    	deck[53].value = 3; //Karte Kreuz 3
    	deck[54].value = 4; //Karte Kreuz 4
    	deck[55].value = 5; //Karte Kreuz 5
    	deck[56].value = 6; //Karte Kreuz 6
    	deck[57].value = 7; //Karte Kreuz 7
    	deck[58].value = 8; //Karte Kreuz 8
    	deck[59].value = 9; //Karte Kreuz 9
    	deck[60].value = 10; //Karte Kreuz 10
    	deck[61].value = 10; //Karte Kreuz Bube
    	deck[62].value = 10; //Karte Kreuz Dame
    	deck[63].value = 10; //Karte Kreuz König
    	deck[64].value = 11; //Karte Kreuz Ass
    	deck[65].value = 2; //Karte Kreuz 2
    	deck[66].value = 3; //Karte Kreuz 3
    	deck[67].value = 4; //Karte Kreuz 4
    	deck[68].value = 5; //Karte Kreuz 5
    	deck[69].value = 6; //Karte Kreuz 6
    	deck[70].value = 7; //Karte Kreuz 7
    	deck[71].value = 8; //Karte Kreuz 8
    	deck[72].value = 9; //Karte Kreuz 9
    	deck[73].value = 10; //Karte Kreuz 10
    	deck[74].value = 10; //Karte Kreuz Bube
    	deck[75].value = 10; //Karte Kreuz Dame
    	deck[76].value = 10; //Karte Kreuz König
    	deck[77].value = 11; //Karte Kreuz Ass
    	deck[78].value = 2; //Karte Pik 2
    	deck[79].value = 3; //Karte Pik 3
    	deck[80].value = 4; //Karte Pik 4
    	deck[81].value = 5; //Karte Pik 5
    	deck[82].value = 6; //Karte Pik 6
    	deck[83].value = 7; //Karte Pik 7
    	deck[84].value = 8; //Karte Pik 8
    	deck[85].value = 9; //Karte Pik 9
    	deck[86].value = 10; //Karte Pik 10
    	deck[87].value = 10; //Karte Pik Bube
    	deck[88].value = 10; //Karte Pik Dame
    	deck[89].value = 10; //Karte Pik König
    	deck[90].value = 11; //Karte Pik Ass
    	deck[91].value = 2; //Karte Pik 2
    	deck[92].value = 3; //Karte Pik 3
    	deck[93].value = 4; //Karte Pik 4
    	deck[94].value = 5; //Karte Pik 5
    	deck[95].value = 6; //Karte Pik 6
    	deck[96].value = 7; //Karte Pik 7
    	deck[97].value = 8; //Karte Pik 8
    	deck[98].value = 9; //Karte Pik 9
    	deck[99].value = 10; //Karte Pik 10
    	deck[100].value = 10; //Karte Pik Bube
    	deck[101].value = 10; //Karte Pik Dame
    	deck[102].value = 10; //Karte Pik König
    	deck[103].value = 11; //Karte Pik Ass
    	deck[104].value = 20; //Joker
    	deck[105].value = 20; //Joker
    	deck[106].value = 20; //Joker
    	deck[107].value = 20; //Joker
    	deck[108].value = 20; //Joker
    	deck[109].value = 20; //Joker
    	deck[0].name = '2';
    	deck[1].name = '3';
    	deck[2].name = '4';
    	deck[3].name = '5';
    	deck[4].name = '6';
    	deck[5].name = '7';
    	deck[6].name = '8';
    	deck[7].name = '9';
    	deck[8].name = '0';
    	deck[9].name = 'B';
    	deck[10].name = 'D';
    	deck[11].name = 'K';
    	deck[12].name = 'A';
    	deck[13].name = '2';
    	deck[14].name = '3';
    	deck[15].name = '4';
    	deck[16].name = '5';
    	deck[17].name = '6';
    	deck[18].name = '7';
    	deck[19].name = '8';
    	deck[20].name = '9';
    	deck[21].name = '0';
    	deck[22].name = 'B';
    	deck[23].name = 'D';
    	deck[24].name = 'K';
    	deck[25].name = 'A';
    	deck[26].name = '2';
    	deck[27].name = '3';
    	deck[28].name = '4';
    	deck[29].name = '5';
    	deck[30].name = '6';
    	deck[31].name = '7';
    	deck[32].name = '8';
    	deck[33].name = '9';
    	deck[34].name = '0';
    	deck[35].name = 'B';
    	deck[36].name = 'D';
    	deck[37].name = 'K';
    	deck[38].name = 'A';
    	deck[39].name = '2';
    	deck[40].name = '3';
    	deck[41].name = '4';
    	deck[42].name = '5';
    	deck[43].name = '6';
    	deck[44].name = '7';
    	deck[45].name = '8';
    	deck[46].name = '9';
    	deck[47].name = '0';
    	deck[48].name = 'B';
    	deck[49].name = 'D';
    	deck[50].name = 'K';
    	deck[51].name = 'A';
    	deck[52].name = '2';
    	deck[53].name = '3';
    	deck[54].name = '4';
    	deck[55].name = '5';
    	deck[56].name = '6';
    	deck[57].name = '7';
    	deck[58].name = '8';
    	deck[59].name = '9';
    	deck[60].name = '0';
    	deck[61].name = 'B';
    	deck[62].name = 'D';
    	deck[63].name = 'K';
    	deck[64].name = 'A';
    	deck[65].name = '2';
    	deck[66].name = '3';
    	deck[67].name = '4';
    	deck[68].name = '5';
    	deck[69].name = '6';
    	deck[70].name = '7';
    	deck[71].name = '8';
    	deck[72].name = '9';
    	deck[73].name = '0';
    	deck[74].name = 'B';
    	deck[75].name = 'D';
    	deck[76].name = 'K';
    	deck[77].name = 'A';
    	deck[78].name = '2';
    	deck[79].name = '3';
    	deck[80].name = '4';
    	deck[81].name = '5';
    	deck[82].name = '6';
    	deck[83].name = '7';
    	deck[84].name = '8';
    	deck[85].name = '9';
    	deck[86].name = '0';
    	deck[87].name = 'B';
    	deck[88].name = 'D';
    	deck[89].name = 'K';
    	deck[90].name = 'A';
    	deck[91].name = '2';
    	deck[92].name = '3';
    	deck[93].name = '4';
    	deck[94].name = '5';
    	deck[95].name = '6';
    	deck[96].name = '7';
    	deck[97].name = '8';
    	deck[98].name = '9';
    	deck[99].name = '0';
    	deck[100].name = 'B';
    	deck[101].name = 'D';
    	deck[102].name = 'K';
    	deck[103].name = 'A';
    	deck[104].name = 'J';
    	deck[105].name = 'J';
    	deck[106].name = 'J';
    	deck[107].name = 'J';
    	deck[108].name = 'J';
    	deck[109].name = 'J';
    
    	for(int i = 0; i<110; i++)
    	{
    		int new_pos = rand();
    
    		short int temp_value = deck[i].value;
    		char temp_color = deck[i].color;
    		char temp_name = deck[i].name;
    
    		deck[i] = deck[new_pos];
    
    		deck[new_pos].value = temp_value;
    		deck[new_pos].color = temp_color;
    		deck[new_pos].name = temp_name;
    	}
    
    	for (int i=0; i<110; i++)
    	{
            cout << deck[i].color << " ";
    
            cout << endl;
        }
    
    	return 0;
    }
    

    Am Ende werden die Farben der Karten hintereinander ausgegeben, als Überprüfung ob das Mischen erfolgreich war (natürlich nur in der Entwicklungsphase, im fertigen Programm verschwindet dann diese Ausgabe)
    Also..wäre euch sehr dankbar, wenn sich eine Lösung finden ließe.

    btw: Wie ihr sicher seht, sind in dem Script 220 Zeilen mit Zuweisungen an das Karten-Array. Mir ist keine Idee gekommen, wie man diese ganzen Zeilen durch Schleifen ersetzen könnte, da beim Wert z.B. manche Werte doppelt vorkommen oder beim Name Zahlen u. Buchstaben gemischt sind.



  • Hier ein Tipp für die Schleifen:

    1. Mache zuerst die ganzen Karten-Namen-Zuweisungen mit einer Schleife (Hinweis: Modulo-Operator "%" - da die Reihenfolge der Karten-Namen immer die selbe ist).
    2. dann berechne die Karten-Werte (Schleife in der der Name überprüft wird)

    Das ganze dient dann der Übersichtlichkeit und der Fehlerunanfälligkeit.



  • binäri schrieb:

    int new_pos = rand();

    Nach diesem Aufruf hat new_pos einen Wert zwischen 0 und RAND_MAX. Du willst einen Wert zwischen 0 und 109:

    int new_pos = rand() % 110;
    

    So hast du zwar keine ideale Verteilung der Zufallszahlen, aber das ist wohl vorerst vernachlässigbar.


  • Mod

    rand() weiß nicht, dass dein Kartenspiel 110 Karten hat. Es liefert Werte zwischen 0 und RAN_MAX (eine sehr, sehr große Zahl). Da liegt die Ursache deines Absturzes. Anonsten hast du ja selbst schon treffend erkannt, dass du dein Design dringend überdenken solltest.

    edit: Oh, da habe ich viel zu lange gebraucht beim Tippen....



  • #include <algorithm> // std::swap
    /* ... */
    for(int i = 0; i != 110; ++i) {
        int first_index = rand() % 110; // ergibt Zahl zwischen 0 und 109
        int second_index;
        do {
            second_index = rand() % 110;
        }while(first_index == second_index); // bis beide Indizes(?) unterschiedliche Werte haben
        std::swap(deck[first_index], deck[second_index]); // beide Arrayelemente tauschen
    }
    

    EDIT: Hmpf, ich brauch aber auch ewig zum tippen 😞



  • Danke, so kommt es zumindest nicht mehr zum Absturz.
    @Mizar: Auch dein Script funktioniert. Es ist halt bloß ein anderer Ansatz - kannst du einem ANfänger wie mir sagen, ob diese Variante Vorteile gegenüber der meinigen (mit der Berichtigung von SeppJ) hat?
    Bei beiden Varianten gibt es aber anscheindend Fälle, an denen irgendetwas schief geht. Das äußert sich dann darin, dass nichts, bzw. ein Leerzeichen (erkennt man auf der Konsole so schlecht) ausgegeben wird. (6 Fälle beim letzten Test)
    Woran könnte denn das liegen?



  • binäri schrieb:

    Bei beiden Varianten gibt es aber anscheindend Fälle, an denen irgendetwas schief geht. Das äußert sich dann darin, dass nichts, bzw. ein Leerzeichen (erkennt man auf der Konsole so schlecht) ausgegeben wird. (6 Fälle beim letzten Test)
    Woran könnte denn das liegen?

    Dein Array:

    struct Card deck[110];
    

    hat 110 Elemente (von 0 bis 109).
    Bei den folgenden for-Schleifen, weist du den Elementen 0 bis 103 entsprechende Werte für die Farbe zu:

    for(int i = 0; i <26; i++)
        {
            deck[i].color = 'h';
        }
    
        for(int i = 26; i <52; i++)
        {
            deck[i].color = 'c';
        }
    
        for(int i = 52; i <78; i++)
        {
            deck[i].color = 'k';
        }
    
        for(int i = 78; i <104; i++)
        {
            deck[i].color = 'p';
        }
    

    109 minus 103 ergibt genau eine Differenz von 6, was die 6 "Leerzeichen" (oder was auch immer) erklärt, die dir die folgende for-Schleife ausgibt:

    for (int i=0; i<110; i++)
        {
            cout << deck[i].color << " ";
    
            cout << endl;
        }
    

    Den Elementen 104 bis 109 hast du einfach keine Farbe zugewiesen.

    binäri schrieb:

    @Mizar: Auch dein Script funktioniert. Es ist halt bloß ein anderer Ansatz - kannst du einem ANfänger wie mir sagen, ob diese Variante Vorteile gegenüber der meinigen (mit der Berichtigung von SeppJ) hat?

    Falls du damit das std::swap meintest: Dies ersetzt einfach deine folgenden Codezeilen:

    short int temp_value = deck[i].value;
            char temp_color = deck[i].color;
            char temp_name = deck[i].name;
    
            deck[i] = deck[new_pos];
    
            deck[new_pos].value = temp_value;
            deck[new_pos].color = temp_color;
            deck[new_pos].name = temp_name;
    


  • Ach stimmt, bei den for-Schleifen habe ich die Joker nicht berücksichtigt.
    Ja genau, ich meinte std::swap. Also bloß kürzer - ok.


Anmelden zum Antworten