Preparation

a. Create a folder called lab-02-20 in your StuWork directory.

b. Open a Terminal and navigate to your lab-02-20 directory.

c. Create a file named classes.py and put all of the code from it today in there.

Exercise 1

Recall that in the textbook, we created a class to model a multi-sided die. The code for the class is below.

from random import randrange

class MSDie:

    def __init__(self, sides):
        self.sides = sides
        self.value = 1

    def roll(self):
        self.value = randrange(1, self.sides+1)

    def getValue(self):
        return self.value

    def setValue(self, value):
        self.value = value

a. Before we experiment with the code, let’s play with the randrange function. Open up a REPL environment and run the following.

>>> from random import randrange
>>> randrange(0, 5)

b. Try repeatedly typing randrange(0, 5) to see what it generates. Does it ever generate the number 0? What about 5?

c. Try changing the parameters to other numbers to make sure you understand what it is doing.

d. Look at the roll() method of the MSDie class. Why are the parameters to randrange 1 and self.sides+1? Discuss this with your partner.

e. Create a main() function in your classes.py file that creates two six-sided dice, rolls them, and prints off their individual values and their sum.

Exercise 2

Below is a partial implementation of a Rectangle class that contains two instance variables: width and height.

class Rectangle:

    def __init__(self, width, height):
        self.width = width
        self.height = height

    def getWidth(self):
        # Not yet implemented

    def getHeight(self):
        # Not yet implemented

    def getArea(self):
        # Not yet implemented

    def getPerimeter(self):
        # Not yet implemented

a. Copy and paste this class definition into your classes.py file.

b. Finish implementing the getWidth() and the getHeight() methods. Test that you can create objects of type Rectangle and get back their width and height components by updating your main() function, creating a few objects, and printing their width and height.

c. Finish implementing the getArea() and the getPerimeter() methods which return the area of the rectangle and the perimeter of the rectangle. Be sure to test them in your main() function and by running it via the terminal!

Exercise 3

Sometimes we want to track where a rectangle is located. If a rectangle is located at the point (x,y), we usually mean its upper left corner is at (x,y).

a. Add two more instance variables to the Rectangle class called x and y and update the constructor to take in the initial values of x and y.

b. Add methods getX() and getY() that return the values of these variables.

c. Test your updates in your main() function.

Exercise 4

It is sometimes useful to check if two rectangles are overlapping. Write a a method inside the Rectangle classes called overlapping(rect) that takes a single object of type Rectangle as a parameter and returns True if the rectangle rect is overlapping this rectangle and False otherwise. (Remember that you need to include the self parameter in the method definition and that you can use it to get the width and height of the self object.)

For example, here are a few examples of executing the method.

r1 = Rectangle(0, 50, 100, 50)      # x=0, y=50, width = 100, height = 50
r2 = Rectangle(25, 25, 50, 50)      # x=25, y=25, width=50, height=50
r3 = Rectangle(0, 100, 25, 25)      # x=0, y=100, width=25, height=25

print(r1.overlapping(r2))   # Prints True since they are overlapping
print(r2.overlapping(r3))   # Prints False since they are not

It may be helpful drawing the rectangles to see why they are overlapping or not overlapping to figure out how to write this method.

Exercise 5

Suppose we were tasked by Carleton to rewrite the course management system. Thus, we need to write software that allows students to register for courses but not exceed course enrollments, etc. Our software should also be verifying that prerequisites have been taken before allowing students to register, etc.

a. To help with our course management program, we decide to create some intuitive classes called Student and Course. Brainstorm with your partner what would be appropriate instance variables (i.e. data that each class encapsulates) and what would be intuitive methods (i.e. operations) that each class should have. Make a list.

b. Work on implementing your Student class with whatever instance variables you chose. You might choose only a subset of the features you identified in part a such as name, student ID, current year, etc.

c. Work on implementing your Course class with whatever instance variables you chose. You might include a title, description, capacity, currently enrolled students, credits, etc.

d. Now that you have a Course class, you could consider adding more features to your Student class like a list of courses the student is taking, or a list of courses the students have already taken to be able to check prerequisites correctly.

You do not need to implement an entire course management system in this exercise! The point is just to brainstorm how we might encapsulate information and how classes might interact with one another in a larger program. The goal is for each class to contain useful information and be intuitive for a human to use.