Blackjack

Blackjack

Tanulófeladat

Bevezetés

Összehasonlítások

A Python a következő alapvető összehasonlító operátorokat támogatja:

Operátor Művelet Leírás
> „nagyobb, mint” az a > b akkor True, ha a értéke szigorúan nagyobb, mint b értéke
< „kisebb, mint” az a < b akkor True, ha a értéke szigorúan kisebb, mint b értéke
== „egyenlő” az a == b akkor True, ha a értéke szigorúan egyenlő b értékével
>= „nagyobb vagy egyenlő” az a >= b akkor True, ha érték szerint a > b VAGY a == b
<= „kisebb vagy egyenlő” az a <= b akkor True, ha érték szerint a < b vagy a == b
!= „nem egyenlő” az a != b akkor True, ha az a == b értéke False
is „azonosság” az a is b akkor és csak akkor True, ha a és b ugyanaz az objektum
is not „tagadott azonosság” az a is not b akkor True, ha a és b nem ugyanaz az objektum
in „tartalmazásvizsgálat” az a in b akkor True, ha a tagja, részhalmaza vagy eleme b-nek
not in „tagadott tartalmazásvizsgálat” az a not in b akkor True, ha a nem tagja, részhalmaza vagy eleme b-nek

Mindegyikük prioritása ugyanaz (ez magasabb, mint a Boolean-műveletek prioritása, de alacsonyabb az aritmetikai vagy bitenkénti műveletek prioritásánál).

Összehasonlítás különböző adattípusok között

A különböző típusú objektumok (a numerikus típusok kivételével) alapértelmezés szerint soha nem számítanak egyenlőnek. Egy class nem azonos példányai szintén nem számítanak egyenlőnek, kivéve, ha a class olyan speciális rich comparison metódusokat definiál, amelyek testre szabják az object alapértelmezett összehasonlítási viselkedését. A rich comparisons használatával történő testreszabást egy későbbi feladatban tárgyaljuk. Ha (sokkal) részletesebben szeretnél olvasni erről a témáról, nézd meg az értékek összehasonlítása részt a Python dokumentációjában.

A numerikus típusok (többnyire) kivételt képeznek ez alól a típusegyezési szabály alól. Egy integer egyenlőnek tekinthető egy float-tal (vagy egy octal egyenlő egy hexadecimal értékkel), amennyiben a típusok az összehasonlításhoz implicit módon átalakíthatók.

A Python szabványos könyvtárában található többi numerikus típus (complex, decimal, fractions) esetében az összehasonlító operátorok ott vannak definiálva, ahol „van értelmük” (vagyis ahol az implicit átalakítás nem változtatja meg az eredményt), de TypeError-t dobnak, ha a mögöttes objektumok nem alakíthatók át pontosan az összehasonlításhoz. Ha többet szeretnél megtudni azokról a szabályokról, amelyeket a Python a numerikus átalakításnál használ, nézd meg az aritmetikai átalakítások részt a Python dokumentációjában.

>>> import fractions

# A string cannot be converted to an int.
>>> 17 == '17'
False

# An int can be converted to float for comparison.
>>> 17 == 17.0
True

# The fraction 6/3 can be converted to the int 2
# The int 2 can be converted to 0b10 in binary.
>>> 6/3 == 0b10
True

# An int can be converted to a complex number with a 0 imaginary part.
>>> 17 == complex(17)
True

# The fraction 2/5 can be converted to the float 0.4
>>> 0.4 == 2/5
True

>>> complex(2/5, 1/2) == complex(0.4, 0.5)
True

Egy szám bármely rendezett összehasonlítása egy NaN (not a number) típussal False. A Python NaN definíciójának zavaró mellékhatása, hogy a NaN soha nem számít egyenlőnek a NaN-nal.

>>> x = float('NaN')

>>> 3 < x
False

>>> x < 3
False

# NaN never compares equal to NaN
>>> x == x
False

Stringek összehasonlítása

A számokkal ellentétben a stringek (str) összehasonlítása lexikografikusan történik, az egyes Unicode-kódpontjaik alapján (amit úgy kapunk meg, hogy a str minden kódpontját átadjuk a beépített ord() függvénynek, amely egy int értéket ad vissza). Ha mindkét string minden kódpontja megegyezik, és ugyanabban a sorrendben szerepel, a két string egyenlőnek számít. Ez az összehasonlítás „páronkénti” módon történik: elsőt az elsővel, másodikat a másodikkal, és így tovább. A Python 3.x-ben a str és a bytes nem alakítható át és nem hasonlítható össze közvetlenül.

>>> 'Python' > 'Rust'
False

>>> 'Python' > 'JavaScript'
True

# Examples with Mandarin.
# hello < goodbye
>>> '你好' < '再见'
True

# ord() of first characters
>>> ord('你'), ord('再')
(20320, 20877)

# ord() of second characters
>>> ord('好'), ord('见')
(22909, 35265)

# And with Korean words.
# Pretty < beautiful.
>>> '예쁜' < '아름다운'
False

>>> ord('예'), ord('아')
(50696, 50500)

Az összehasonlítások láncolása

Az összehasonlító operátorok tetszőlegesen láncolhatók, ami azt jelenti, hogy bármilyen hosszúságú, bármilyen kombinációban használhatók. Fontos, hogy egy kifejezés kiértékelése left-től right-ig halad.

Például az x < y <= z egyenértékű az x < y and y <= z kifejezéssel, azzal a kivétellel, hogy y kiértékelése csak egyszer történik meg. Mindkét esetben z kiértékelése egyáltalán nem történik meg, ha az x < y értéke False. Ezt gyakran short-circuit evaluation-nek nevezik: a kiértékelés leáll, ha a kifejezés igazságértéke már meghatározható.

A Short circuiting-et többféle Boolean operátor és függvény is támogatja, és a Pythonban az összehasonlítások láncolása is. Sok más programozási nyelvvel ellentétben, köztük a C, a C++, a C# és a Java nyelvvel, a Pythonban az olyan láncolt kifejezések, mint az a < b < c, hagyományos matematikai értelmezéssel és precedenciával rendelkeznek.

>>> x = 2
>>> y = 5
>>> z = 10

>>> x < y < z
True

>>> x < y > z
False

>>> x > y < z
False

Objektumazonosság összehasonlítása

Az is és az is not operátor az objektum azonosságát vizsgálja, szemben az objektum értékével. Egy objektum azonossága létrehozása után soha nem változik, és a id() függvénnyel deríthető ki.

A <apple> is <orange> akkor és csak akkor értékelődik ki True-ra, ha id(<apple>) == id(<orange>). A <apple> is not <orange> ennek az ellenkezőjét adja.

Mivel ezek singleton értékek, a None és a NotImplemented összehasonlítását mindig az is és az is not operátorral érdemes végezni. A részletekért erről a konvencióról lásd a Python referenciadokumentációját az értékek összehasonlításáról, valamint a PEP8 útmutatót.

>>> my_fav_numbers = [1, 2, 3]

>>> your_fav_numbers = my_fav_numbers

>>> my_fav_numbers is your_fav_numbers
True

# The returned id will differ by system and python version.
>>> id(my_fav_numbers)
4517478208

# your_fav_numbers is only an alias pointing to the original my_fav_numbers object.
# Assigning a new name does not create a new object.
>>> id(your_fav_numbers)
4517478208


>>> my_fav_numbers is not your_fav_numbers
False

>>> my_fav_numbers is not None
True

>>> my_fav_numbers is NotImplemented
False

Tagsági vizsgálatok

Az in és a not in operátor a tagságot vizsgálja. A <fish> in <soup> akkor értékelődik ki True-ra, ha <fish> tagja a <soup>-nak (azaz ha <fish> részhalmaza a <soup>-nak, vagy benne van a <soup>-ban), egyébként pedig False. A <fish> not in <soup> a tagadását, vagyis a <fish> in <soup> ellentétét adja eredményül.

String- és bytes-típusok esetén a <name> in <fullname> akkor és csak akkor True, ha <name> részstringje a <fullname>-nek.

# A set of lucky numbers.
>>> lucky_numbers = {11, 22, 33}
>>> 22 in lucky_numbers
True

>>> 44 in lucky_numbers
False

# A dictionary of employee information.
>>> employee = {'name': 'John Doe', 
                'id': 67826, 'age': 33, 
                'title': 'ceo'}

# Checking for the membership of certain keys.
>>> 'age' in employee
True

>>> 33 in employee
False

>>> 'lastname' not in employee
True

# Checking for substring membership
>>> name = 'Super Batman'
>>> 'Bat' in name
True

>>> 'Batwoman' in name
False

Utasítások

Ebben a feladatban a Blackjack néhány szabályát fogod megvalósítani, például azt, hogyan játsszák és pontozzák a játékot.

Megjegyzés: Ebben a feladatban az A ászt, a J bubit, a Q dámát, a K pedig királyt jelent. A jokereket nem használjuk. Egy standard francia színes 52 lapos pakliból indulunk ki, de a legtöbb változatban több paklit kevernek össze a játékhoz.

1. Egy kártya értékének kiszámítása

Blackjackben minden játékos maga dönti el, hogy az ász 1 vagy 11 pontot ér (erről később még lesz szó). A figurás kártyák (J, Q, K) 10 pontot érnek, minden más kártya pedig a „pip” (számérték) értékét éri.

Definiáld a value_of_card(<card>) függvényt card paraméterrel. A függvénynek vissza kell adnia az átadott kártya string numerikus értékét. Mivel az ász több értéket is felvehet (1 vagy 11), ez a függvény egyelőre rögzítse az ász kártya értékét 1-ben. Később megvalósítasz egy függvényt, amely egy meglévő kéz ismeretében meghatározza az ász kártya értékét.

>>> value_of_card('K')
10

>>> value_of_card('4')
4

>>> value_of_card('A')
1

2. A nagyobb értékű kártya meghatározása

Definiáld a higher_card(<card_one>, <card_two>) függvényt card_one és card_two paraméterekkel. Pontozás szempontjából a J, Q vagy K értéke 10. A függvénynek vissza kell adnia, hogy melyik kártya értéke nagyobb a pontozás szempontjából. Ha mindkét kártya értéke egyenlő, add vissza mindkettőt. A két kártya visszaadásához vesszőt használhatsz a return utasításban:

# Using a comma in a return creates a Tuple.  Tuples will be covered in a later exercise.
>>> def returning_two_values(value_one, value_two):
        return value_one, value_two

>>> returning_two_values('K', '3')
('K', '3')

Az ász több értéket is felvehet, ezért ebben a részfeladatban a A kártyák értékét 1-ben rögzítjük.

>>> higher_card('K', '10')
('K', '10')

>>> higher_card('4', '6')
'6'

>>> higher_card('K', 'A')
'K'

3. Az ász értékének kiszámítása

Ahogy korábban említettük, az ász akár 1 vagy 11 pontot is érhet. A játékosok a lehető legközelebb próbálnak kerülni a 21-hez, anélkül hogy túllépnének 21-en (azaz „besokallnának”).

Definiáld a value_of_ace(<card_one>, <card_two>) függvényt card_one és card_two paraméterekkel; ezek egy pár kártya, amelyek már a kézben vannak, mielőtt ász kártyát kapnál. A függvényednek el kell döntenie, hogy a következő ász 1-es vagy 11-es értéket kap-e, és vissza kell adnia ezt az értéket. Ne feledd: a kéz értékének az ásszal együtt a lehető legmagasabbnak kell lennie, anélkül hogy meghaladná a 21-et.

Tipp: ha már van ász a kezünkben, akkor a következő ász értéke 1 lenne.

>>> value_of_ace('6', 'K')
1

>>> value_of_ace('7', '3')
11

4. A „Natural” vagy „Blackjack” kéz meghatározása

Ha a játékos első két lapként ászt (A) és tízest (10, K, Q vagy J) kap, akkor a pontszáma 21. Ezt nevezik blackjack kéznek.

Definiáld az is_blackjack(<card_one>, <card_two>) függvényt card_one és card_two paraméterekkel; ezek egy pár kártya. Döntsd el, hogy a kétkártyás kéz blackjack-e, és add vissza a Boolean True értéket, ha igen, egyébként False-t.

Megjegyzés: A pontszám kiszámítása többféleképpen is elvégezhető. De ha lehetséges, szeretnénk, ha ellenőriznéd, hogy van-e ász és tízes a kézben (vagy egy adott pozícióban), ahelyett hogy összeadnád a kéz értékeit.

>>> is_blackjack('A', 'K')
True

>>> is_blackjack('10', '9')
False

5. Párok szétválasztása

Ha egy kéz első két lapja azonos értékű (például két hatos vagy egy Q és K), a játékos dönthet úgy, hogy két külön kézként kezeli őket. Ezt nevezik „párok szétválasztásának”.

Definiáld a can_split_pairs(<card_one>, <card_two>) függvényt card_one és card_two paraméterekkel; ezek egy pár kártya. Döntsd el, hogy ez a kétkártyás kéz szétválasztható-e két párra. Ha a kéz szétválasztható, add vissza a Boolean True értéket, egyébként False-t.

>>> can_split_pairs('Q', 'K')
True

>>> can_split_pairs('10', 'A')
False

6. Duplázás

Amikor az osztott első két lap összértéke 9, 10 vagy 11 pont, a játékos további tétet tehet, amely megegyezik az eredeti tétével. Ezt nevezik „duplázásnak”.

Definiáld a can_double_down(<card_one>, <card_two>) függvényt card_one és card_two paraméterekkel; ezek egy pár kártya. Döntsd el, hogy a kétkártyás kéz „duplázható”-e, és add vissza a Boolean True értéket, ha igen, egyébként False-t.

>>> can_double_down('A', '9')
True

>>> can_double_down('10', '2')
False
Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg
Python Exercism

Készen állsz elkezdeni a(z) Blackjack feladatot?

Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) Python nyelvet 17 fogalom146 feladat segítségével, valódi emberi mentorálással, mindez ingyen.