# Introduction to Computer Programming: Lab 10

## Classes and objects

### Instructions

• Work on this lab with your partner (or on your own if you have not been assigned one).

• Work with the supplied starter file.

• You are welcome to download a runnable solution module called `lab10x`.

• If you do not have time to complete the exercises during the scheduled time then you should finish them on your own.

### Exercises

1. Read over the starter file, particularly the first part that shows the `Counter` class. Experiment in the shell with constructing counters, reading their values and incrementing them like this:

``````>>> c = Counter()
>>> d = Counter()
0
0
>>> c.inc()
1
0
...``````
2. Add a `reset` method to the `Counter` class that resets the counter to 0:

``````>>> c = Counter()
>>> c.inc()
>>> c.inc()
2
>>> c.reset()
0``````
3. Add an optional argument `initial_value` to the `Counter` constructor (its `__init__` method) so that counters can be constructed to start at `initial_value` (which should default to zero) as in:

``````>>> c = Counter()
0
>>> d = Counter(4103)
4103``````

"Record" `initial_value` in the object that is constructed and modify `reset` so that it resets the counter to its initial value:

``````>>> c = Counter(99)
>>> c.inc()
100
>>> c.reset()
99``````
4. Add a method `is_cleared` that returns `True` if the counter is at its initial value:

``````>>> c = Counter(53)
>>> c.is_cleared()
True
>>> c.inc()
>>> c.is_cleared()
False
>>> c.reset()
>>> c.is_cleared()
True``````
5. Add a method `add` that takes an argument `other_counter` and adds the value of `other_counter` to this counter:

``````>>> c = Counter(37)
>>> d = Counter(43)
43
80
>>> c.reset()
37``````

6. [Courtesy of Jim Marshall] Design and implement a `Card` class to represent playing cards. Your `Card` constructor (its `init` method) should take two parameters (beyond `self`): a number from 2 to 14 representing the card's rank (with 11=Jack, 12=Queen, 13=King, and 14=Ace), and another number from 0 to 3 representing the suit (0=Clubs, 1=Diamonds, 2=Hearts, 3=Spades). `Card` objects should have the following methods:

• `get_rank(self)` which returns the rank as a string: either a one-digit string from `'2'` to `'9'`, or, `'Ten'`, `'Jack'`, `'Queen'`, `'King'`, or `'Ace'`.

• `get_suit(self)` which returns the suit: `'Clubs'`, `'Diamonds'`, `'Hearts'`, or `'Spades'`.

• `__str__(self)` which returns a string description of the card of the form `'2 of Clubs'`, `'Ace of Spades'`, etc.

• `trumps(self, other_card)` which returns `True` if this card has a higher rank than `other_card`.

You can test your class and its instances in the shell. For example:

``````    >>> qh = Card(12, 2)
>>> jd = Card(11, 1)
>>> c2 = Card(2, 0)
>>> qh.get_rank()
'Queen'
>>> jd.get_suit()
'Diamonds'
>>> print(c2)
2 of Clubs
>>> jd.trumps(qh)
False
>>> qh.trumps(jd)
True
>>> c2.trumps(c2)
False``````

If examples like those work, try using it via the supplied `war()` function.

7. Examine the code in the final section of the starter file. Create a class `Hopper` (somewhat similar to the `Thingy` class we defined in lecture) that offers a constructor and methods `hop`, `is_reset`, and `undo` that are consistent with the way they are used by the `add`, `hop`, `undo`, and `reset` functions that are triggered by click and key events. Each time a hopper hops, it should record its former position on the end of its queue (which should be a Python list; use the `append` method for lists). A hopper's `undo` method should put the hopper back at its last position (and remove that position) from its queue (use `pop`). `is_reset` returns `True` if the hopper's queue is empty.

The supplied `go` function should create a `square_graphics` window such that a new `Hopper` appears where the user clicks. 'h' should make all Hoppers hop up to one space in both the vertical and horizontal directions. 'u' should undo: all Hoppers should hop back to their previous location. 'r' should reset: all Hoppers should hop back, one hop at a time, all the way to their starting location.

For this problem you should place a copy of the `square_graphics` module in your working folder.

#### Time permitting

• Add a new key event that removes any hoppers (from the global `hoppers` set) that are reset.

• Add a timer to make hoppers hop every second.

• Add code to support the idea that if the user clicks on a square where a hopper currently resides, that hopper is removed from the global `hoppers` set (and, in that case, no new `Hopper` is created).

• Add methods to `Card` to compare a card to another card to support "bridge order" (all clubs come before all diamonds before all hearts before all spades; and within the same suit two is smallest, Ace is largest). Add a method that builds a 2-character string representation of a card that is suit then rank, as in: 'SA' (for Spade Ace) 'HT' (for Heart Ten), 'DJ' (for Diamond Jack), 'C3' (for Club 3), etc. Experiment with using the `sorted` function to write a class `Hand` that consists of zero or more Cards, where the string representation uses the usual long form ('Ace of Diamonds', etc.) but that the order is in bridge order. To facilitate doing this, you can add a method to `Deck` called `deal_many(self, n)` that, assuming at least `n` cards remain in the deck, returns a `Hand` of the next `n` cards in the deck.