Autor zadání | David Klaška |
---|---|
Úprava | Patrick Ondika |
Odevzdávané soubory |
main.c
|
Začátek odevzdávání | viz diskusní fórum |
Další odevzdání navíc do | 2025-03-19 24:00 |
Konec odevzdání | 2025-03-26 24:00 |
Vzorová implementace |
/home/kontr/pb071/hw02/poker
|
Opravy v zadání | 2025-03-24 18:27 |
Představení úkolu
V této úloze se budeme věnovat světově nejpopulárnější karetní hře — pokeru. Tato hra je známá ve spoustě variant. My se zde budeme zabývat tou patrně nejrozšířenější, Texas Hold’em Poker, kdy každý hráč drží v ruce dvě karty a na stůl je rozdáno (až) pět karet společných pro všechny hráče.
Zadání
Vaším úkolem bude napsat program, který bude komunikovat s uživatelem prostřednictvím příkazové řádky. Váš program bude samozřejmě muset umět porovnávat mezi sebou jednotlivé karetní kombinace.
Jádrem problému bude algoritmus rozhodující, který ze dvou hráčů vyhrál, bude-li znát obě karty obou hráčů i všech pět karet ležících na stole.
Pravidla hry
Podrobnější popis pravidel naleznete např. na Wikipedii v článku Texas Hold’em Poker nebo seznamu karetních kombinací pokru. |
-
Každý hráč má k dispozici dvě soukromé karty a pět společných karet, jež jsou vyloženy na stole. Z těchto sedmi karet sestavuje nejsilnější možnou kombinaci pěti karet. Nejsilnější pětikaretní kombinace vyhrává.
-
Nejvyšší kartou je A (výjimkou je postupka, kde ji lze použít jako kartu s hodnotou 1) — následují K, Q, J, 10, 9, 8, 7, 6, 5, 4, 3, 2.
-
Všechny barvy karet jsou rovnocenné.
Výherní kombinace od nejvyšší po nejnižší jsou následující:
-
Straight flush je čistá postupka (všechny karty mají stejnou barvu, např. 7 6 5 4 3). V případě, že mají oba hráči straight flush, vítěz je ten, kdo má tuto postupku zakončenou vyšší kartou. V případě shody dochází k remíze.
A se může v čisté postupce vyskytovat jako karta nejvyšší (takové postupce se říká royal straight flush), nebo jako karta nejnižší (takové postupce se říká steel wheel).
-
Four of a kind (poker) je čtveřice, tzn. čtyři karty stejné hodnoty (např. 5 5 5 5). V případě, že mají oba hráči four of a kind, rozhoduje o vítězi hodnota čtveřice. V případě shody rozhoduje hodnota páté (doplňující) karty. Shoduje-li se i hodnota doplňující karty, dochází k remíze.
-
Full house je trojice a dvojice (např. 7 7 7 10 10). V případě, že mají oba hráči full house, rozhoduje o vítězi hodnota trojice. V případě shody rozhoduje hodnota dvojice. Shoduje-li se i hodnota dvojice, dochází k remíze.
-
Flush je pět karet libovolné hodnoty, ale stejné barvy (např. A 10 8 7 2). V případě, že mají oba hráči flush, rozhoduje nejvyšší karta. Shoduje-li se hodnota nejvyšší karty, rozhoduje druhá nejvyšší karta atd. Mají-li oba hráči pětice se stejnými hodnotami (seřazenými od nejvyšší karty po nejnižší), dochází k remíze.
-
Straight je špinavá postupka (např. 9 8 7 6 5). V případě, že mají oba hráči straight, vítěz je ten, kdo má tuto postupku zakončenou vyšší kartou. V případě shody dochází k remíze.
Stejně jako v čisté postupce, i zde se A může vyskytovat jako karta nejvyšší (takové postupce se říká broadway straight), nebo jako karta nejnižší (takové postupce se říká baby straight).
-
Three of a kind je trojice (např. K K K). V případě, že mají oba hráči three of a kind, rozhoduje o vítězi hodnota trojice. V případě shody rozhoduje hodnota vyšší ze dvou doplňujících karet. Shodují-li se hodnoty vyšších doplňujících karet, rozhodují ty nižší. Shodují-li se i ty, dochází k remíze.
-
Two pair jsou dvě dvojice (např. 4 4 2 2). V případě, že mají oba hráči two pair, rozhoduje o vítězi hodnota vyšší dvojice. V případě shody rozhoduje hodnota nižší dvojice. Shodují-li se i hodnoty nižších dvojic, rozhodují hodnoty pátých (doplňujících) karet. Shodují-li se i ty, dochází k remíze.
-
Pair je dvojice (např. 5 5). V případě, že mají oba hráči pair, rozhoduje o vítězi hodnota dvojice. V případě shody rozhoduje nejvyšší ze tří doplňujících karet. Shoduje-li se nejvyšší z doplňujících karet, rozhoduje druhá nejvyšší. Pokud se shoduje i ta nejnižší, dochází k remíze.
-
High card je vysoká karta. Pokud ani jeden z hráčů nemá lepší kombinaci, rozhoduje o vítězi nejvyšší z pěti karet. V případě shody rozhoduje druhá nejvyšší atd. Mají-li oba hráči pětice se stejnými hodnotami (seřazenými od nejvyšší karty po nejnižší), dochází k remíze.
Formát vstupu a výstupu
Karty budou reprezentovány dvojicí znaků:
-
první z nich určuje hodnotu;
2
,3
,4
,5
,6
,7
,8
,9
,T
,J
,Q
,K
,A
pro po řadě 2, 3, …, 10, J, Q, K, A, -
druhý barvu;
h
,d
,s
,c
pro po řadě ♥ (srdce, hearts), ♦ (káry, diamonds), ♠ (piky, spades), ♣ (kříže, clubs).
Vstup bude sestávat z několika po sobě jdoucích instancí (situací), výstup pak z odpovědí na jednotlivé instance. Program tedy neskončí hned po vyřešení jediné instance, ale až když se na vstupu nenachází žádná další instance (End of File).
Porovnávání dvou hráčů
Vstupní instance budou sestávat ze tří řádků:
-
na prvním budou dvě karty jednoho hráče,
-
na druhém dvě karty druhého hráče,
-
na třetím pět karet ležících na stole
Váš program odpoví pro každou instanci tím, který hráč vyhrál, tedy:
-
Player 1
, pokud vyhrál první hráč, -
Player 2
, pokud vyhrál druhý, -
Draw
, pokud nastala remíza.
Karty jsou na jednom řádku oddělené mezerou. Každý řádek na výstupu je ukončen znakem pro nový řádek.
Korektnost vstupu
Program musí ověřit, že formát vstupu odpovídá popisu výše. Pro jednoduchost nemusíte vyžadovat přesně jednu mezeru, stačí ověřit následující podmínky:
-
Karta má správný tvar a je v aktuální instanci jedinečná.
-
Mezi kartami na řádku je alespoň jeden bílý znak (nemusí být nutně mezera).
-
Na řádku se nachází očekávaný počet karet a pak znak
\n
. -
Instance je kompletní, tj. pokud se povede načíst první řádek, pak musí být na vstupu i zbylé řádky instance.
Pokud některá podmínka neplatí, vypište nějakou smysluplnou zprávu
ukončenou znakem \n
na standardní chybový výstup
voláním funkce fprintf()
s prvním argumentem stderr
.
Tato zpráva musí být pouze na jediném řádku, tzn. pokud vypisujete
část vstupu, dejte si pozor, aby program nevypsal další '\n'
uvnitř zprávy.
Další instance se po chybě zpracovávat nesmí, program ukončete
s libovolným návratovým kódem.
Příklad použití funkce fprintf()
:
if (!card_is_valid(card))
fprintf(stderr, "%s: invalid card\n", card);
Tato funkce se chová jako printf(FORMAT, …)
, ale výstup se objeví
na chybovém výstupu. Text zpráv je na vás, ale měly by dávat smysl
a musí být jasné, proč došlo k chybě. Například error
není vhodná zpráva.
Kompilace
Některé testy naostro zkouší velký počet instancí (až 2¹⁸). Proto se tyto
testy kompilují s přepínačem -O2
, který zapne některé optimalizace.
Je však nezbytné vyzkoušet si kompilaci řešení na Aise i s tímto přepínačem. Kompilátor totiž může při optimalizaci kódu odhalit problémy, pro které vygeneruje další varování.
# Nejdřív vyzkoušejte kompilaci běžným způsobem
login@aisa:~$ gcc -std=c99 -pedantic -Wall -Wextra -Werror -o poker main.c
# Pak vyzkoušejte kompilaci s -O2
login@aisa:~$ gcc -O2 -std=c99 -pedantic -Wall -Wextra -Werror -o poker main.c
Ukázkové příklady
Pro vstup:
3d 3h
Ac Ts
Qd 8s 2c 4c Kh
4s 8d
5c 8h
7c 7h Ac Kd 2d
6s Kh
Ah 3c
Ac 4h 5h Ks Jh
je očekávaným výstupem
Player 1
Draw
Player 2
Komentář:
-
V prvním případě má první hráč dvojici trojek (3 3), a druhý žádnou dvojici, tedy nezáleží na hodnotě jeho karet.
-
V druhém případě první hráč hraje 7 7 A K 8, druhý hráč hraje 7 7 A K 8 (porovnává se vždycky pouze pět nejlepších karet, v tomto případě pár a tři zbylé nejvyšší karty). Pár 7 7 je pro oba hráče společný, a zbytek karet má stejnou hodnotu, proto dochází k remíze.
To, že jeden drží 5, zatímco druhý 4, je již nepodstatné. * Ve třetím případě má první hráč dvojici (K K), ale druhý má vyšší dvojici (A A).
Bonusová rozšíření
Rozšíření na více hráčů [10 bodů]
Upravte implementaci tak, aby fungovala pro 2 až 8 hráčů.
Počet hráčů pro danou instanci dostane program na příkazové řádce. Způsob jak správně přečíst argument najdete v přiložené kostře, ošetřit jeho korektnost je na vás. Formát vstupu zůstává stejný; program čeká na 2 karty pro každého hráče, poté 5 karet na stole, a při chybě vypíše vhodnou chybovou hlášku.
Výstup programu také zůstává stejný. Program vypíše hráče s nejsilnější kombinací, a pokud výherní kombinaci má více hráčů, výstupem bude
Draw
Tipy a poznámky
-
Pro případ, že byste měli nejasnosti týkající se formátu vstupu a výstupu nebo srovnávání jednotlivých karetních kombinací, můžete srovnat chování vašeho programu se vzorovým řešením, které je vám k dispozici na Aise na
/home/kontr/pb071/hw02/poker
.Vzorová implementace s přepínačem
-e
(explain) navíc vysvětlí na výstupu, který hráč má jakou kombinaci. -
Výstup vašeho programu bude testován strojově, nesmí se tedy lišit ani v jediném znaku.
-
K otestování korektnosti vstupu stačí vhodně použít funkci
scanf()
. Doporučujeme si přečíst dokumentaci. -
Časová efektivita vašeho programu je také důležitá, proto si dávejte pozor, aby váš program nebyl zbytečně pomalý.
Opravy v zadání
Fix solution path in Tips and Notes
2d69a7b
2025-03-24 18:27
Roman Lacko
-257,3 +257,3 Draw
chování vašeho programu se vzorovým řešením, které je vám k dispozici
- na Aise na `{page.solution-path}`.
+ na Aise na `{{ page.solution-path }}`.
+