Create a subfolder called lab11
within your
cs111
folder, and put all of the files for this lab in that
folder.
Card
objectsTo implement a card game, one type of object that would be useful is an object that represents an individual card from a deck of cards.
Begin by downloading
card.py,
saving it in your lab11
folder.
Open the file in Spyder. You’ll see that we’ve begun to define a
class called Card
that will serve as a blueprint for a single
playing card.
Each Card
object has two attributes:
rank
, which is either an int
(for numeric cards) or a
single upper-case letter (for Aces and for face cards like Queens)suit
, which is stored as a single upper-case letter
('C'
for Clubs, 'S'
for Spades, 'H'
for Hearts,
and 'D'
for Diamonds)For example, here’s one way to picture what a Card
object
representing the 4 of Clubs would look like in memory:
+----------------+ | +-----+ | | rank | 4 | | | +-----+ | | +-----+ | | suit | 'C' | | | +-----+ | +----------------+
And here’s a picture of a Card
object representing the Queen of
Diamonds:
+----------------+ | +-----+ | | rank | 'Q' | | | +-----+ | | +-----+ | | suit | 'D' | | | +-----+ | +----------------+
Locate the constructor that we’ve provided for Card
objects.
Notice how it uses the type()
function to determine what to do
with the value passed in for rank
:
If the value of rank
is an int
, it simply stores that
integer value in the rank
attribute (self.rank
).
Otherwise, it assumes that the value passed in for rank
is a
string, and it uses string indexing and the upper()
method
to ensure that the value stored in the suit
attribute is a
single upper-case character.
The constructor also converts the value passed in for suit
(which we assume is a string) to a single upper-case letter.
Run card.py
in Spyder, and enter these statements in the console:
>>> c1 = Card(4, 'C') >>> c1.rank result: 4 >>> c1.suit result: 'C' >>> c2 = Card('queen', 'diamonds') >>> c2.rank result: 'Q' >>> c2.suit result: 'D'
We’ve also given you an initial version of a __repr__
method
for converting a Card
object to a string. It simply constructs
a string consisting of the rank
and suit
, separated by a space:
>>> c2 = Card('Q', 'D') >>> c2 Q D
Although it makes sense to only store a single character for a Card
object’s rank and suit, we’d like the string representation of the
of the object to be more descriptive.
If you look at the top of the file, you’ll see that we’ve given you the following lines of code:
RANK_NAMES = {'A': 'Ace', 'J': 'Jack', 'Q': 'Queen', 'K': 'King'} SUIT_NAMES = {'C': 'Clubs', 'S': 'Spades', 'H': 'Hearts', 'D': 'Diamonds'}
Since we’re putting these lines in the global scope, the variables
RANK_NAMES
and SUIT_NAMES
are global variables (variables that
can be accessed from anywhere in the file), and we’re capitalizing
their names to indicate that fact.
Both of these variables represent dictionaries:
RANK_NAMES
is a dictionary that connects each non-numeric rank
to a more descriptive string for that rank. For example,
it connects the rank 'A'
to the string 'Ace'
.
SUIT_NAMES
is a dictionary that connects each suit character
to a more descriptive string for that suit. For example,
it connects the suit 'C'
to the string 'Clubs'
.
Remember that a dictionary is a set of key-value pairs, and that you can use the key as an index to obtain the value associated with the key. For example:
>>> RANK_NAMES['A'] result: 'Ace' >>> SUIT_NAMES['C'] result: 'Clubs'
Modify the __repr__
method so that it uses these
dictionaries to create and return a string of the form
'
rank-name of
suit-name'
. For example:
>>> c2 = Card('Q', 'D') >>> c2 result: Queen of Diamonds
If the called object’s rank
is of type int
, you should simply
convert it to a string, as we do in the initial __repr__
. Otherwise,
you should use the RANK_NAMES
dictionary to look up the descriptive
name associated with the object’s rank
.
Similarly, you should use the SUIT_NAMES
dictionary to look up the
descriptive name associated with the object’s suit
.
Examine the method called get_value()
in card.py
.
It returns the value of the called Card
object. More specifically:
Card
object has a numeric rank
, it returns the rank
This follows the common convention of giving all face cards a value of 10.
For example:
>>> c1 = Card(4, 'C') >>> c1.get_value() result: 4 >>> c2 = Card('queen', 'diamonds') >>> c2.get_value() result: 10
The current version of get_value()
also gives Aces a value of 10.
Modify the method so that it gives Aces a value of 1 instead:
>>> c3 = Card('A', 'S') >>> c3 result: Ace of Spades >>> c3.get_value() result: 1
Hand
objectsNext, we’ll consider another type of object that would be useful when implementing a card game.
Begin by downloading the following files:
Make sure to save both files in your lab11
folder, and open
them in Spyder.
In hand.py
, we’ve begun to define a class
called Hand
that will serve as a blueprint for objects
that represent a single hand of cards.
Each Hand
object has a single attribute called cards
that
is initially an empty list. As Card
objects are added to the
Hand
using the add_card()
method, they are concentenated to
the end of this list.
In addition, there is a method called num_cards
that can be used
for obtaining the number of cards in the called Hand
object.
After reviewing and understanding the Hand
class, add client
code to lab11_client.py
to accomplish the tasks listed
below.
Create two Card
objects:
c1
c2
Create a single Hand
object and assign it to a variable h1
.
Use the add_card()
method to add both of the Card
objects
to h1
. You will need to call the method twice, once for
each Card
.
Print h1
as follows:
print('first hand:', h1)
Print the string 'number of cards:'
, followed by the value
obtained by calling the num_cards()
method on h1
.
Run lab11_client.py
, and you should see the following output:
first hand: [7 of Hearts, Ace of Diamonds] number of cards: 2
As part of the Hand
class, add a method called get_value()
that returns the total value of the cards in the called Hand
object (self
). Make sure to indent it under the class header.
You will need to perform a cumulative computation, and you should
use the Card
version of the get_value()
method to determine
the individual value of each Card
object in the Hand
.
To test your new method, add the following line to the end of your client code:
print('total value:', h1.get_value())
Rerun the program, and you should now see:
first hand: [7 of Hearts, Ace of Diamonds] number of cards: 2 total value: 8
As part of the Hand
class, add a method called has_any()
that
takes a card rank as its only input, and that returns True
if
there is at least one occurrence of a Card
with that rank in the
called Hand
object (self
), and that returns False
if there are
no occurrences of that rank in the Hand
. (Note that the suits of
the Card
objects don’t matter in this method; we’re only looking
at their ranks.)
To test your new method, add the following lines to the end of your client code:
print('has at least one 7:', h1.has_any(7)) print('has at least one Ace:', h1.has_any('A')) print('has at least one Queen:', h1.has_any('Q'))
Rerun the program, and you should now see:
first hand: [7 of Hearts, Ace of Diamonds] number of cards: 2 total value: 8 has at least one 7: True has at least one Ace: True has at least one Queen: False
Last updated on November 18, 2024.