15-112 Fall 2014 Homework 8
Due Monday, 27-Oct, at 10pm
Read these instructions first!
- The first coding problem (Tetris), and only the first problem, on this hw is COLLABORATIVE. You may work in teams of up to 2 current 15-112 students on it. See below and also see the syllabus for more details.
- The first coding problem will be submitted as part of hw8c, in the file hw8c.py ("c" for Collaborative).
- Except for the first coding problem (Tetris), the rest of this hw is strictly SOLO, in the same way hw1-part2, hw2, and hw3 were, so you may not even discuss the problems with any other students or anyone except the course staff.
- The rest of this hw (except Tetris) will be submitted as hw8s, in the file hw8s.py ("s" for SOLO).
- This week, you may only make up to 5 submissions max to Autolab. As usual, only your last one counts.
-
Note: do not copy-paste basicAnimation.py or basicAnimationClass.py into your hw8 files. Instead, include the line:
from basicAnimationClass import BasicAnimationClass
Be sure to include that line below the #ignore_rest line so the autograder does not get confused. And be sure that both basicAnimation.py and basicAnimationClass.py are in the same folder as your hw8c.py file when you run it. We'll do the same when we run it. - Some hints and clarifications are included at the end of this document.
- 5-Minute TP Meetings [5pts] [manually graded] [SOLO]
By the hw8 deadline, everyone must have completed a 5-minute meeting (yes, just 5 minutes!) with one of the CA's from your assigned recitation, to begin a discussion about your term project ideas. This is very brief, just to be sure you've started thinking about TP's at least a bit. You do not have to prepare for these meetings, but it would be nice (and probably more effective) if you showed up with some ideas about what you might want to pursue. Also, at this point about half of you have already discussed your ideas with your CA or professor. Great! You still need to meet with your CA's. Perhaps the additional conversation may help give you even more cool ideas on how to pursue your project at this early stage.
Early in this hw cycle, you will receive an email from your CA's with instructions about how to sign up for these meetings. Be sure to sign up right away, and be sure to be on time to these meetings. And move quickly, since they will be kept to 5 minutes, for real. So you know: They are worth 5 points in hw8, and the only way to get the points is to be on time. If you are late, or if you miss the meeting, you will not get the points, even if you have a make-up meeting. Of course, this does not include students with hw8 extensions for university-approved conflicts, or documented medical emergencies, etc.
These meetings are only to help you. But you can help yourself, too. Look over the gallery a bit. Get an idea of what constitutes a term project. And start thinking about what you might be interested in.
Also, once you have an idea, the next step after this meeting is to start fleshing it out. First, poke around the web and find some related projects, and check out what they do well and what they do poorly (this is a required part of the TP, and you might as well do it now, since it's a nice way to help you organize your thinking). Also, think about the technologies or modules you might need, and start downloading and installing them and seeing if you can use them. This is also required: to use a technology or module, you will have to demonstrate basic proficiency with it prior to starting the actual term project (that is, right after the second midterm). So now is the time to play around with them and see where you get the most traction.
The hardest part of a TP for many students is Polya Step 1, choosing a good problem. And for that, time is your friend. So we are getting the TP clock ticking now, giving you the time you need to really blue-sky and innovate and dream up really fun, interesting, and doable projects.
What to submit?
For this problem, there is nothing to submit, as the CA's will record these meeting times and enter your grades accordingly. - Tetris [40pts] [manually graded]
[COLLABORATIVE]
This portion of hw8 is "hw8c", where the "c" means "Collaborative". This problem (Tetris), and only this problem, is optionally collaborative. You may work in groups of up to 2 currently enrolled 15-112 students (yourself included), so do not work with more than one other student. Each student should submit their own work individually, submitted as part of hw8c. Include the name and andrew id of your groupmate, if any, at the top of your hw8c.py file. And as always with collaborative work, you must be actively involved in every part of your solution, and you may never simply copy any code from anyone.
Tetris
Write Tetris according to the design given in this step-by-step tutorial except with these important changes:- Use BasicAnimationClass
This week we are adding classes/OOP to our MVC basic interactive graphics framework. You need to use this week's approach in hw8c. In particular, you need to create a subclass of BasicAnimationClass, called Tetris, as such:
And then your game needs to be run as such:class Tetris(BasicAnimationClass): # place your solution here!
tetris = Tetris(15, 10) # play Tetris on a 15x10 board # (must work for any reasonable dimensions) tetris.run()
- Ignore resizing the window
The writeup talks about calling root.resizable. Ignore this. And ignore how your app looks if it is resized. And then don't resize it! We won't, either. :-) - Use self.foo instead of canvas.data["foo"]
The Tetris tutorial uses a dictionary in canvas.data, like this: canvas.data["foo"]. You have to change this to use a Struct(), like this: canvas.data.foo. Actually, you need to do more -- you should not use canvas.data.foo at all, but instead you should follow our new OOP framework, and replace canvas.data.foo with self.foo. - Do not use a global canvas!
This is obvious! Globals are evil! And the tutorial uses a global canvas. Fortunately, if you use our MVC approach, you will not have a global canvas, so this is automatic. Just be sure to use no globals at all, not even canvas or app.
Except for these changes, you may not use a different design, even if you think there's a better way to do it (there probably is, but you still have to do it this way). This may seem limiting, but sometimes you are given specs at Polya Step 1 (just indicating the problem to solve), and other times at Polya Step 2 (also indicating the algorithms to use). This is one of those second kind of specs. Your task is to do Polya Step 3, and write the corresponding code, and then using this week's class-based MVC framework.
Have fun!!! - Use BasicAnimationClass
- Polynomial + Quadratic [30 pts] [autograded]
[SOLO]
This portion of hw8 is "hw8s", where the "s" means "SOLO". Submit this work in the file hw8s.py.
Do s14-hw9 #1 (Polynomial and Quadratic classes). Small point: note that when it says "determinant" it means "discriminant". Even so, match the spec exactly. - FarmGame [25 pts] [manually graded]
[SOLO]
Note: while this problem is part of hw8, it will be submitted along with hw9. So this problem, and only this problem, is due when the rest of hw9 is due. This is because it was released a bit late in the hw cycle. Even so, quiz8 will cover the ideas in this problem. So you should try to finish it by the hw8 deadline. But if you need more time, you can have it, all the way to the hw9 deadline.
So, remember: do not submit this with hw8. Submit this with hw9.
To showcase your OOP skills, write a very simple game, FarmGame, where you are a farmer with a 2d field of crops, which are represented in a 2d grid. You can choose to plant one of two different kinds of crops in each cell of the grid. For gameplay, you can either buy seeds for a crop, plant a crop, water a crop, do nothing, or eventually you can harvest a crop. When you harvest a crop, you get paid the market rate for it. To keep it interesting, one crop should be easy to grow quickly but is cheap in the market. The other crop should take longer to grow but should be more expensive. You do not need any images for the crops. They can just be colored squares or circles. Maybe make one crop green for instance, and the other one blue. And you need to visually convey how close a crop is to being ready for harvest. Maybe use shading for that, so when planted, the first crop is light green, and when ready for harvest, it is dark green (for this you'd probably want to use custom colors with rgbString, as described in our earlier notes on Graphics in Tkinter). In any case, And your game needs to be run as such:farmGame = FarmGame(15, 10) # play FarmGame on a 15x10 field of crops # (must work for any reasonable dimensions) farmGame.run()
You have lots of flexibility here. But you need to represent the crops as objects (either of a single Crop class, or as two individual classes, perhaps each subclassing a Crop class -- again, your choice). And you also need to represent the farmer or perhaps the farm as an object (tracking, for example, the current bank account balance, which goes down to buy seeds and water, but goes up when the harvest is sold). And you need a very simple UI, truly very simple, but one which provides the ability to play this very simple game, with no hidden state (so if you track the current bank account balance, display it somehow). Also, be sure to include a help screen which is visible when the player hits 'h' or '?'. And include a splash screen at the start which includes the game's name, your name, and tells the user to press 'h' or '?' for help, and maybe also says how to actually start playing the game (maybe press space or 'p' or some such).
Do not go overboard on this. Have fun and keep it simple. It is meant to showcase your understanding of OOP, and not to be a serious competitor to Farmville. - Bonus/Optional: BetterTetris [Up to 6 points] [manually graded]
[SOLO]
This goes in the SOLO portion of hw8, in the file hw8s.py, below the #ignore_rest line. For these problems, write BetterTetris. You may start by copy-pasting your Tetris code, but then all bonus work is SOLO. Place all your bonus features into the single BetterTetris game.
- Bonus: Piece Preview [1 pt] Add a piece preview, so you can see what the next piece the whole time the current piece is falling.
- Bonus: Piece Editor [2 pts] Add a piece editor, which is sort of like a bitmap editor, so you can edit a pattern that then gets added into the 3d list of pieces. The user (or, more specifically, the CA grading your submissions) should be able to easily see how to launch the piece editor, and then easily be able to test that future pieces include some that use that newly-created pattern.
- Bonus: Simple AI [up to 3 pts] Add some simple AI, so that when the user presses "a" it toggles AI mode on and off. When AI mode is on, the AI controls which keypress events to simulate. Of course, it should try to get as high a score as possible! Have fun!
Here are some hints and clarifications:
- Peer Tutors and Collaboration
To be clear: you may not collaborate with anyone except your one-and-only partner. Except, this week only: you may get some help from your peer-tutor. Be sure to indicate this with a citation at the top of your file. And... This help is limited to debugging and high-level discussion only. In particular, peer tutors may not write any code, not a line of code, for their peer-tutees. This is a one-time exception for only this week and only for Tetris. - Just one Tetris class
You should only have one class in your Tetris. This is just like what we did with Snake when converting it into our OOP-based MVC framework (see course notes for details). So Tetris not really completely object-oriented this week. So there's no separate object for the board, or for the falling piece, or anything else except the whole game. Actually, that's not true. A 2d list is in fact an object. As are integers. But those are objects using built-in classes. So, to be more precise, the only non-builtin-class you should write for Tetris is the entire app class, and then you'll create exactly one instance when you play the game. - Polynomial Starter Code
This problem refers to some starter code, which was covered briefly in lecture last semester. You can find this in last semester's lecture notes here. You may copy-paste this code from the course website to get started, but if you do that, be certain first to throughly study and understand the code! See how it stores the coefficients of a Polynomial in self.coeff, so if coeffs == [2,-3,5], then the Polynomial being represented is 2x**2-3*x+5. - Polynomial and Quadratic Required Methods
Including the methods we already provided for you above, here are some of the methods you'll probably want to include in your solution (though of course you may include other methods, and also more helper methods if you wish):class Polynomial(object): def __init__(self, *coeffs): def firstNonZeroCoeff(self, coeffs): def degree(self): def coeff(self, power): def evalAt(self, x): def __add__(self, other): def __mul__(self, other): def __rmul__(self, other): def __pow__(self, power): def derivative(self): def __str__(self): def __repr__(self): def __eq__(self, other): def __hash__(self): class Quadratic(Polynomial): def __init__(self, *coeffs): def determinant(self): def numberOfRealRoots(self): def getRealRoots(self):
- A simple hash Method
You do not have to write hash this week, so here is an overly-simplistic yet functional hash method for you (just copy-paste this into your code):def __hash__(self): # this is quick and dirty, but works return hash(str(self))
- Variable-length parameters (*args)
To create the constructor for Polynomial, you will have to use *args. We did not cover this in lecture (life in intermediate courses...). When you use *args, Python places all the remaining arguments into a tuple and sets the parameter "args" to reference that tuple. Consider this:
See how the first call has only one parameter, and the second one has two parameters? Cool.def f(*args): print "in f, args =", args Then: # f(5) prints: in f, args = (5) # f(5,"wow") prints: in f, args = (5, 'wow')
Thus, you can do something like this in class Polynomial:
Hope this helps!def __init__(self, *coeffs): if len(coeffs) == 0: # check for empty tuple () # do something elif ((type(coeffs[0]) == tuple) or # if ceoffs given as a list/tuple (type(coeffs[0]) == list)): # do something else...