În timp ce Henry, Hetty și Harry dorm în casele lor din Anglia, Charles a plecat să facă în continuare curățenie – în cazinourile din Las Vegas. El va petrece zile în acel oraș, încercând să câștige cât mai mulți bani la masa de Blackjack. În cazinourile frecventate de Charles, jocul de Blackjack se desfășoară după următoarele reguli:
Desfășurarea jocului
În fiecare din cele seri, Charles pleacă de acasă cu o sumă de bani și se așează la o masă de joc la care se mai alfă doar dealerul (cel care împarte cărțile). Jocul se desfășoară în etape, numite mâini. O mână se desfășoară astfel:
- Charles pariază o sumă de bani pe mâna curentă. Natural, Charles nu are voie să parieze mai mulți bani decât deține în acel moment.
- Dealerul pune pe masă o carte cu fața în sus – aceasta este prima carte a dealerului.
- Charles primește două cărți.
- Cât timp suma valorilor cărților lui Charles (vom nota această sumă cu ) nu depășește , Charles are opțiunea să mai ceară o carte. Acest pas se repetă până Charles anunță că nu mai dorește cărți. Charles este obligat să anunțe că nu mai dorește cărți dacă a depășit .
- Dealerul trage cărți din pachet până când suma valorilor cărților lui (să o notăm cu ) depășește .
- Charles primește înapoi bani corespunzător rezultatului mâinii, astfel:
- – dacă și , sau dacă și .
- – dacă și , sau dacă și
- – dacă și , sau dacă și .
Cărțile
În jocul de Blackjack se folosesc cărțile aferente a pachete standard de de cărți ( cărți pentru fiecare număr de la la , plus ași , popi , dame și valeți ). Cărțile numererotate au valoarea egală cu numărul înscris pe ele, popii, damele și valeții au valoarea , iar un as poate să ia fie valoarea fie valoarea (la decizia jucătorului).
Suma valorilor unui set de cărți se definește ca cea mai mare sumă ce se poate forma din valorile acelor cărți astfel încât aceasta să nu depășească . În caz că acest lucru nu este posibil, suma valorilor setului de cărți se definește ca fiind cea mai mică sumă ce se poate forma din valorile acelor cărți. Exemple: suma valorilor setului este , a setului este (unul din ași ia valoarea , celălalt ), a setului este , iar a setului este .
La începutul jocului, cărțile sunt amestecate și sunt puse într-un teanc cu fața în jos. Pe parcursul jocului, cărțile se împart din vârful teancului. Odată folosite pentru o mână, cărțile nu vor mai fi folosite pentru o alta până la o reamestecare a pachetului. După ce se termină o mână și în teanc se află mai puțin de de cărți, toate cărțile sunt reamestecate. Jocul din seara respectivă continuă până când cărțile sunt amestecate -a oară.
Cerință
După nopți de joc intens, Charles s-a întors acasă cu un profit considerabil. Voi puteți atinge același succes ca Charles? Scrieți un program care ține locul lui Charles într-un joc de Blackjack jucat după regulile descrise mai sus, cu scopul de a câștiga cât mai mulți bani la finalul jocului.
Interacțiune
Pentru a rezolva această problemă va trebui ca în sursa voastră să existe următoarele funcții:
void startGame(int money, int nPacks);
Această funcție este apelată de exact ori, semnificând faptul că jucătorul începe un joc nou. Ea primește ca parametru suma de bani cu care începe să joace concurentul în acel joc și numărul de pachete care se vor folosi pentru joc.
void playHand();
Această funcție va fi apelată de fiecare dată când se va juca o mână. Interacțiunea dintre programul comisiei și această funcție se realizează conform cu pașii de desfășurare a unei mâini descriși în enunț, și anume:
- Concurentul apelează funcția
pentru a paria o sumă de bani bet pe mâna curentă. Funcția returnează suma de bani pe care o mai are concurentul după ce a făcut pariul.int placeBet(int bet)
- Concurentul apelează o singură dată funcția
care returnează valoarea primei cărți a dealerului.int getDealerCard()
- Concurentul apelează de două ori funcția
pentru a afla valorile primelor două cărți ale sale. Funcția returnează valoarea unei cărți primite de concurent.int getCard()
- Cât timp suma a valorilor cărților sale nu depășește , concurentul poate apela din nou
getcard
pentru a cere o nouă carte. Funcția returnează valoarea cărții primite. Acest pas se repetă până concurentul apelează funcția
prin care anunță că nu mai dorește cărți. Atenție! În cazul în care, după ce concurentul a primit o carte, suma a depășit , concurentul este obligat să apelezevoid stand()
stand
. - Pentru a afla cărțile pe care dealerul le trage din pachet, concurentul apelează repetat
fiecare apel al acestei funcții returnând valoarea unei cărți trase de dealer sau dacă dealerul s-a oprit din a trage cărți. După ce funcțiaint getOutcome()
getOutcome
a returnat 0 aceasta nu se mai apelează pentru mâna curentă. Reamintim că dealerul trage cărți din pachet până când suma valorilor cărților lui (să o notăm cu ) depășește . - Concurentul apelează o singură dată
pentru a afla câți bani primește înapoi. Funcția returnează suma primită de concurent după ce a jucat o mână. Reamintim că această sumă este:int cashIn()
- – dacă și , sau dacă și .
- – dacă și , sau dacă și
- – dacă și , sau dacă și .
Ca să rezumăm, ordinea în care jucătorul apelează funcțiile pentru o mână este: placeBet(int bet)
getDealerCard()
getCard()
getCard()
(de câte ori mai dorește jucătorul, maxim până depășește ) stand()
getOutcome()
(până retunează ) cashIn()
.
void reshuffle();
Această funcție se apelează după terminarea unei mâini pentru a semnaliza concurentului că toate cărțile folosite în mâinile precedente au fost repuse în teanc iar teancul a fost reamestecat.
Restricții și precizări
- Pentru orice apel al funcției
placeBet(int bet)
, , unde reprezintă suma de bani pe care o are concurentul în acel moment. - Un apel al funcțiilor
getCard
,getDealerCard
saugetOutcome
va returna în cazul în care cartea returnată este un as, și în cazul în care cartea returnată este un , un popă, o damă sau un valet. - În cazul în care, după ce s-a terminat de jucat o mână și concurentul are cel puțin bani, jocul se termină și concurentul primește punctaj maxim pe acel test.
- Punctajul concurentului se va stabili în felul următor: se rulează sursa concurentului și se iau cele sume de bani cu care concurentul termină fiecare joc și se sortează descrescător. Se elimină primele două și ultimele două din acest șir și se stabilește = suma valorilor din acest șir. În mod similar se definește pentru sursa comisiei . Definim . Punctajul concurentului pe un test este .
Exemplu de interacțiune
grader
: startGame(20000, 10)
grader
: playHand()
concurent
: placeBet(100)
grader
: return 19900
concurent
: getDealerCard()
grader
: return 9
concurent
: getCard()
grader
: return 11
concurent
: getCard()
grader
: return 10
concurent
: cashIn()
grader
: return 200
concurent
: getOutcome()
grader
: return 5
concurent
: getOutcome()
grader
: return 6
concurent
: getOutcome()
grader
: return 0
grader
: startGame(2000, 10)
grader
: playHand()
concurent
: placeBet(100)
grader
: return 1900
concurent
: getDealerCard()
grader
: return 10
concurent
: getCard()
grader
: return 10
concurent
: getCard()
grader
: return 9
concurent
: getCard()
grader
: return 4
concurent
: stand()
concurent
: getOutcome()
grader
: return 10
concurent
: getOutcome()
grader
: return 0
concurent
: cashIn()
grader
: return 0
grader
: reshuffle()
Explicație
Funcția startGame
este apelată cu parametrii , semnificând că în teancul de cărți se vor afla cărțile a pachete standard, și , reprezentând suma de bani pe care o are inițial concurentul.
Se semnalizează concurentului începerea unei mâini.
Concurentul pariază că va câștiga mâna curentă
Dealerul a primit un .
Concurentul apelează de ori getCard
pentru a primi primele cărți. El primește un as și un . Suma cărților concurentului este .
Concurentul anunță că nu mai dorește cărți.
Dealerul primește un și un . Suma cărților dealerului este .
Concurentul a câștigat mâna și primește de bani. Acum are bani.
Începe a doua seară de joc.
Concurentul mai cere o carte după primele . Aceasta este și face ca suma să devină .
Concurentul este obligat să apeleze stand
acum.
Concurentului îi este semnalizat faptul că teancul de cărți a fost reamestecat.