Track
/
Python
Python
/
Esercizi
/
Black Jack
Black Jack

Black Jack

Esercizio di apprendimento

Introduzione

Confronti

Python supporta i seguenti operatori di confronto di base:

Operatore Operazione Descrizione
> «maggiore di» a > b è True se a è strettamente maggiore in valore di b
< «minore di» a < b è True se a è strettamente minore in valore di b
== «uguale a» a == b è True se a è strettamente uguale a b in valore
>= «maggiore o uguale a» a >= b è True se a > b OPPURE a == b in valore
<= «minore o uguale a» a <= b è True se a < b o a == b in valore
!= «diverso da» a != b è True se a == b è False
is «identità» a is b è True se e solo se a e b sono lo stesso oggetto
is not «identità negata» a is not b è True se a e b non sono lo stesso oggetto
in «test di appartenenza» a in b è True se a è membro, sottoinsieme o elemento di b
not in «test di appartenenza negato» a not in b è True se a non è membro, sottoinsieme o elemento di b

Hanno tutti la stessa priorità (che è più alta di quella delle operazioni booleane, ma più bassa di quella delle operazioni aritmetiche o bit a bit).

Confronto tra tipi di dati diversi

Gli oggetti di tipi diversi (tranne i tipi numerici) non risultano mai uguali per impostazione predefinita. Anche le istanze non identiche di una class non risulteranno uguali, a meno che la class non definisca metodi speciali di confronto ricco che personalizzano il comportamento di confronto predefinito di object. La personalizzazione tramite rich comparisons sarà trattata in un esercizio successivo. Per (molti) più dettagli su questo argomento, vedi Confronti di valore nella documentazione di Python.

I tipi numerici sono (per lo più) un'eccezione a questa regola di corrispondenza tra tipi. Un integer può essere considerato uguale a un float (o un octal uguale a un hexadecimal), purché i tipi possano essere convertiti implicitamente per il confronto.

Per gli altri tipi numerici nella libreria standard di Python (complex, decimal, fractions), gli operatori di confronto sono definiti dove «ha senso» (dove la conversione implicita non cambia il risultato), ma generano un TypeError se gli oggetti sottostanti non possono essere convertiti accuratamente per il confronto. Per maggiori informazioni sulle regole che Python usa per la conversione numerica, vedi conversioni aritmetiche nella documentazione di Python.

>>> 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

Qualsiasi confronto ordinato di un numero con un tipo NaN (not a number) è False. Un effetto collaterale confuso della definizione di NaN in Python è che NaN non è mai uguale a NaN.

>>> x = float('NaN')

>>> 3 < x
False

>>> x < 3
False

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

Confronto tra stringhe

A differenza dei numeri, le stringhe (str) vengono confrontate lessicograficamente, usando i loro singoli punti di codice Unicode (il risultato del passaggio di ogni punto di codice nella str alla funzione incorporata ord(), che restituisce un int). Se tutti i punti di codice in entrambe le stringhe corrispondono e sono nello stesso ordine, le due stringhe sono considerate uguali. Questo confronto viene fatto in modo «a coppie»: primo con primo, secondo con secondo, ecc. In Python 3.x, str e bytes non possono essere convertiti/confrontati direttamente.

>>> '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)

Concatenamento dei confronti

Gli operatori di confronto possono essere concatenati arbitrariamente, nel senso che possono essere usati in qualsiasi combinazione e di qualsiasi lunghezza. Nota che la valutazione di un'espressione avviene da left a right.

Ad esempio, x < y <= z è equivalente a x < y and y <= z, tranne per il fatto che y viene valutato una sola volta. In entrambi i casi, z non viene valutato affatto quando x < y risulta False. Questo è spesso chiamato short-circuit evaluation: la valutazione si ferma se il valore di verità dell'espressione è già stato determinato.

Il Short circuiting è supportato da vari operatori booleani, funzioni e anche dal concatenamento di confronti in Python. A differenza di molti altri linguaggi di programmazione, tra cui C, C++, C# e Java, le espressioni concatenate come a < b < c in Python hanno una convenzionale interpretazione matematica e una precedenza.

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

>>> x < y < z
True

>>> x < y > z
False

>>> x > y < z
False

Confronto dell'identità degli oggetti

Gli operatori is e is not verificano l'_identità_ di un oggetto, in contrapposizione al valore dell'oggetto. L'identità di un oggetto non cambia mai dopo la creazione e può essere trovata usando la funzione id().

<apple> is <orange> valuta a True se e solo se id(<apple>) == id(<orange>). <apple> is not <orange> restituisce l'inverso.

A causa del loro stato di singleton, None e NotImplemented dovrebbero sempre essere confrontati con gli elementi usando is e is not. Vedi la documentazione di riferimento di Python su confronti di valore e PEP8 per maggiori dettagli su questa convenzione.

>>> 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

Confronti di appartenenza

Gli operatori in e not in verificano l'appartenenza. <fish> in <soup> valuta a True se <fish> è un membro di <soup> (se <fish> è un sottoinsieme di <soup> o è contenuto in <soup>), e valuta False altrimenti. <fish> not in <soup> restituisce la negazione, o l'opposto di <fish> in <soup>.

Per i tipi string e bytes, <name> in <fullname> è True se e solo se <name> è una sottostringa di <fullname>.

# 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

Istruzioni

In questo esercizio implementerai alcune regole del Blackjack, come il modo in cui si gioca e si assegnano i punti.

Nota: In questo esercizio, A indica l'asso, J il fante, Q la regina e K il re. I jolly vengono scartati. Si presume l'uso di un mazzo standard francese da 52 carte, ma nella maggior parte delle versioni si mescolano insieme più mazzi per giocare.

1. Calcola il valore di una carta

A Blackjack, sta a ogni singolo giocatore decidere se un asso valga 1 o 11 punti (ne riparleremo più avanti). Le figure (J, Q, K) valgono 10 punti e qualsiasi altra carta vale il suo valore «pip» (numerico).

Definisci la funzione value_of_card(<card>) con parametro card. La funzione deve restituire il valore numerico della stringa della carta passata. Poiché un asso può assumere più valori (1 o 11), per ora questa funzione deve fissare il valore di un asso a 1. Più avanti implementerai una funzione che determina il valore di un asso, data una mano esistente.

>>> value_of_card('K')
10

>>> value_of_card('4')
4

>>> value_of_card('A')
1

2. Determina quale carta ha il valore più alto

Definisci la funzione higher_card(<card_one>, <card_two>) con parametri card_one e card_two. Ai fini del punteggio, il valore di J, Q o K è 10. La funzione deve restituire quale carta ha il valore più alto ai fini del punteggio. Se entrambe le carte hanno lo stesso valore, restituiscile entrambe. Restituire entrambe le carte è possibile usando una virgola nell'istruzione return:

# 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')

Un asso può assumere più valori, quindi per questo compito fisseremo le carte A a un valore di 1.

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

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

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

3. Calcola il valore di un asso

Come accennato prima, un asso può valere o 1 o 11 punti. I giocatori cercano di avvicinarsi il più possibile a un punteggio di 21, senza superare il 21 (cioè «sballare»).

Definisci la funzione value_of_ace(<card_one>, <card_two>) con parametri card_one e card_two, che sono una coppia di carte già presenti in mano prima di ricevere un asso. La funzione dovrà decidere se l'asso in arrivo avrà un valore di 1 o di 11 e restituire quel valore. Ricorda: il valore della mano con l'asso deve essere il più alto possibile senza superare il 21.

Suggerimento: se abbiamo già un asso in mano, il valore dell'asso in arrivo sarà 1.

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

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

4. Determina una mano «naturale» o «blackjack»

Se a un giocatore vengono distribuite un asso (A) e una carta da dieci (10, K, Q o J) come prime due carte, allora il giocatore ha un punteggio di 21. Questa è nota come mano blackjack.

Definisci la funzione is_blackjack(<card_one>, <card_two>) con parametri card_one e card_two, che sono una coppia di carte. Determina se la mano di due carte è un blackjack e restituisci il booleano True se lo è, False altrimenti.

Nota: Il calcolo del punteggio può essere fatto in molti modi. Ma, se possibile, vorremmo che controllassi se ci sono un asso e una carta da dieci nella mano (o in una certa posizione), invece di sommare i valori della mano.

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

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

5. Dividere le coppie

Se le prime due carte di una mano hanno lo stesso valore (ad esempio due sei oppure una Q ed un K), un giocatore può scegliere di trattarle come due mani separate. Questa operazione è nota come «dividere le coppie».

Definisci la funzione can_split_pairs(<card_one>, <card_two>) con parametri card_one e card_two, che sono una coppia di carte. Determina se questa mano di due carte può essere divisa in due coppie. Se la mano può essere divisa, restituisci il booleano True, altrimenti restituisci False

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

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

6. Raddoppiare la puntata

Quando le due carte distribuite inizialmente totalizzano 9, 10 o 11 punti, un giocatore può piazzare una puntata aggiuntiva pari a quella iniziale. Questa operazione è nota come «raddoppiare la puntata».

Definisci la funzione can_double_down(<card_one>, <card_two>) con parametri card_one e card_two, che sono una coppia di carte. Determina se la mano di due carte può essere «raddoppiata», e restituisci il booleano True se può esserlo, False altrimenti.

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

>>> can_double_down('10', '2')
False
Modifica tramite GitHub Il link si apre in una nuova finestra o scheda
Python Exercism

Vuoi iniziare Black Jack?

Iscriviti a Exercism per imparare e padroneggiare Python con 17 concetti146 esercizi e il mentoring di persone reali, tutto gratis.