Μπλακ Τζακ

Μπλακ Τζακ

Άσκηση εκμάθησης

Εισαγωγή

Συγκρίσεις

Η Python υποστηρίζει τους παρακάτω βασικούς τελεστές σύγκρισης:

Τελεστής Λειτουργία Περιγραφή
> "μεγαλύτερο από" a > b είναι True αν το a είναι αυστηρά μεγαλύτερο σε τιμή από το b
< "μικρότερο από" a < b είναι True αν το a είναι αυστηρά μικρότερο σε τιμή από το b
== "ίσο με" a == b είναι True αν το a είναι αυστηρά ίσο σε τιμή με το b
>= "μεγαλύτερο από ή ίσο με" a >= b είναι True αν a > b Ή a == b σε τιμή
<= "μικρότερο από ή ίσο με" a <= b είναι True αν a < b ή a == b σε τιμή
!= "δεν είναι ίσο με" a != b είναι True αν το a == b είναι False
is "ταυτότητα" a is b είναι True αν και μόνο αν τα a και b είναι το ίδιο αντικείμενο
is not "αρνημένη ταυτότητα" a is not b είναι True αν τα a και b είναι όχι το ίδιο αντικείμενο
in "έλεγχος περιεκτικότητας" a in b είναι True αν το a είναι μέλος, υποσύνολο ή στοιχείο του b
not in "αρνημένος έλεγχος περιεκτικότητας" a not in b είναι True αν το a δεν είναι μέλος, υποσύνολο ή στοιχείο του b

Έχουν όλοι την ίδια προτεραιότητα (η οποία είναι υψηλότερη από αυτή των πράξεων Boolean, αλλά χαμηλότερη από αυτή των αριθμητικών πράξεων ή των πράξεων bit).

Σύγκριση μεταξύ διαφορετικών τύπων δεδομένων

Αντικείμενα που είναι διαφορετικών τύπων (εκτός από τους αριθμητικούς τύπους) δεν συγκρίνονται ποτέ ως ίσα εξ ορισμού. Μη ταυτόσημα στιγμιότυπα μιας class επίσης δεν θα συγκριθούν ως ίσα, εκτός αν η class ορίζει ειδικές μεθόδους πλούσιας σύγκρισης που προσαρμόζουν την προεπιλεγμένη συμπεριφορά σύγκρισης του object. Η προσαρμογή μέσω rich comparisons θα καλυφθεί σε μια επόμενη άσκηση. Για (πολύ) περισσότερες λεπτομέρειες πάνω σε αυτό το θέμα, δες τις Συγκρίσεις τιμών στην τεκμηρίωση της Python.

Οι αριθμητικοί τύποι αποτελούν (ως επί το πλείστον) εξαίρεση σε αυτόν τον κανόνα αντιστοίχισης τύπων. Ένας integer μπορεί να θεωρηθεί ίσος με έναν float (ή ένας octal ίσος με έναν hexadecimal), αρκεί οι τύποι να μπορούν να μετατραπούν έμμεσα για τη σύγκριση.

Για τους υπόλοιπους αριθμητικούς τύπους στην τυπική βιβλιοθήκη της Python (μιγαδικοί, δεκαδικοί, κλάσματα), οι τελεστές σύγκρισης ορίζονται εκεί όπου "έχουν νόημα" (όπου η έμμεση μετατροπή δεν αλλάζει το αποτέλεσμα), αλλά πετούν ένα TypeError αν τα υποκείμενα αντικείμενα δεν μπορούν να μετατραπούν με ακρίβεια για σύγκριση. Για περισσότερες πληροφορίες σχετικά με τους κανόνες που χρησιμοποιεί η Python για τη μετατροπή αριθμητικών τύπων, δες τις αριθμητικές μετατροπές στην τεκμηρίωση της 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

Κάθε σύγκριση διάταξης ενός αριθμού με έναν τύπο NaN (όχι αριθμός) είναι False. Μια μπερδεμένη παρενέργεια του ορισμού του NaN στην Python είναι ότι το NaN δεν συγκρίνεται ποτέ ως ίσο με το NaN.

>>> x = float('NaN')

>>> 3 < x
False

>>> x < 3
False

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

Σύγκριση συμβολοσειρών

Σε αντίθεση με τους αριθμούς, οι συμβολοσειρές (str) συγκρίνονται λεξικογραφικά, χρησιμοποιώντας τα επιμέρους σημεία κώδικα Unicode (το αποτέλεσμα του περάσματος κάθε σημείου κώδικα της str στην ενσωματωμένη συνάρτηση ord(), η οποία επιστρέφει ένα int). Αν όλα τα σημεία κώδικα και στις δύο συμβολοσειρές ταιριάζουν και βρίσκονται στην ίδια σειρά, οι δύο συμβολοσειρές θεωρούνται ίσες. Αυτή η σύγκριση γίνεται με τρόπο "κατά ζεύγη": πρώτο με πρώτο, δεύτερο με δεύτερο κ.ο.κ. Στην Python 3.x, οι str και bytes δεν μπορούν να μετατραπούν ή να συγκριθούν άμεσα.

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

Αλυσιδωτές συγκρίσεις

Οι τελεστές σύγκρισης μπορούν να αλυσιδωθούν αυθαίρετα, δηλαδή μπορούν να χρησιμοποιηθούν σε οποιονδήποτε συνδυασμό και οποιουδήποτε μήκους. Σημείωσε ότι η αξιολόγηση μιας έκφρασης γίνεται από left προς right.

Ως παράδειγμα, το x < y <= z είναι ισοδύναμο με το x < y and y <= z, με τη διαφορά ότι το y αξιολογείται μόνο μία φορά. Και στις δύο περιπτώσεις, το z δεν αξιολογείται καθόλου όταν το x < y βρεθεί να είναι False. Αυτό συχνά ονομάζεται short-circuit evaluation: η αξιολόγηση σταματά αν η τιμή αλήθειας της έκφρασης έχει ήδη προσδιοριστεί.

Το Short circuiting υποστηρίζεται από διάφορους τελεστές Boolean, συναρτήσεις, αλλά και από τις αλυσιδωτές συγκρίσεις στην Python. Σε αντίθεση με πολλές άλλες γλώσσες προγραμματισμού, όπως οι C, C++, C# και Java, οι αλυσιδωτές εκφράσεις όπως η a < b < c στην Python έχουν μια συμβατική μαθηματική ερμηνεία και προτεραιότητα.

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

>>> x < y < z
True

>>> x < y > z
False

>>> x > y < z
False

Σύγκριση ταυτότητας αντικειμένων

Οι τελεστές is και is not ελέγχουν την ταυτότητα ενός αντικειμένου, σε αντίθεση με την τιμή του αντικειμένου. Η ταυτότητα ενός αντικειμένου δεν αλλάζει ποτέ μετά τη δημιουργία του και μπορεί να βρεθεί χρησιμοποιώντας τη συνάρτηση id().

Το <apple> is <orange> αξιολογείται σε True αν και μόνο αν id(<apple>) == id(<orange>). Το <apple> is not <orange> δίνει το αντίστροφο.

Λόγω της ιδιότητάς τους ως singleton, οι None και NotImplemented θα πρέπει πάντα να συγκρίνονται με άλλα στοιχεία χρησιμοποιώντας is και is not. Δες την τεκμηρίωση αναφοράς της Python για τις συγκρίσεις τιμών και το PEP8 για περισσότερες λεπτομέρειες σχετικά με αυτή τη σύμβαση.

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

Συγκρίσεις συμμετοχής

Οι τελεστές in και not in ελέγχουν τη συμμετοχή. Το <fish> in <soup> αξιολογείται σε True αν το <fish> είναι μέλος του <soup> (αν το <fish> είναι υποσύνολο του <soup> ή περιέχεται σε αυτό), και αξιολογείται σε False διαφορετικά. Το <fish> not in <soup> επιστρέφει την άρνηση, ή το αντίθετο του <fish> in <soup>.

Για τους τύπους συμβολοσειράς και bytes, το <name> in <fullname> είναι True αν και μόνο αν το <name> είναι υποσυμβολοσειρά του <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

Οδηγίες

Σε αυτή την άσκηση θα υλοποιήσεις μερικούς από τους κανόνες του Blackjack, όπως τον τρόπο που παίζεται και βαθμολογείται το παιχνίδι.

Σημείωση: Σε αυτή την άσκηση, το A σημαίνει άσο, το J σημαίνει βαλέ, το Q σημαίνει ντάμα και το K σημαίνει ρήγα. Οι τζόκερ αφαιρούνται. Υποθέτουμε μια τυπική τράπουλα 52 φύλλων με γαλλικά χρώματα, αλλά στις περισσότερες εκδοχές, αρκετές τράπουλες ανακατεύονται μαζί για το παιχνίδι.

1. Υπολόγισε την τιμή ενός φύλλου

Στο Blackjack, εξαρτάται από κάθε παίκτη αν ένας άσος αξίζει 1 ή 11 πόντους (περισσότερα γι' αυτό αργότερα). Τα φύλλα με φιγούρα (J, Q, K) βαθμολογούνται με 10 πόντους, ενώ κάθε άλλο φύλλο αξίζει την τιμή της «κουκκίδας» του (δηλαδή την αριθμητική του τιμή).

Όρισε τη συνάρτηση value_of_card(<card>) με παράμετρο card. Η συνάρτηση θα πρέπει να επιστρέφει την αριθμητική τιμή της συμβολοσειράς του φύλλου που δέχεται ως όρισμα. Επειδή ένας άσος μπορεί να πάρει πολλαπλές τιμές (1 ή 11), αυτή η συνάρτηση θα πρέπει, για την ώρα, να ορίζει την τιμή ενός άσου στο 1. Πιο μετά, θα υλοποιήσεις μια συνάρτηση που θα καθορίζει την τιμή ενός άσου, δεδομένου ενός υπάρχοντος χεριού.

>>> value_of_card('K')
10

>>> value_of_card('4')
4

>>> value_of_card('A')
1

2. Καθόρισε ποιο φύλλο έχει μεγαλύτερη τιμή

Όρισε τη συνάρτηση higher_card(<card_one>, <card_two>) με παραμέτρους card_one και card_two. Για τη βαθμολόγηση, η τιμή του J, του Q ή του K είναι 10. Η συνάρτηση θα πρέπει να επιστρέφει ποιο φύλλο έχει τη μεγαλύτερη τιμή για τη βαθμολόγηση. Αν και τα δύο φύλλα έχουν ίση τιμή, επέστρεψέ τα και τα δύο. Μπορείς να επιστρέψεις και τα δύο φύλλα χρησιμοποιώντας ένα κόμμα στην εντολή 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')

Ένας άσος μπορεί να πάρει πολλαπλές τιμές, οπότε για αυτό το βήμα θα ορίσουμε τα φύλλα A στην τιμή 1.

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

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

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

3. Υπολόγισε την τιμή ενός άσου

Όπως αναφέρθηκε προηγουμένως, ένας άσος μπορεί να αξίζει είτε 1 είτε 11 πόντους. Οι παίκτες προσπαθούν να πλησιάσουν όσο το δυνατόν περισσότερο στους 21 πόντους, χωρίς να ξεπεράσουν το 21 (δηλαδή να «σπάσουν»).

Όρισε τη συνάρτηση value_of_ace(<card_one>, <card_two>) με παραμέτρους card_one και card_two, που είναι δύο φύλλα που βρίσκονται ήδη στο χέρι πριν πάρεις άσο. Η συνάρτηση θα πρέπει να αποφασίσει αν ο άσος που έρχεται θα πάρει τιμή 1 ή τιμή 11 και να επιστρέψει αυτή την τιμή. Θυμήσου: η τιμή του χεριού με τον άσο πρέπει να είναι όσο το δυνατόν μεγαλύτερη, χωρίς να ξεπερνά το 21.

Υπόδειξη: αν έχουμε ήδη έναν άσο στο χέρι, τότε η τιμή για τον άσο που έρχεται θα ήταν 1.

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

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

4. Καθόρισε ένα «φυσικό» ή «Blackjack» χέρι

Αν ένας παίκτης πάρει έναν άσο (A) και ένα δεκάρι (10, K, Q ή J) ως τα δύο πρώτα του φύλλα, τότε ο παίκτης έχει σκορ 21. Αυτό είναι γνωστό ως χέρι blackjack.

Όρισε τη συνάρτηση is_blackjack(<card_one>, <card_two>) με παραμέτρους card_one και card_two, που είναι δύο φύλλα. Καθόρισε αν το χέρι των δύο φύλλων είναι blackjack και επέστρεψε τη boolean (λογική τιμή) True αν είναι, αλλιώς False.

Σημείωση: Ο υπολογισμός του σκορ μπορεί να γίνει με πολλούς τρόπους. Αλλά αν είναι δυνατόν, θα θέλαμε να ελέγξεις αν υπάρχει ένας άσος και ένα δεκάρι μέσα στο χέρι (ή σε μια συγκεκριμένη θέση), αντί να αθροίσεις τις τιμές του χεριού.

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

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

5. Χωρισμός ζευγαριών

Αν τα δύο πρώτα φύλλα ενός χεριού έχουν την ίδια τιμή (για παράδειγμα, δύο εξάρια ή ένα Q και ένα K), ο παίκτης μπορεί να επιλέξει να τα αντιμετωπίσει ως δύο ξεχωριστά χέρια. Αυτό είναι γνωστό ως «χωρισμός ζευγαριών».

Όρισε τη συνάρτηση can_split_pairs(<card_one>, <card_two>) με παραμέτρους card_one και card_two, που είναι δύο φύλλα. Καθόρισε αν αυτό το χέρι των δύο φύλλων μπορεί να χωριστεί σε δύο ζευγάρια. Αν το χέρι μπορεί να χωριστεί, επέστρεψε τη boolean (λογική τιμή) True, αλλιώς επέστρεψε False

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

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

6. Διπλασιασμός του πονταρίσματος

Όταν τα δύο αρχικά φύλλα που μοιράστηκαν έχουν σύνολο 9, 10 ή 11 πόντους, ο παίκτης μπορεί να τοποθετήσει ένα επιπλέον ποντάρισμα ίσο με το αρχικό του. Αυτό είναι γνωστό ως «διπλασιασμός του πονταρίσματος».

Όρισε τη συνάρτηση can_double_down(<card_one>, <card_two>) με παραμέτρους card_one και card_two, που είναι δύο φύλλα. Καθόρισε αν το χέρι των δύο φύλλων μπορεί να «διπλασιαστεί» και επέστρεψε τη boolean (λογική τιμή) True αν μπορεί, αλλιώς False.

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

>>> can_double_down('10', '2')
False
Επεξεργασία μέσω GitHub Ο σύνδεσμος ανοίγει σε νέο παράθυρο ή καρτέλα
Python Exercism

Έτοιμος να ξεκινήσεις την άσκηση Μπλακ Τζακ;

Γράψου στο Exercism για να μάθεις και να κατακτήσεις Python με 17 έννοιες146 ασκήσεις και πραγματική καθοδήγηση από ανθρώπους, όλα δωρεάν.