Risolto Funzione che si ferma a metà esecuzione.

enk17

Utente Bronze
23 Ottobre 2021
69
17
8
37
Salve sto svillupando una funzione di blackjack però arrivato alla riga 54 (ovvero dove si trova il while) si ferma senza restituire errori.
C++:
void blackjack()
{
    string carte[4]={"Cuori","Picche","Fiori","Quadri"};
    string valori[3]={"Regina","Re","Fante"};
    bool selezione=true;
    int ris_carte_simb,ris_carte,scelta,valore,ris_carte_player,valore_ris,ris_carte_mano,scommessa,carte_player=0,carte_mano=0,vincita;
    cout<<"Benvuto/a in blackjack"<<endl;
    cout<<"quanto vuoi puntare? ";
    cin>>scommessa;
    ris_carte_simb = rand() % 4;
    ris_carte_player=rand() % 10+1;
    if(ris_carte_player==10)
    {
        valore=rand() % 4;
        if(valore== 1 || valore== 2 || valore== 3)
        {
            valore_ris=valore;
        }   
        
    }
    carte_player++;
    
    //cout<<carte[ris_carte_simb];,
    cout<<"la tua mano e' "<< ris_carte_player <<" di "<< carte[ris_carte_simb] <<valori[valore_ris];
    while(selezione==true)
    {
        cout<<"1. prendi una carte. 2.stai. 3.raddoppia";
        switch(selezione)
        {
            case 1:ris_carte=ris_carte+rand() % 10+1;
            carte_player++;
            cout<<"la tua mano e' "<< ris_carte_player <<" di "<< carte[ris_carte_simb] <<valori[valore_ris];
            break;
            case 2: selezione=false;
            break;
            case 3: if(carte_player>=2)
            {
                ris_carte=ris_carte+rand() % 10+1;
                scommessa=scommessa*2;
                carte_player++;
                cout<<"la tua mano e' "<< ris_carte_player <<" di "<< carte[ris_carte_simb] <<valori[valore_ris];
                system("pause");
                break;
            }
            default: cout<<"Non ho capito cosa vuoi fare, riprova!";
        }
    }
    while(carte_player>carte_mano)
    {
        carte_mano++;
        ris_carte_mano=rand() % 10+1;
        
    }       
    if(ris_carte_player>21)
    {
        cout<<"mi dispiace, hai perso! ";
    }
    if(ris_carte_manor>21)
    {
        cout<<"La mano ha fatto più di 21,hai vinto!";
    }
    if(ris_carte_player>ris_carte_mano)
    {
        cout<<"hai vinto!";
    }
    if(ris_carte_player<ris_carte_mano)
    {
        cout<<"hai perso!";
    }
}
 
Ultima modifica:
Credo sia dovuto al fatto che se non peschi il 10 valori_ris resta non inizializzato e tu lo usi come indice per valori. Se posso darti un consiglio, definisci le variabili quando ti servono e non tutte all'inizio della funzione. Comunque il dieci (inteso come carta) non lo puoi mai estrarre e fante, regina e re hanno una probabilità di estrazione più bassa rispetto alle altre carte. Nello switch credo che devi scrivere scelta invece di selezione. Io procederei in questo modo:
C++:
void blackjack() {
    const string semi[4] = {"Cuori", "Picche", "Fiori", "Quadri"};
    const string valori[13] = {"Asso", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Fante", "Regina", "Re"};

    cout << "Benvuto/a in blackjack" << endl;
    cout << "quanto vuoi puntare? ";
    int scommessa;
    cin >> scommessa;

    int carte = 1;
    int seme = rand() % 4;
    int valore = rand() % 13;
    cout << "la tua mano è "<< valori[valore] << " di "<< semi[seme] << endl;

    bool gameover = false;
    while (!gameover) {
        cout << "1) prendi una carta. 2) stai. 3) raddoppia.";
        int scelta;
        cin >> scelta;

        switch(scelta) {
           // ...
        }

        // ...
    }
    // ...
}

Ancora meglio se crei più di una funzione e magari crei almeno una struttura.
 
Credo sia dovuto al fatto che se non peschi il 10 valori_ris resta non inizializzato e tu lo usi come indice per valori. Se posso darti un consiglio, definisci le variabili quando ti servono e non tutte all'inizio della funzione. Comunque il dieci (inteso come carta) non lo puoi mai estrarre e fante, regina e re hanno una probabilità di estrazione più bassa rispetto alle altre carte. Nello switch credo che devi scrivere scelta invece di selezione. Io procederei in questo modo:
C++:
void blackjack() {
    const string semi[4] = {"Cuori", "Picche", "Fiori", "Quadri"};
    const string valori[13] = {"Asso", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Fante", "Regina", "Re"};

    cout << "Benvuto/a in blackjack" << endl;
    cout << "quanto vuoi puntare? ";
    int scommessa;
    cin >> scommessa;

    int carte = 1;
    int seme = rand() % 4;
    int valore = rand() % 13;
    cout << "la tua mano è "<< valori[valore] << " di "<< semi[seme] << endl;

    bool gameover = false;
    while (!gameover) {
        cout << "1) prendi una carta. 2) stai. 3) raddoppia.";
        int scelta;
        cin >> scelta;

        switch(scelta) {
           // ...
        }

        // ...
    }
    // ...
}

Ancora meglio se crei più di una funzione e magari crei almeno una struttura.
ok ora entra nello switch ma non esce, nel senso quando metto 2 per uscire rimane inchiodato
C++:
void blackjack()
{
    string semi[4] = {"Cuori", "Picche", "Fiori", "Quadri"};
    string valori[13] = {"Asso", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Fante", "Regina", "Re"};
    bool gameover = false;
    int ris_carte_simb,ris_carte,scelta,valore,ris_carte_player,seme,ris_carte_mano,scommessa,carte_player=0,carte_mano=0,vincita;
    cout<<"Benvuto/a in blackjack"<<endl;
    cout<<"quanto vuoi puntare? ";
    cin>>scommessa;
    
    
    seme = rand() % 4;
    valore = rand() % 13;
    carte_player=1;
    
    //cout<<carte[ris_carte_simb];,
     cout << "la tua mano è "<< valori[valore] << " di "<< semi[seme] << endl;
    while(!gameover)
    {
        cout<<"1. prendi una carte. 2.stai. 3.raddoppia";
        cin>>scelta;
        switch(scelta)
        {
            case 1:ris_carte_player= ris_carte_player+valore;
            carte_player++;
            cout << "la tua mano è "<< ris_carte_player << " di "<< semi[seme] << endl;
            cout<<carte_player;
            break;
            case 2: gameover=true;
            break;
            case 3: if(carte_player>=2)
            {
                ris_carte_player=ris_carte_player+valore;;
                scommessa=scommessa*2;
                carte_player++;
                cout << "la tua mano è "<< ris_carte_player << " di "<< semi[seme] << endl;
            }
            break;
            default: cout<<"Non ho capito cosa vuoi fare, riprova!";
        }
    }
    while(carte_player>carte_mano)
    {
        carte_mano=1;
        ris_carte_mano= ris_carte_mano + valore;
    }       
    if(ris_carte_player>21)
    {
        cout<<"mi dispiace, hai perso! ";
    }
    if(ris_carte_player>21)
    {
        cout<<"La mano ha fatto più di 21,hai vinto!";
    }
    if(ris_carte_player>ris_carte_mano)
    {
        cout<<"hai vinto!";
    }
    if(ris_carte_player<ris_carte_mano)
    {
        cout<<"hai perso!";
    }
}
 
Esce dallo switch (esce dal primo while) e rimane inchiodato nel while successivo.
C++:
while (carte_player>carte_mano) {
    carte_mano=1;
    ris_carte_mano= ris_carte_mano + valore;
}
Se carte_player è maggiore di 1 ed entri nel while, non ne esci più. Ragionaci con calma.
 
Credo sia dovuto al fatto che se non peschi il 10 valori_ris resta non inizializzato e tu lo usi come indice per valori. Se posso darti un consiglio, definisci le variabili quando ti servono e non tutte all'inizio della funzione. Comunque il dieci (inteso come carta) non lo puoi mai estrarre e fante, regina e re hanno una probabilità di estrazione più bassa rispetto alle altre carte. Nello switch credo che devi scrivere scelta invece di selezione. Io procederei in questo modo:
C++:
void blackjack() {
    const string semi[4] = {"Cuori", "Picche", "Fiori", "Quadri"};
    const string valori[13] = {"Asso", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Fante", "Regina", "Re"};

    cout << "Benvuto/a in blackjack" << endl;
    cout << "quanto vuoi puntare? ";
    int scommessa;
    cin >> scommessa;

    int carte = 1;
    int seme = rand() % 4;
    int valore = rand() % 13;
    cout << "la tua mano è "<< valori[valore] << " di "<< semi[seme] << endl;

    bool gameover = false;
    while (!gameover) {
        cout << "1) prendi una carta. 2) stai. 3) raddoppia.";
        int scelta;
        cin >> scelta;

        switch(scelta) {
           // ...
        }

        // ...
    }
    // ...
}

Ancora meglio se crei più di una funzione e magari crei almeno una struttura.
Unica cosetta che sistemerei...quando randomizzi il valore del seme e del valore non devi sconfinare con gli array. Si può fare così:
C++:
int seme = rand() % 3;
int valore = rand() % 12
 
Esce dallo switch (esce dal primo while) e rimane inchiodato nel while successivo.
C++:
while (carte_player>carte_mano) {
    carte_mano=1;
    ris_carte_mano= ris_carte_mano + valore;
}
Se carte_player è maggiore di 1 ed entri nel while, non ne esci più. Ragionaci con calma.
ho risolto sostituendo con un for
C++:
for(int n=carte_player ; n>carte_mano ; carte_mano++)
    {
        ris_carte_mano= ris_carte_mano + valore;
    }
Unica cosetta che sistemerei...quando randomizzi il valore del seme e del valore non devi sconfinare con gli array. Si può fare così:
C++:
int seme = rand() % 3;
int valore = rand() % 12
Nei test fatti da me non mi ha riportato bug riguardo alla generazione, però grazie di averlo fatto notare!
 
Unica cosetta che sistemerei...quando randomizzi il valore del seme e del valore non devi sconfinare con gli array. Si può fare così:
C++:
int seme = rand() % 3;
int valore = rand() % 12
Era giusto prima: 4 e 13 perché ci sono 4 semi (da 0 a 3) e 13 carte (da 0 a 12).
Quando fai x % n; ti ritrovi con un numero intero compreso tra 0 ed n-1.

Poi quando calcola i punteggi deve stare attento, ma è già una cosa un po' più elaborata perché ad esempio l'asso vale o 1 o 11.
 
Poi quando calcola i punteggi deve stare attento, ma è già una cosa un po' più elaborata perché ad esempio l'asso vale o 1 o 11.
Per questo ho risolto così,dici che vabene?
C++:
if(valori[valore]=="Fante" || valori[valore]=="Re" || valori[valore]=="Regina" )
    {
        ris_carte_player+=10;
    }
    else if(valori[valore]=="Asso")
    {
        cout<<"Quanto vuoi far valere l'asso? 1 o 11? ";
        cin>>asso;
        ris_carte_player=+asso;
    }
 
Era giusto prima: 4 e 13 perché ci sono 4 semi (da 0 a 3) e 13 carte (da 0 a 12).
Quando fai x % n; ti ritrovi con un numero intero compreso tra 0 ed n-1.

Poi quando calcola i punteggi deve stare attento, ma è già una cosa un po' più elaborata perché ad esempio l'asso vale o 1 o 11.
Pardon, errore mio, avevo letto male ;)
 
Avevo implementato tempo fa il blackjack, l'ho modificato per seguire la tua struttura in modo che puoi vedere le cose che ti mancano: il calcolo del valore degli assi (se 1 o 11), che le carte siano uniche (non posso avere l'asso di cuori se c'è l'ha il banco...), le regole per raddoppiare (split) e altro.

blackjack.png


C++:
int carte_usate[52] = {0};

int carta()
{
    int carta;
    do
    {
        carta = rand() % 52;

    } while (carte_usate[carta] != 0);

    carte_usate[carta] = 1;
    return carta;
}

string seme(int carta)
{
    const char* semi[] = { "Cuori", "Quadri", "Fiori", "Picche" };
    int seme = (carta / 13);
    return string(semi[seme]);
}

string nome_carta(int carta)
{
    const char* map[] = { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" };
    int v = (carta % 13);
    return string(map[carta % 13]) + " di " + seme(carta);
}

bool can_split(const vector<int>& mano)
{
    int carta1 = mano.at(0);
    int carta2 = mano.at(1);
    carta1 = min(carta1 % 13, 10);
    carta2 = min(carta2 % 13, 10);
    return (carta1 == carta2);
}

int punteggio(const vector<int> &mano)
{
    int totale = 0, assi = 0;
    for (int c : mano)
    {
        int i = min((c % 13) + 1, 10);
        if (i == 1)
            assi++;
        else
            totale += i;
    }
    if (assi > 0)
    {
        if (assi > 1)
            totale += assi - 1;

        totale += (totale + 11 > 21) ? 1 : 11;
    }
    return totale;
}

bool busted(const vector<int>& mano)
{
    int score = punteggio(mano);
    bool busted = (score > 21);
    if (busted)
        cout << "Hai sballato! " << score << endl;

    return busted;
}

void win(int amount)
{
    cout << "Hai vinto " << amount << endl;
}

void lose(int amount)
{
    cout << "Hai perso " << amount << endl;
}

void visualizza(const vector<int> &mano)
{
    for (int c : mano)
        cout << nome_carta(c) << endl;

    cout << "Totale: " << punteggio(mano) << endl;
}

void blackjack()
{
    vector<int> mano, mano_split, banco;
    bool play = true, mano1 = true, mano2 = false;
    int scelta, scommessa, score_mano1, score_mano2, score_banco;
    cout << "Benvuto/a in blackjack" << endl;
    cout << "Quanto vuoi puntare? ";
    cin >> scommessa;
    srand(time(0));
    mano.push_back(carta());
    mano.push_back(carta());
    banco.push_back(carta());
    banco.push_back(carta());
    cout << "La tua mano e':" << endl;
    visualizza(mano);
    cout << "Carta visibile del banco: " << nome_carta(banco.at(0)) << endl;
    do
    {
        cout << endl << "1. prendi una carta. 2. stai. 3. raddoppia: ";
        cin >> scelta;
        switch (scelta)
        {
        case 1:
            mano.push_back(carta());
            cout << "La tua mano e':" << endl;
            visualizza(mano);
            if (!mano_split.empty())
            {
                mano_split.push_back(carta());
                cout << "Seconda giocata: " << endl;
                visualizza(mano_split);
            }
            if (punteggio(mano) >= 21 && (mano_split.empty() || punteggio(mano_split) >= 21))
                play = false;

            break;
        case 2:
            play = false;
            break;
        case 3:
            if (mano.size() != 2)
            {
                cout << "Non puoi raddoppiare dopo aver preso una carta" << endl;
                break;
            }
            if (!can_split(mano))
            {
                cout << "Per raddoppiare le carte devono avere lo stesso valore" << endl;
                break;
            }
            // Sposta la seconda carta nella seconda giocata
            mano_split.push_back(mano.at(1));
            mano.erase(mano.end() - 1);
            // Richiedi due carte per le due giocate
            mano.push_back(carta());
            mano_split.push_back(carta());
            cout << "La tua mano e':" << endl;
            visualizza(mano);
            cout << "Seconda giocata: " << endl;
            visualizza(mano_split);
            scommessa *= 2;
            mano2 = true;
            break;
        default:
            cout << "Scelta non valida" << endl;
            break;
        }
    } while (play);

    score_mano1 = punteggio(mano);
    score_mano2 = punteggio(mano_split);

    if (mano2 && !(mano2 = !busted(mano_split)))
        lose(scommessa / 2);

    if (!(mano1 = !busted(mano)))
        lose(score_mano2 == 0 ? scommessa : scommessa / 2);

    if (!mano1 && !mano2)
        return;

    // Essendo 1v1 il banco prende carta finché non batte almeno una giocata o sballa
    score_banco = punteggio(banco);
    while (score_banco < score_mano1 && (score_mano2 == 0 || score_banco < score_mano2))
    {
        banco.push_back(carta());
        score_banco = punteggio(banco);
    }

    cout << "Il banco ha: " << endl;
    visualizza(banco);

    if (score_banco > 21)
    {
        cout << "Il banco ha sballato! " << score_banco << endl;
        win(scommessa);
        return;
    }

    if (score_mano2 != 0 && score_mano2 > score_banco)
        win(scommessa / 2);
    else if (score_mano2 != 0)
        lose(scommessa / 2);

    if (score_mano1 > score_banco)
        win(score_mano2 != 0 ? scommessa / 2 : scommessa);
    else
        lose(score_mano2 != 0 ? scommessa / 2 : scommessa);
}
 
  • Mi piace
Reazioni: --- Ra ---
Avevo implementato tempo fa il blackjack, l'ho modificato per seguire la tua struttura in modo che puoi vedere le cose che ti mancano: il calcolo del valore degli assi (se 1 o 11), che le carte siano uniche (non posso avere l'asso di cuori se c'è l'ha il banco...), le regole per raddoppiare (split) e altro.

Visualizza allegato 61526

C++:
int carte_usate[52] = {0};

int carta()
{
    int carta;
    do
    {
        carta = rand() % 52;

    } while (carte_usate[carta] != 0);

    carte_usate[carta] = 1;
    return carta;
}

string seme(int carta)
{
    const char* semi[] = { "Cuori", "Quadri", "Fiori", "Picche" };
    int seme = (carta / 13);
    return string(semi[seme]);
}

string nome_carta(int carta)
{
    const char* map[] = { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" };
    int v = (carta % 13);
    return string(map[carta % 13]) + " di " + seme(carta);
}

bool can_split(const vector<int>& mano)
{
    int carta1 = mano.at(0);
    int carta2 = mano.at(1);
    carta1 = min(carta1 % 13, 10);
    carta2 = min(carta2 % 13, 10);
    return (carta1 == carta2);
}

int punteggio(const vector<int> &mano)
{
    int totale = 0, assi = 0;
    for (int c : mano)
    {
        int i = min((c % 13) + 1, 10);
        if (i == 1)
            assi++;
        else
            totale += i;
    }
    if (assi > 0)
    {
        if (assi > 1)
            totale += assi - 1;

        totale += (totale + 11 > 21) ? 1 : 11;
    }
    return totale;
}

bool busted(const vector<int>& mano)
{
    int score = punteggio(mano);
    bool busted = (score > 21);
    if (busted)
        cout << "Hai sballato! " << score << endl;

    return busted;
}

void win(int amount)
{
    cout << "Hai vinto " << amount << endl;
}

void lose(int amount)
{
    cout << "Hai perso " << amount << endl;
}

void visualizza(const vector<int> &mano)
{
    for (int c : mano)
        cout << nome_carta(c) << endl;

    cout << "Totale: " << punteggio(mano) << endl;
}

void blackjack()
{
    vector<int> mano, mano_split, banco;
    bool play = true, mano1 = true, mano2 = false;
    int scelta, scommessa, score_mano1, score_mano2, score_banco;
    cout << "Benvuto/a in blackjack" << endl;
    cout << "Quanto vuoi puntare? ";
    cin >> scommessa;
    srand(time(0));
    mano.push_back(carta());
    mano.push_back(carta());
    banco.push_back(carta());
    banco.push_back(carta());
    cout << "La tua mano e':" << endl;
    visualizza(mano);
    cout << "Carta visibile del banco: " << nome_carta(banco.at(0)) << endl;
    do
    {
        cout << endl << "1. prendi una carta. 2. stai. 3. raddoppia: ";
        cin >> scelta;
        switch (scelta)
        {
        case 1:
            mano.push_back(carta());
            cout << "La tua mano e':" << endl;
            visualizza(mano);
            if (!mano_split.empty())
            {
                mano_split.push_back(carta());
                cout << "Seconda giocata: " << endl;
                visualizza(mano_split);
            }
            if (punteggio(mano) >= 21 && (mano_split.empty() || punteggio(mano_split) >= 21))
                play = false;

            break;
        case 2:
            play = false;
            break;
        case 3:
            if (mano.size() != 2)
            {
                cout << "Non puoi raddoppiare dopo aver preso una carta" << endl;
                break;
            }
            if (!can_split(mano))
            {
                cout << "Per raddoppiare le carte devono avere lo stesso valore" << endl;
                break;
            }
            // Sposta la seconda carta nella seconda giocata
            mano_split.push_back(mano.at(1));
            mano.erase(mano.end() - 1);
            // Richiedi due carte per le due giocate
            mano.push_back(carta());
            mano_split.push_back(carta());
            cout << "La tua mano e':" << endl;
            visualizza(mano);
            cout << "Seconda giocata: " << endl;
            visualizza(mano_split);
            scommessa *= 2;
            mano2 = true;
            break;
        default:
            cout << "Scelta non valida" << endl;
            break;
        }
    } while (play);

    score_mano1 = punteggio(mano);
    score_mano2 = punteggio(mano_split);

    if (mano2 && !(mano2 = !busted(mano_split)))
        lose(scommessa / 2);

    if (!(mano1 = !busted(mano)))
        lose(score_mano2 == 0 ? scommessa : scommessa / 2);

    if (!mano1 && !mano2)
        return;

    // Essendo 1v1 il banco prende carta finché non batte almeno una giocata o sballa
    score_banco = punteggio(banco);
    while (score_banco < score_mano1 && (score_mano2 == 0 || score_banco < score_mano2))
    {
        banco.push_back(carta());
        score_banco = punteggio(banco);
    }

    cout << "Il banco ha: " << endl;
    visualizza(banco);

    if (score_banco > 21)
    {
        cout << "Il banco ha sballato! " << score_banco << endl;
        win(scommessa);
        return;
    }

    if (score_mano2 != 0 && score_mano2 > score_banco)
        win(scommessa / 2);
    else if (score_mano2 != 0)
        lose(scommessa / 2);

    if (score_mano1 > score_banco)
        win(score_mano2 != 0 ? scommessa / 2 : scommessa);
    else
        lose(score_mano2 != 0 ? scommessa / 2 : scommessa);
}
Ci sono comandi che non ho mai visto e che il prof non ha mai spiegato tipo push_back
int carte_usate[52] = {0};
Poi perché hai messo quel {0};
 
Ci sono comandi che non ho mai visto e che il prof non ha mai spiegato tipo push_back

Poi perché hai messo quel {0};

Quello 0 serve ad inizializzare l'array di interi tutti a 0, altrimenti avrebbero dei valori casuali in base a cosa c'era prima in quell'area di memoria.

La funzione push_back appartiene alla classe vector, è come un array dinamico che non ha bisogno di specificare la dimensione all'inizio. Non usando vettori o linked list è difficile implementare una soluzione pulita, non basta tenere traccia del punteggio perché l'asso può cambiare valore in un secondo momento per non farti sballare.
 
Quello 0 serve ad inizializzare l'array di interi tutti a 0, altrimenti avrebbero dei valori casuali in base a cosa c'era prima in quell'area di memoria.

La funzione push_back appartiene alla classe vector, è come un array dinamico che non ha bisogno di specificare la dimensione all'inizio. Non usando vettori o linked list è difficile implementare una soluzione pulita, non basta tenere traccia del punteggio perché l'asso può cambiare valore in un secondo momento per non farti sballare.
Quindi se ho capito bene push_back crea un array senza che gli specifico la grandezza e che la grandezza a ogni avvio cambia?
 
Mi sono spiegato male, vector è l'array dinamico, push_back inserisce un elemento in coda al vettore. Il container vector cresce man mano che aggiungi elementi gestendo la parte di reallocazione della memoria da solo.

Esempio:
C++:
// Creazione del vettore
vector<int> vettore;
// Aggiunta di un elemento, deve essere dello stesso tipo specificato tra < >
vettore.push_back(123);
 
Mi sono spiegato male, vector è l'array dinamico, push_back inserisce un elemento in coda al vettore. Il container vector cresce man mano che aggiungi elementi gestendo la parte di reallocazione della memoria da solo.

Esempio:
C++:
// Creazione del vettore
vector<int> vettore;
// Aggiunta di un elemento, deve essere dello stesso tipo specificato tra < >
vettore.push_back(123);
Ok ora ho capito perfettamente, grazie!