Coursera RU Fundamentals of Computing Specialization

For quick search
Coursera can be found here

This Specialization covers much of the material that first-year Computer Science students take at Rice University. Students learn sophisticated programming skills in Python from the ground up and apply these skills in building more than 20 fun projects. The Specialization concludes with a Capstone exam that allows the students to demonstrate the range of knowledge that they have acquired in the Specialization.

An Introduction to Interactive Programming in Python (Part 1)

Lecture slides can be found here
Coursera can be found here
youtube link

About this course: This two-part course is designed to help students with very little or no computing background learn the basics of building simple interactive applications. Our language of choice, Python, is an easy-to learn, high-level computer language that is used in many of the computational courses offered on Coursera. To make learning Python easy, we have developed a new browser-based programming environment that makes developing interactive applications in Python simple. These applications will involve windows whose contents are graphical and respond to buttons, the keyboard and the mouse.

In part 1 of this course, we will introduce the basic elements of programming (such as expressions, conditionals, and functions) and then use these elements to create simple interactive applications such as a digital stopwatch. Part 1 of this class will culminate in building a version of the classic arcade game “Pong”.

Who is this class for: Recommended Background - A knowledge of high school mathematics is required. The class is designed for students with no prior programming experience.

Week 1 Statements, expressions, variables

Understand the structure of this class, explore Python as a calculator

Week 0a - Expressions

Introduction14 min

CodeSkulptor11 min

Arithmetic Expressions13 min

Practice Exercises for Expressions (optional)10 min

Week 0b - Variables and Assignments

Variables11 min

Saving in CodeSkulptor9 min

Practice Exercises for Variables and Assignments (optional)10 min

Quiz: Quiz 0 10 questions

QUIZ
Quiz 0
10 questions
To Pass70% or higher
Attempts3 every 8 hours
Deadline
October 22, 11:59 PM PDT

1 point
1.Which of the following are syntactically correct strings?

Try each of them in CodeSkulptor.




1 point
2.To display a value in the console, what Python keyword do you use?




1 point
3.In the following code, there is one line starting with $$\color{red}{\verb|#|}$$. What does this line mean to Python?

1
2
3
4
5
6
tax_rate = 0.15
income = 40000
deduction = 10000
# Calculate income taxes
tax = (income - deduction) * tax_rate
print tax




1 point
4.Which of the following arithmetic expressions are syntactically correct?

Try each of them in CodeSkulptor.




1 point
5.You would like to make it so that the variable $$\color{red}{\verb|ounces|}$$ has the value 16, thus representing one pound. What simple Python statement will accomplish this?




1 point
6.A gram is equal to 0.035274 ounces. Assume that the variable $$\color{red}{\verb|mass_in_ounces|}$$ has a value representing a given mass in ounces. Which Python statement below uses the variable $$\color{red}{\verb|mass_in_ounces|}$$ to compute an equivalent mass $$\color{red}{\verb|mass_in_grams|}$$ expressed in grams?

Think about it mathematically, but also test these expressions in CodeSkulptor3. If you are still confused, you might check out this student tutorial video by Kelly on unit conversions.




1 point
7.Which of the following can be used as a variable name?

Try using each in CodeSkulptor.




1 point
8.Assume you have values in the variables $$\color{red}{\verb|x|}$$ and $$\color{red}{\verb|y|}$$. Which statement(s) would result in $$\color{red}{\verb|x|}$$ having the sum of the current values of $$\color{red}{\verb|x|}$$ and $$\color{red}{\verb|y|}$$?

Test your answer in CodeSkulptor.




1 point
9.Python file names traditionally end in what characters after a period? Don’t include the period.




1 point
10.We encourage you to save your CodeSkulptor Python files where?



Mini-project #0 - “We want… a shrubbery!” (optional)

Mini-project Video10 min

Mini-project Description10 min

Mini-project development process

Your task is simple: modify this program template to print

1
We want... a shrubbery!

in the CodeSkulptor console. Your program should consist of a single line of Python. Before submitting your program, we suggest that you review the grading rubric given below.

Code Clinic Tips10 min

Practice Peer-graded Assignment: “We want… a shrubbery!”2h

url can be found here

Week 2 Week 1 - Functions, logic, conditionals

Learn the basic constructs of Python programming, create a program that plays a variant of Rock-Paper-Scissors

Week 1a - Functions

Functions15 min

http://www.codeskulptor.org/#examples-functions.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# computes the area of a triangle
def triangle_area(base, height): # header - ends in colon
area = (1.0 / 2) * base * height # body - all of body is indented
return area # body - return outputs value
a1 = triangle_area(3, 8)
print a1
a2 = triangle_area(14, 2)
print a2
# converts fahrenheit to celsius
def fahrenheit2celsius(fahrenheit):
celsius = (5.0 / 9) * (fahrenheit - 32)
return celsius
# test!!!
c1 = fahrenheit2celsius(32)
c2 = fahrenheit2celsius(212)
print c1, c2
# converts fahrenheit to kelvin
def fahrenheit2kelvin(fahrenheit):
celsius = fahrenheit2celsius(fahrenheit)
kelvin = celsius + 273.15
return kelvin
# test!!!
k1 = fahrenheit2kelvin(32)
k2 = fahrenheit2kelvin(212)
print k1, k2
# prints hello, world!
def hello():
print "Hello, world!"
# test!!!
hello() # call to hello prints "Hello, world!"
h = hello() # call to hello prints "Hello, world!" a second time
print h # prints None since there was no return value
1
2
3
4
5
6
7
12.0
14.0
0.0 100.0
273.15 373.15
Hello, world!
Hello, world!
None

Visualizing Functions12 min

http://www.codeskulptor.org/#examples-functions.py

1
2
3
4
5
6
7
8
def f(i,I=[]):
for j in range(i):
I.append(j)
return I
print f(3)
print f(2,[4,5])
print f(4)
1
2
3
[0, 1, 2]
[4, 5, 0, 1]
[0, 1, 2, 0, 1, 2, 3]

More Operations17 min

http://www.codeskulptor.org/#examples-more_operations.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# Remainder - modular arithmetic
# systematically restrict computation to a range
# long division - divide by a number, we get a quotient plus a remainder
# quotient is integer division //, the remainder is % (Docs)
# problem - get the ones digit of a number
num = 49
tens = num // 10
ones = num % 10
print tens, ones
print 10 * tens + ones, num
# application - 24 hour clock
# http://en.wikipedia.org/wiki/24-hour_clock
hour = 20
shift = 8
print (hour + shift) % 24
# application - screen wraparound
# Spaceship from week seven
width = 800
position = 797
move = 5
position = (position + move) % width
print position
# Data conversion operations
# convert an integer into string - str
# convert an hour into 24-hour format "03:00", always print leading zero
hour = 3
ones = hour % 10
tens = hour // 10
print tens, ones, ":00"
print str(tens), str(ones), ":00"
print str(tens) + str(ones) + ":00"
# convert a string into numbers using int and float
# Python modules - extra functions implemented outside basic Python
import simplegui # access to drawing operations for interactive applications
import math # access to standard math functions, e.g; trig
import random # functions to generate random numbers
# look in Docs for useful functions
print math.pi

1
2
3
4
5
6
7
8
4 9
49 49
4
2
0 3 :00
0 3 :00
03:00
3.14159265359

Practice Exercises for Functions (optional)10 min

Week 1b - Logic and Conditionals

Logic and Comparisons10 min

Conditionals10 min

http://www.codeskulptor.org/#examples-conditionals.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def greet(friend, money):
if friend and (money > 20):
print "Hi!"
money = money - 20
elif friend:
print "Hello"
else:
print "Ha ha"
money = money + 10
return money
money = 15
money = greet(True, money)
print "Money:", money
print ""
money = greet(False, money)
print "Money:", money
print ""
money = greet(True, money)
print "Money:", money
print ""
1
2
3
4
5
6
7
8
Hello
Money: 15
Ha ha
Money: 25
Hi!
Money: 5

http://www.codeskulptor.org/#examples-leap_year.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Conditionals Examples
# Return True if year is a leap year, false otherwise
def is_leap_year(year):
if (year % 400) == 0:
return True
elif (year % 100) == 0:
return False
elif (year % 4) == 0:
return True
else:
return False
year = 2012
leap_year = is_leap_year(year)
if leap_year:
print year, "is a leap year"
else:
print year, "is not a leap year"

Programming Tips - 116 min

http://www.codeskulptor.org/#examples_tips1.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
############
# This is a compilation of the examples from Week 1's Programming Tips.
# Many of these functions have errors, so this file won't run as is.
############
import math
############
# Has multiple NameErrors
def volume_cube(side):
return sidde ** 3
s = 2
print "Volume of cube with side", s, "is", volume(s), "."
############
# Has a NameError
def random_dice():
die1 = random.randrange(1, 7)
die2 = random.randrange(1, 7)
return die1 + die2
print "Sum of two random dice, rolled once:", random_dice()
print "Sum of two random dice, rolled again:", random_dice()
print "Sum of two random dice, rolled again:", random_dice()
############
# Has an AttributeError
def volume_sphere(radius):
return 4.0/3.0 * math.Pi * (radius ** 3)
r = 2
print "Volume of sphere of radius", r, "is", volume_sphere(r), "."
############
# Has multiple TypeErrors
def area_triangle(base, height):
return 0.5 * base * height
b = "5"
h = "2 + 2"
print "Area of triangle with base", b, "and height", h, "is", area_triangle(b), "."
############
# Has multiple SyntaxErrors
def is_mary(x)
if x = "Mary":
print "Found Mary!"
else:
print "No Mary."
is_mary(Mary)
is_mary(Fred)
############
# Poor readability
def area(a,b,c):
s = (a+b+c)/2.0
return math.sqrt(s*(s-a)*(s-b)*(s-c))
############
# Improved readability
def area_triangle_sss(side1, side2, side3):
"""
Returns the area of a triangle, given the lengths of
its three sides.
"""
# Use Heron's formula
semiperim = (side1 + side2 + side3) / 2.0
return math.sqrt(semiperim *
(semiperim - side1) *
(semiperim - side2) *
(semiperim - side3))
base = 3
height = 4
hyp = 5
print "Area of triangle with sides", base, height, hyp, "is", area_triangle_sss(base, height, hyp), "."
############
# Could use error-checking of input value
def favorites(instructor):
"""Return the favorite thing of the given instructor."""
if instructor == "Joe":
return "games"
elif instructor == "Scott":
return "ties"
elif instructor == "John":
return "outdoors"
print favorites("John")
print favorites("Jeannie")

Practice Exercises for Logic and Conditionals (optional)10 min

Quiz: Quiz 110 questions

QUIZ
Quiz 1
10 questions
To Pass70% or higher
Attempts3 every 8 hours
Deadline
October 29, 11:59 PM PDT

1 point
1.An if statement can have at most how many else parts?


Unlimited, i.e., 0 or more




1 point
2.Consider the Boolean expression not (p or not q). Give the four following values in order, separated only by spaces:

the value of the expression when p is True, and q is True,

the value of the expression when p is True, and q is False,

the value of the expression when p is False, and q is True,

the value of the expression when p is False, and q is False,

Remember, each of the four results you provide should be True or False with the proper capitalization.




1 point
3.A common error for beginning programmers is to confuse the behavior of print statements and return statements.

print statements can appear anywhere in your program and print a specified value(s) in the console. Note that execution of your Python program continues onward to the following statement. Remember that executing a print statement inside a function definition does not return a value from the function.
return statements appear inside functions. The value associated with the return statement is substituted for the expression that called the function. Note that executing a return statement terminates execution of the function definition immediately. Any statements in the function definition following the return statement are ignored. Execution of your Python code resumes with the execution of the statement after the function call.
As an example to illustrate these points, consider the following piece of code:

1
2
3
4
5
def do_stuff():
print "Hello world"
return "Is it over yet?"
print "Goodbye cruel world!"
print do_stuff()

Note that this code calls the function do_stuff in the last print statement. The definition of do_stuff includes two print statements and one return statement.

Which of the following is the console output that results from executing this piece of code? While it is trivial to solve this question by cutting and pasting this code into CodeSkulptor, we suggest that you first attempt this problem by attempting to execute this code in your mind.

1
2
3
4
Hello world
Is it over yet?
Goodbye cruel world!
Is it over yet?

1
Hello world

1
2
3
Hello world
Is it over yet?
Goodbye cruel world!

1
2
Hello world
Is it over yet?




1 point
4.Given a non-negative integer n, which of the following expressions computes the ten’s digit of n? For example, if n is 123, then we want the expression to evaluate to 2.

Think about each expression mathematically, but also try each in CodeSkulptor.




1 point
5.The function calls random.randint(0, 10) and random.randrange(0, 10) generate random numbers in different ranges. What number can be generated by one of these functions, but not the other?

(Refer to the CodeSkulptor documentation.)

By the way, we (and most Python programmers) always prefer to use random.randrange() since it handles numerical ranges in a way that is more consistent with the rest of Python.




1 point
6.Implement the mathematical function f(x)=−5x5+69x2−47 as a Python function. Then use Python to compute the function values f(0), f(1), f(2), and f(3). Enter the maximum of these four values calculated.




1 point
7.When investing money, an important concept to know is compound interest.

The equation FV=PV(1+rate)periods relates the following four quantities.

The present value (PV) of your money is how much money you have now.
The future value (FV) of your money is how much money you will have in the future.
The nominal interest rate per period (rate) is how much interest you earn during a particular length of time, before accounting for compounding. This is typically expressed as a percentage.
The number of periods (periods) is how many periods in the future this calculation is for.
Finish the following code, run it, and submit the printed number. Provide at least four digits of precision after the decimal point.

1
2
3
4
5
6
7
8
def future_value(present_value, annual_rate, periods_per_year, years):
rate_per_period = annual_rate / periods_per_year
periods = periods_per_year * years
rate = rate_per_period
# Put your code here.
return present_value * (1 + rate)**periods
print "$1000 at 2% compounded daily for 3 years yields $", future_value(1000,.02, 365, 3)

Before submitting your answer, test your function on the following example.

future_value(500, .04, 10, 10) should return 745.317442824




1 point
8.There are several ways to calculate the area of a regular polygon. Given the number of sides, n, and the length of each side, s, the polygon’s area is

ns24tan(πn)
For example, a regular polygon with 5 sides, each of length 7 inches, has area 84.3033926289 square inches.

Write a function that calculates the area of a regular polygon, given the number of sides and length of each side. Submit the area of a regular polygon with 7 sides each of length 3 inches. Enter a number (and not the units) with at least four digits of precision after the decimal point.

Note that the use of inches as the unit of measurement in these examples is arbitrary. Python only keeps track of the numerical values, not the units.




1 point
9.Running the following program results in the error

SyntaxError: bad input on line 8 (‘return’).

Which of the following describes the problem?

1
2
3
4
5
6
7
def max_of_2(a, b):
if a > b:
return a
else:
return b
def max_of_3(a, b, c):
return max_of_2(a, max_of_2(b, c))




1 point
10.The following code has a number of syntactic errors in it. The intended math calculations are correct, so the only errors are syntactic. Fix the syntactic errors.

Once the code has been fully corrected, it should print out two numbers. The first should be 1.09888451159. Submit the second number printed in CodeSkulptor. Provide at least four digits of precision after the decimal point.

1
2
3
4
5
define project_to_distance(point_x point_y distance):
dist_to_origin = math.square_root(pointx ** 2 + pointy ** 2)
scale == distance / dist_to_origin
print point_x * scale, point_y * scale
project-to-distance(2, 7, 4)
1
2
3
4
5
def project_to_distance(point_x, point_y, distance):
dist_to_origin = math.sqrt(point_x ** 2 + point_y ** 2)
scale = distance / dist_to_origin
print point_x * scale, point_y * scale
project_to_distance(2, 7, 4)



Mini-project #1 - Rock-paper-scissor-lizard-Spock

Mini-project Video15 min

http://www.codeskulptor.org/#examples-rpsls_template.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# Rock-paper-scissors-lizard-Spock template
# The key idea of this program is to equate the strings
# "rock", "paper", "scissors", "lizard", "Spock" to numbers
# as follows:
#
# 0 - rock
# 1 - Spock
# 2 - paper
# 3 - lizard
# 4 - scissors
# helper functions
def name_to_number(name):
# delete the following pass statement and fill in your code below
pass
# convert name to number using if/elif/else
# don't forget to return the result!
def number_to_name(number):
# delete the following pass statement and fill in your code below
pass
# convert number to a name using if/elif/else
# don't forget to return the result!
def rpsls(player_choice):
# delete the following pass statement and fill in your code below
pass
# print a blank line to separate consecutive games
# print out the message for the player's choice
# convert the player's choice to player_number using the function name_to_number()
# compute random guess for comp_number using random.randrange()
# convert comp_number to comp_choice using the function number_to_name()
# print out the message for computer's choice
# compute difference of comp_number and player_number modulo five
# use if/elif/else to determine winner, print winner message
# test your code - THESE CALLS MUST BE PRESENT IN YOUR SUBMITTED CODE
rpsls("rock")
rpsls("Spock")
rpsls("paper")
rpsls("lizard")
rpsls("scissors")
# always remember to check your completed program against the grading rubric

http://www.codeskulptor.org/#user43_2OiD0caumf_0.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# Rock-paper-scissors-lizard-Spock template
# The key idea of this program is to equate the strings
# "rock", "paper", "scissors", "lizard", "Spock" to numbers
# as follows:
#
# 0 - rock
# 1 - Spock
# 2 - paper
# 3 - lizard
# 4 - scissors
# helper functions
def name_to_number(name):
# delete the following pass statement and fill in your code below
#dic = {"rock":0, "Spock":1, "paper":2, "lizard":3, "scissors":4]
num = [x for x in range(5)]
nam = ["rock", "Spock", "paper", "lizard", "scissors"]
dic = dict(zip(nam,num))
# convert name to number using if/elif/else
# don't forget to return the result!
return dic[name]
def number_to_name(number):
# delete the following pass statement and fill in your code below
num = [x for x in range(5)]
nam = ["rock", "Spock", "paper", "lizard", "scissors"]
dic = dict(zip(num,nam))
# convert number to a name using if/elif/else
# don't forget to return the result!
return dic[number]
def rpsls(player_choice):
# delete the following pass statement and fill in your code below
# print a blank line to separate consecutive games
print '\n'
# print out the message for the player's choice
print 'Player chooses ' + player_choice
# convert the player's choice to player_number using the function name_to_number()
player_number = name_to_number(player_choice)
# compute random guess for comp_number using random.randrange()
import random
comp_number = random.randrange(0,5)
# convert comp_number to comp_choice using the function number_to_name()
comp_choice = number_to_name(comp_number)
# print out the message for computer's choice
print 'Computer chooses ' + comp_choice
# compute difference of comp_number and player_number modulo five
diff = (comp_number - player_number) % 5
# use if/elif/else to determine winner, print winner message
if diff == 3 or diff == 4:
print 'Player wins!'
elif diff == 1 or diff == 2:
print 'Computer wins!'
else:
print "Player and computer tie!"
# test your code - THESE CALLS MUST BE PRESENT IN YOUR SUBMITTED CODE
rpsls("rock")
rpsls("Spock")
rpsls("paper")
rpsls("lizard")
rpsls("scissors")
# always remember to check your completed program against the grading rubric

Mini-project Description10 min

Practice Mini-project: Mystical Octosphere (optional)10 min

Code Clinic Tips10 min

This item will be unlocked when the session begins.

Peer-graded Assignment: Rock-paper-scissors-lizard-Spock2h

http://www.codeskulptor.org/#user43_2OiD0caumf_0.py

Review Your Peers: Rock-paper-scissors-lizard-Spock

Week 3 Week 2 - Event-driven programming, local/global variables

Learn the basics of event-driven programming, understand difference between local and global variables, create an interactive program that plays a simple guessing game

Week 2a - Interactive Applications in Python

Event-Driven Programming13 min

http://www.codeskulptor.org/#examples-events.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Example of a simple event-driven program
# CodeSkulptor GUI module
import simplegui
# Event handler
def tick():
print "tick!"
# Register handler
timer = simplegui.create_timer(1000, tick)
# Start timer
timer.start()

Local vs. Global Variables11 min

http://www.codeskulptor.org/#examples-local_vs_global.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# global vs local examples
# num1 is a global variable
num1 = 1
print num1
# num2 is a local variable
def fun():
num1 = 2
num2 = num1 + 1
print num2
fun()
# the scope of global num1 is the whole program, num 1 remains defined
print num1
# the scope of the variable num2 is fun(), num2 is now undefined
# print num2
# why use local variables?
# give a descriptive name to a quantity
# avoid computing something multiple times
def fahren_to_kelvin(fahren):
celsius = 5.0 / 9 * (fahren - 32)
zero_celsius_in_kelvin = 273.15
return celsius + zero_celsius_in_kelvin
print fahren_to_kelvin(212)
# the risk/reward of using global variables
# risk - consider the software system for an airliner
# critical piece - flight control system
# non-critical piece - in-flight entertainment system
# both systems might use a variable called "dial"
# we don't want possibility that change the volume on your audio
# causes the plane's flaps to change!
# example
num = 4
def fun1():
global num
num = 5
def fun2():
global num
num = 6
# note that num changes after each call with no obvious explanation
print num
fun1()
print num
fun2()
print num
# global variables are an easy way for event handlers
# to communicate game information.
# safer method - but they required more sophisticated
# object-programming techniques

1
2
3
4
5
6
7
1
3
1
373.15
4
5
6

SimpleGUI11 min

http://www.codeskulptor.org/#examples-simplegui-0.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# CodeSkulptor runs Python programs in your browser.
# Click the upper left button to run this simple demo.
# CodeSkulptor runs in Chrome 18+, Firefox 11+, and Safari 6+.
# Some features may work in other browsers, but do not expect
# full functionality. It does NOT run in Internet Explorer.
import simplegui
message = "Welcome!"
# Handler for mouse click
def click():
global message
message = "Good job!"
# Handler to draw on canvas
def draw(canvas):
canvas.draw_text(message, [50,112], 36, "Red")
# Create a frame and assign callbacks to event handlers
frame = simplegui.create_frame("Home", 300, 200)
frame.add_button("Click me", click)
frame.set_draw_handler(draw)
# Start the frame animation
frame.start()

http://www.codeskulptor.org/#examples-simplegui-1.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# SimpleGUI program template
# Import the module
import simplegui
# Define global variables (program state)
count = 0
# Define "helper" functions
def incre():
global count
count += 1
# Define event handler functions
def tick():
incre()
print count
def bpress():
global count
count = 0
# Create a frame
frame = simplegui.create_frame("SimpleGUI Test",100,100)
# Register event handlers
timer = simplegui.create_timer(1000, tick)
frame.add_button("click me!", bpress)
# Start frame and timers
frame.start()
timer.start()

Practice Exercises for Interactive Applications (optional)10 min

Quiz: Quiz 2a10 questions

QUIZ
Quiz 2a
10 questions
To Pass70% or higher
Attempts3 every 8 hours
Deadline
November 5, 11:59 PM PST

1 point
1.What typically calls an event handler?


Some code that you didn’t write which generates the event.


The code you write.


1 point
2.In CodeSkulptor, how many event handlers can be running at the same time?


Unlimited, i.e., 0 or more


1


0


1 point
3.What are the three parts of a frame?

Refer to the video on SimpleGUI.


Status Area


Control Area


Mouse


Title


Keyboard


Background Area


Canvas


Border


Options Area


1 point
4.For the SimpleGUI-based programs in this course, we recommended breaking down an interactive Python program into seven parts. Below, these parts are listed alphabetically.

Create frame
Define classes
Define event handlers
Initialize global variables
Define helper functions
Register event handlers
Start frame and timers
However, in lecture, we recommended a particular ordering of these parts.

Enter 7 numbers in the range 1–7, separated only by spaces, to indicate the recommended ordering of the preceding elements of an interactive Python program. For example, if you think that the first action in your program should be to register your event handlers, enter 6 as the first number in the sequence.




1 point
5.Assume the following global definition is part of your program.

1
x = 5

If each of the following function definitions are also part of your program, which of them needs a global x declaration? You can try each definition in CodeSkulptor.


1
2
3
def d(y):
y = x + y
return y


1
2
def c(y):
return x + y


1
2
3
def b(x,y):
x = x + y
return x


1
2
3
def a(y):
x = x + y
return y



1 point
6.Consider the following code.

1
2
3
4
5
6
count = 0
def square(x):
global count
count += 1
return x**2
print square(square(square(square(3))))

What is the value of count at the end? Enter a number. (You can double check your answer in CodeSkulptor if you wish.)




1 point
7.Consider the following code.

1
2
3
4
5
a = 3
b = 6
def f(a):
c = a + b
return c

Which names occur in the global scope?


c


f


b


a


1 point
8.Consider the following code.

1
2
3
4
5
a = 3
b = 6
def f(a):
c = a + b
return c

Which names occur in a local scope?


f


b


a


c


1 point
9.Which of the following are valid calls to create_frame?

Look at the documentation for SimpleGUI frames, but also try the code in CodeSkulptor.


1
f = simplegui.create_frame("My Frame", 100, 100)


1
frame = simplegui.create_frame("Testing", 200, 200, 300)


1
frame = simplegui.create_frame(100, 100, 100)


1
frame = simplegui.create_frame("My Frame", 200, 200, 200, 200)



1 point
10.Which of the following are valid ways of making a canvas with a red background?

Look at the documentation for SimpleGUI constants, but also try the code in CodeSkulptor.


1
2
3
4
import simplegui
frame = simplegui.create_frame("My Frame", 100, 100)
frame.set_canvas_background(Red)
frame.start()


1
2
3
4
import simplegui
frame = simplegui.create_frame("My Frame", 100, 100)
frame.set_canvas_background("Red")
frame.start()


1
2
3
import simplegui
frame = simplegui.create_frame("My Frame", 100, 100, "Red")
frame.start()


1
2
3
4
5
import simplegui
frame = simplegui.create_frame("My Frame", 100, 100)
frame.set_canvas_background("#FF0000")
frame.start()


Week 2b - Buttons and Input Fields

Buttons10 min

http://www.codeskulptor.org/#examples-buttons.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# calculator with all buttons
import simplegui
# intialize globals
store = 12
operand = 3
# event handlers for calculator with a store and operand
def output():
"""prints contents of store and operand"""
print "Store = ", store
print "Operand = ", operand
print ""
def swap():
""" swap contents of store and operand"""
global store, operand
store, operand = operand, store
output()
def add():
""" add operand to store"""
global store
store = store + operand
output()
def sub():
""" subtract operand from store"""
global store
store = store - operand
output()
def mult():
""" multiply store by operand"""
global store
store = store * operand
output()
def div():
""" divide store by operand"""
global store
store = store / operand
output()
# create frame
f = simplegui.create_frame("Calculator",300,300)
# register event handlers
f.add_button("Print", output, 100)
f.add_button("Swap", swap, 100)
f.add_button("Add", add, 100)
f.add_button("Sub", sub, 100)
f.add_button("Mult", mult, 100)
f.add_button("Div", div, 100)
# get frame rolling
f.start()

Input Fields9 min

http://www.codeskulptor.org/#examples-input_fields.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# calculator with all buttons
import simplegui
# intialize globals
store = 0
operand = 0
# event handlers for calculator with a store and operand
def output():
"""prints contents of store and operand"""
print "Store = ", store
print "Operand = ", operand
print ""
def swap():
""" swap contents of store and operand"""
global store, operand
store, operand = operand, store
output()
def add():
""" add operand to store"""
global store
store = store + operand
output()
def sub():
""" subtract operand from store"""
global store
store = store - operand
output()
def mult():
""" multiply store by operand"""
global store
store = store * operand
output()
def div():
""" divide store by operand"""
global store
store = store / operand
output()
def enter(t):
""" enter a new operand"""
global operand
operand = int(t)
output()
# create frame
f = simplegui.create_frame("Calculator",300,300)
# register event handlers and create control elements
f.add_button("Print", output, 100)
f.add_button("Swap", swap, 100)
f.add_button("Add", add, 100)
f.add_button("Sub", sub, 100)
f.add_button("Mult", mult, 100)
f.add_button("Div", div, 100)
f.add_input("Enter", enter, 100)
# get frame rolling
f.start()

Visualizing Events5 min

http://www.codeskulptor.org/viz/#examples-input_fields.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# calculator with all buttons
import simplegui
# intialize globals
store = 0
operand = 0
# event handlers for calculator with a store and operand
def output():
"""prints contents of store and operand"""
print "Store = ", store
print "Operand = ", operand
print ""
def swap():
""" swap contents of store and operand"""
global store, operand
store, operand = operand, store
output()
def add():
""" add operand to store"""
global store
store = store + operand
output()
def sub():
""" subtract operand from store"""
global store
store = store - operand
output()
def mult():
""" multiply store by operand"""
global store
store = store * operand
output()
def div():
""" divide store by operand"""
global store
store = store / operand
output()
def enter(t):
""" enter a new operand"""
global operand
operand = int(t)
output()
# create frame
f = simplegui.create_frame("Calculator",300,300)
# register event handlers and create control elements
f.add_button("Print", output, 100)
f.add_button("Swap", swap, 100)
f.add_button("Add", add, 100)
f.add_button("Sub", sub, 100)
f.add_button("Mult", mult, 100)
f.add_button("Div", div, 100)
f.add_input("Enter", enter, 100)
# get frame rolling
f.start()

Programming Tips - 213 min

http://www.codeskulptor.org/#examples-tips2.py
https://docs.python.org/2/tutorial/controlflow.html#intermezzo-coding-style

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
##############
# Example of missing "global"
n1 = 0
def increment():
n1 = n1 + 1
increment()
increment()
increment()
print n1
##############
# Example of missing "global"
n2 = 0
def assign(x):
n2 = x
assign(2)
assign(15)
assign(7)
print n2
##############
# Example of missing "return"
n3 = 0
def decrement():
global n3
n3 = n3 - 1
x = decrement()
print "x = ", x
print "n = ", n
##############
# Example of print debugging
import simplegui
x = 0
def f(n):
print "f: n,x = ", n, x
result = n ** x
print "f: result = ",result
return result
def button_handler():
global x
print "bh : x = ", x
x += 1
print "bh : x = ", x
def input_handler(text):
print "ih : text = ", text
print f(float(text))
frame = simplegui.create_frame("Example", 200, 200)
frame.add_button("Increment", button_handler)
frame.add_input("Number:", input_handler, 100)
frame.start()
##############
# Examples of simplifying conditionals
def f1(a, b):
"""Returns True exactly when a is False and b is True."""
if a == False and b == True:
return True
else:
return False
def f2(a, b):
"""Returns True exactly when a is False and b is True."""
if not a and b:
return True
else:
return False
def f3(a, b):
"""Returns True exactly when a is False and b is True."""
return not a and b
def g1(a, b):
"""Returns False eactly when a and b are both True."""
if a == True and b == True:
return False
else:
return True
def g2(a, b):
"""Returns False eactly when a and b are both True."""
if a and b:
return False
else:
return True
def g3(a, b):
"""Returns False eactly when a and b are both True."""
return not (a and b)

Practice Exercises for Button and Input Fields (optional)10 min

Quiz: Quiz 2b10 questions

QUIZ
Quiz 2b
10 questions
To Pass70% or higher
Attempts3 every 8 hours
Deadline
November 5, 11:59 PM PST

1 point
1.In the following code, what does the number 100 represent?

1
my_button = frame.add_button("My Label", button_handler, 100)

Use the CodeSkulptor documentation to look it up.


Horizontal position of the button in pixels


Height of the button in pixels


Width of the button in pixels


Vertical position of the button in pixels


1 point
2.How many control objects are allowed in a frame?


1


0


Unlimited, i.e., 0 or more


1 point
3.In SimpleGUI, one kind of object can be added to the control panel that doesn’t allow any handler. Thus, this object can’t respond to anything. What kind of object is that?

Look at the documentation for SimpleGUI control objects.


Label


Frame

This should not be selected
That isn’t a control object.


Button


Title


Canvas


Input field


1 point
4.When you enter text into an input field and press enter, the text is passed to the input field’s event handler. What is the data type of the text?


A string


A number


A string or a number, depending on the text entered


1 point
5.Consider the following conditional statement.

1
2
3
4
5
6
if p == False:
return False
elif q == False:
return False
else:
return True

That is equivalent to which of the following simpler statements?

Try to reason logically about each of the statements, but also try each in CodeSkulptor.


1
return p and (not q)


1
return q and p


1
return (not p) or (not q)


1
return not(p or q)



1 point
6.Which of the following describes the mistake in the following code?

1
2
3
4
5
6
def volume_cube(side):
""" Returns the volume of a cube, given the length of its side. """
print side ** 3
s = 5
print "The volume of a cube with sides", s, "long is", volume_cube(s), "."


The call to volume_cube shouldn’t be within a print statement. More generally, function calls usually shouldn’t be within print statements.


All of the printing should be done within the function.


The function should return, not print, its result.


1 point
7.What kind of errors can happen if you are missing a needed global declaration in one of your function definitions? For this question, you need only consider the case where the problem is in the function that is missing the global declaration.

If you are having trouble with this question, watch this week’s Programming Tips video again.


NameError


An incorrect computation that generates no error message


AttributeError


SyntaxError


Error: local variable ‘…’ referenced before assignment


1 point
8.Which of the following function definitions are in the recommended code style?


1
2
3
def f(x, y):
""" Add the two inputs. """
return x + y


1
2
3
def f (x, y):
""" Add the two inputs. """
return x + y


1
2
3
def f(x, y):
""" Add the two inputs. """
return x+y


1
2
3
def myFunction(x, y):
""" Add the two inputs. """
return x + y



1 point
9.Cut and paste the following code into CodeSkulptor. Run it and make an attempt to understand how it works.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Simple interactive application
import simplegui
# Define globals.
message = "Welcome!"
count = 0
# Define event handlers.
def button_handler():
"""Count number of button presses."""
global count
count += 1
print message," You have clicked", count, "times."
def input_handler(text):
"""Get text to be displayed."""
global message
message = text
# Create frame and register event handlers.
frame = simplegui.create_frame("Home", 100, 200)
frame.add_button("Click me", button_handler)
frame.add_input("New message:", input_handler, 100)
# Start frame.
frame.start()

We’d like to modify the code so that the count is reset to zero whenever a new message is entered. Where would you need to modify this code to implement this change?


Add an assignment to count at the end of this code.


Add an assignment to count in the event handler for the input field. Also add a global count declaration there.


Add an assignment to count in the event handler for the button.


Add an assignment to count in the initialization of global variables.


1 point
10.In the game “Guess the number”, what is the minimum number of guesses necessary to guarantee that the guesser can always win if the secret number is chosen in range(0, 400)?

Review the mini-project description for “Guess the number” if you are having trouble with this problem.


8 guesses


9 guesses


10 guesses

This should not be selected


12 guesses

This should not be selected


It’s impossible to guarantee that you can always win at “Guess the number“.

This should not be selected
That’s clearly wrong. If nothing else, you could use the strategy of guessing each number from 0 to 399, thus needing 400 guesses.



Mini-project #2 - “Guess the Number!”

Mini-project Video6 min

http://www.codeskulptor.org/#examples-guess_the_number_template.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# template for "Guess the number" mini-project
# input will come from buttons and an input field
# all output for the game will be printed in the console
# helper function to start and restart the game
def new_game():
# initialize global variables used in your code here
# remove this when you add your code
pass
# define event handlers for control panel
def range100():
# button that changes the range to [0,100) and starts a new game
# remove this when you add your code
pass
def range1000():
# button that changes the range to [0,1000) and starts a new game
pass
def input_guess(guess):
# main game logic goes here
# remove this when you add your code
pass
# create frame
# register event handlers for control elements and start frame
# call new_game
new_game()
# always remember to check your completed program against the grading rubric

Mini-project Description10 min

http://www.codeskulptor.org/#examples-gtn_testing_template.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# Testing template for "Guess the number"
###################################################
# Student should add code for "Guess the number" here
# template for "Guess the number" mini-project
# input will come from buttons and an input field
# all output for the game will be printed in the console
import simplegui
import random
import math
###################################################
# Start our test #1 - assume global variable secret_number
# is the the "secret number" - change name if necessary
secret_number = 74
input_guess("50")
input_guess("75")
input_guess("62")
input_guess("68")
input_guess("71")
input_guess("73")
input_guess("74")
###################################################
# Output from test #1
#New game. Range is [0,100)
#Number of remaining guesses is 7
#
#Guess was 50
#Number of remaining guesses is 6
#Higher!
#
#Guess was 75
#Number of remaining guesses is 5
#Lower!
#
#Guess was 62
#Number of remaining guesses is 4
#Higher!
#
#Guess was 68
#Number of remaining guesses is 3
#Higher!
#
#Guess was 71
#Number of remaining guesses is 2
#Higher!
#
#Guess was 73
#Number of remaining guesses is 1
#Higher!
#
#Guess was 74
#Number of remaining guesses is 0
#Correct!
#
#New game. Range is [0,100)
#Number of remaining guesses is 7
###################################################
# Start our test #2 - assume global variable secret_number
# is the the "secret number" - change name if necessary
#range1000()
#secret_number = 375
#input_guess("500")
#input_guess("250")
#input_guess("375")
###################################################
# Output from test #2
#New game. Range is [0,100)
#Number of remaining guesses is 7
#
#New game. Range is [0,1000)
#Number of remaining guesses is 10
#
#Guess was 500
#Number of remaining guesses is 9
#Lower!
#
#Guess was 250
#Number of remaining guesses is 8
#Higher!
#
#Guess was 375
#Number of remaining guesses is 7
#Correct!
#
#New game. Range is [0,1000)
#Number of remaining guesses is 10
###################################################
# Start our test #3 - assume global variable secret_number
# is the the "secret number" - change name if necessary
#range100()
#secret_number = 28
#input_guess("50")
#input_guess("50")
#input_guess("50")
#input_guess("50")
#input_guess("50")
#input_guess("50")
#input_guess("50")
###################################################
# Output from test #3
#New game. Range is [0,100)
#Number of remaining guesses is 7
#
#Guess was 50
#Number of remaining guesses is 6
#Lower!
#
#Guess was 50
#Number of remaining guesses is 5
#Lower!
#
#Guess was 50
#Number of remaining guesses is 4
#Lower!
#
#Guess was 50
#Number of remaining guesses is 3
#Lower!
#
#Guess was 50
#Number of remaining guesses is 2
#Lower!
#
#Guess was 50
#Number of remaining guesses is 1
#Lower!
#
#Guess was 50
#Number of remaining guesses is 0
#You ran out of guesses. The number was 28
#
#New game. Range is [0,100)
#Number of remaining guesses is 7

Practice Mini-project: Magical Octosphere Reloaded (optional)10 min

Code Clinic Tips10 min

Peer-graded Assignment: “Guess the Number!”2h

http://www.codeskulptor.org/#user43_h8ZiuoEmml_0.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# template for "Guess the number" mini-project
# input will come from buttons and an input field
# all output for the game will be printed in the console
import simplegui
import random
import math
# helper function to start and restart the game
def new_game(fl=0):
# initialize global variables used in your code here
# remove this when you add your code
global secret_number
global f
f = fl
global n
if f == 0:
secret_number = random.randrange(0, 100)
n = math.ceil(math.log(101, 2))
print "range[0,100)"
else:
secret_number = random.randrange(0, 1000)
n = math.ceil(math.log(1001, 2))
print "range[0,1000)"
global c
c = 0
print "remain:", n
#print "s:", secret_number
# define event handlers for control panel
def range100():
# button that changes the range to [0,100) and starts a new game
print '\n'
new_game()
#print "remain:", n
#print "s:", secret_number
def range1000():
# button that changes the range to [0,1000) and starts a new game
print '\n'
new_game(1)
#print "s:", secret_number
def input_guess(guess):
# main game logic goes here
global n
global c
if c < n:
global secret_number
c = c + 1
n_guess = int(guess)
print "Guess was", n_guess
if secret_number < n_guess:
print "Lower"
print "remain:", n-c
print '\n'
if secret_number > n_guess:
print "Higher"
print "remain:", n-c
print '\n'
if secret_number == n_guess:
print "Correct"
print "remain:", n-c
print "You win! start new game!"
print '\n'
new_game(f)
if c == n:
print "You run out ot times! start new game! correct is", secret_number
print '\n'
new_game(f)
# create frame
frame = simplegui.create_frame('Guess the number!', 200, 200)
# register event handlers for control elements and start frame
inp = frame.add_input('My Guess', input_guess, 100)
range100 = frame.add_button('range100', range100, 100)
range1000 = frame.add_button('range1000', range1000, 100)
# call new_game
new_game()
# always remember to check your completed program against the grading rubric

Review Your Peers: “Guess the Number!”

Week 4 Week 3 - Canvas, drawing, timers

Create a canvas in Python, learn how to draw on the canvas, create a digital stopwatch

Week 3a - Drawing Canvas

Canvas and Drawing12 min

http://www.codeskulptor.org/#examples-canvas_and_drawing.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# first example of drawing on the canvas
import simplegui
# define draw handler
def draw(canvas):
canvas.draw_text("Hello!",[100, 100], 24, "White")
canvas.draw_circle([100, 100], 2, 2, "Red")
# create frame
frame = simplegui.create_frame("Text drawing", 300, 200)
# register draw handler
frame.set_draw_handler(draw)
# start frame
frame.start()

String Processing11 min

http://www.codeskulptor.org/#examples-strings.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
### String Processing
# String literals
s1 = "Rixner's funny"
s2 = 'Warren wears nice ties!'
s3 = " t-shirts!"
#print s1, s2
#print s3
# Combining strings
a = ' and '
s4 = "Warren" + a + "Rixner" + ' are nuts!'
print s4
# Characters and slices
print s1[3]
print len(s1)
print s1[0:6] + s2[6:]
print s2[:13] + s1[9:] + s3
# Converting strings
s5 = str(375)
print s5[1:]
i1 = int(s5[1:])
print i1 + 38

http://www.codeskulptor.org/#examples-money-0.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# convert xx.yy to xx dollars and yy cents
def convert(val):
dollars = int(val)
cents = int(100 * (val - dollars))
return str(dollars) + " dollars and " + str(cents) + " cents"
# Tests
print convert(11.23)
print convert(11.20)
print convert(1.12)
print convert(12.01)
print convert(1.01)
print convert(0.01)
print convert(1.00)
print convert(0)
print convert(-1.40)
print convert(12.55555)

1
2
3
4
5
6
7
8
9
10
11 dollars and 23 cents
11 dollars and 19 cents
1 dollars and 12 cents
12 dollars and 0 cents
1 dollars and 1 cents
0 dollars and 1 cents
1 dollars and 0 cents
0 dollars and 0 cents
-1 dollars and -39 cents
12 dollars and 55 cents

http://www.codeskulptor.org/#examples-money-1.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# Handle single quantity
def convert_units(val, name):
result = str(val) + " " + name
if val > 1:
result = result + "s"
return result
# convert xx.yy to xx dollars and yy cents
def convert(val):
# Split into dollars and cents
dollars = int(val)
cents = int(round(100 * (val - dollars)))
# Convert to strings
dollars_string = convert_units(dollars, "dollar")
cents_string = convert_units(cents, "cent")
# return composite string
if dollars == 0 and cents == 0:
return "Broke!"
elif dollars == 0:
return cents_string
elif cents == 0:
return dollars_string
else:
return dollars_string + " and " + cents_string
# Tests
print convert(11.23)
print convert(11.20)
print convert(1.12)
print convert(12.01)
print convert(1.01)
print convert(0.01)
print convert(1.00)
print convert(0)

1
2
3
4
5
6
7
8
11 dollars and 23 cents
11 dollars and 20 cents
1 dollar and 12 cents
12 dollars and 1 cent
1 dollar and 1 cent
1 cent
1 dollar
Broke!

Interactive Drawing12 min

http://www.codeskulptor.org/#examples-money-1.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# Handle single quantity
def convert_units(val, name):
result = str(val) + " " + name
if val > 1:
result = result + "s"
return result
# convert xx.yy to xx dollars and yy cents
def convert(val):
# Split into dollars and cents
dollars = int(val)
cents = int(round(100 * (val - dollars)))
# Convert to strings
dollars_string = convert_units(dollars, "dollar")
cents_string = convert_units(cents, "cent")
# return composite string
if dollars == 0 and cents == 0:
return "Broke!"
elif dollars == 0:
return cents_string
elif cents == 0:
return dollars_string
else:
return dollars_string + " and " + cents_string
# Tests
print convert(11.23)
print convert(11.20)
print convert(1.12)
print convert(12.01)
print convert(1.01)
print convert(0.01)
print convert(1.00)
print convert(0)

1
2
3
4
5
6
7
8
11 dollars and 23 cents
11 dollars and 20 cents
1 dollar and 12 cents
12 dollars and 1 cent
1 dollar and 1 cent
1 cent
1 dollar
Broke!

http://www.codeskulptor.org/#examples-interactive_drawing.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# interactive application to convert a float in dollars and cents
import simplegui
# define global value
value = 3.12
# Handle single quantity
def convert_units(val, name):
result = str(val) + " " + name
if val > 1:
result = result + "s"
return result
# convert xx.yy to xx dollars and yy cents
def convert(val):
# Split into dollars and cents
dollars = int(val)
cents = int(round(100 * (val - dollars)))
# Convert to strings
dollars_string = convert_units(dollars, "dollar")
cents_string = convert_units(cents, "cent")
# return composite string
if dollars == 0 and cents == 0:
return "Broke!"
elif dollars == 0:
return cents_string
elif cents == 0:
return dollars_string
else:
return dollars_string + " and " + cents_string
# define draw handler
def draw(canvas):
canvas.draw_text(convert(value), [60, 110], 24, "White")
# define an input field handler
def input_handler(text):
global value
value = float(text)
# create frame
frame = simplegui.create_frame("Converter", 400, 200)
# register event handlers
frame.set_draw_handler(draw)
frame.add_input("Enter value", input_handler, 100)
# start frame
frame.start()

Practice Exercises for Drawing (optional)10 min

Quiz: Quiz 3a10 questions

QUIZ
Quiz 3a
10 questions
To Pass70% or higher
Attempts3 every 8 hours
Deadline
November 12, 11:59 PM PST

1 point

  1. What Python operator takes two strings (e.g., “sun” and “rise”) and forms the combination of these two strings, one followed by the other (e.g., “sunrise”)?

    +

    concat

    append

    concatenate

    *


    1 point
    2.What does the draw handler parameter represent?

If you’ve forgotten, refer to the documentation.


The canvas


Nothing — it doesn’t have a parameter


The object to be drawn


The frame


The location of the object to be drawn


1 point
3.What happens if you draw text outside the canvas coordinates?

Try it in CodeSkulptor.


The text coordinates are implicitly “wrapped” around using modular arithmetic, so that the text appears on the canvas


Some or none of the text is shown. Conceptually, the text is drawn at whatever coordinates are given, but only whatever text fits within the canvas coordinates is shown.


The text appears in the frame, but some or all of the text is shown outside the canvas area.


Causes an error


1 point
4.Assume we have a canvas that is 200 pixels wide and 300 pixels high. We want to draw a green line between the upper left corner of the canvas and the lower right corner of the canvas. Which of the following calls will accomplish this?

Try the code in CodeSkulptor.


1
canvas.draw_line((200, 300), (0, 0), 10, "Green")


1
canvas.draw_line((0, 0), (300, 200), 10, "Green")


1
canvas.draw_line((200, 0), (0, 300), 10, "Green")



1 point
5.Consider the following function definition.

1
2
3
4
5
def date(month, day):
"""Given numbers month and day, returns a string of the form '2/12',
with the month followed by the day."""
return month + "/" + day
print date(2, 12)

This definition leads to an error. To fix it, what Python expression should replace the question marks below?

1
2
3
4
5
def date(month, day):
"""Given numbers month and day, returns a string of the form '2/12',
with the month followed by the day."""
return ???
print date(2, 12)


string(month + “/“ + day)


string(month) + “/“ + string(day)


str(month / day)


str(month + “/“ + day)


str(month) + “/“ + str(day)


string(month / day)


1 point
6.How many instances of the letter “l” are there in the following:

1
2
1lll1l1l1l1ll1l111ll1l1ll1l1ll1ll111ll1ll1ll1l1ll1ll1ll1ll1lll1l1l1l1l1l1l1l1l1l
1l1l1ll1lll1l111ll1l1l1l1l1

Although it might be hard to tell, that string contains ones (1) and lower-case L’s (l). Create a small CodeSkulptor program, and use copy-and-paste to insert this string in your code. Your program should only need one function or method call.




1 point
7.Where should your draw_text, draw_line, and similar drawing calls be?


Anywhere in your code


In a draw handler, or a helper function called from it


In the handlers for the control objects that create or change the drawing, or their helper functions


1 point
8.Which of the following function calls are valid, i.e., don’t lead to an error?


Read the documentation for these functions, and also try the code in CodeSkulptor.


float(“5 five”)


int(“5.4”)


float(“5.4”)


int(“5”)


1 point
9.Turn the following description into a CodeSkulptor program, and run it.

Create a 300-by-300 canvas.
Draw two circles with radius 20 and white lines of width 10. One is centered at (90,200) and one at (210,200).
Draw a red line of width 40 from (50,180) to (250,180).
Draw two red lines of width 5 from (55,170) to (90,120) and from (90,120) to (130,120).
Draw a red line of width 140 from (180,108) to (180,160).
The resulting picture is a simple diagram of what?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# first example of drawing on the canvas
import simplegui
# define draw handler
def draw(canvas):
canvas.draw_circle([90,200], 20, 10, "White")
canvas.draw_circle([210,200], 20, 10, "White")
canvas.draw_line([50,180],[250,180], 40, "Red")
canvas.draw_line([55,170],[90,120], 5, "Red")
canvas.draw_line([90,120],[130,120], 5, "Red")
canvas.draw_line([180,108],[180,160], 140, "Red")
# create frame
frame = simplegui.create_frame("Text drawing", 300, 300)
# register draw handler
frame.set_draw_handler(draw)
# start frame
frame.start()


A person


A house


A computer


A motorcycle


An automobile


1 point
10.The following is a diagram of an archery target.


To draw this in CodeSkulptor, we can put a small yellow circle with a black border on top of a slightly bigger yellow circle with a black border, … on top of a big white circle with a black border. In what order should your code draw these circles?


Smallest first


Largest first

Week 3b - Timers

Timers9 min

http://www.codeskulptor.org/#examples-timers.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# Simple "screensaver" program.
# Import modules
import simplegui
import random
# Global state
message = "Python is Fun!"
position = [50, 50]
width = 500
height = 500
interval = 2000
# Handler for text box
def update(text):
global message
message = text
# Handler for timer
def tick():
x = random.randrange(0, width)
y = random.randrange(0, height)
position[0] = x
position[1] = y
# Handler to draw on canvas
def draw(canvas):
canvas.draw_text(message, position, 36, "Red")
# Create a frame
frame = simplegui.create_frame("Home", width, height)
# Register event handlers
text = frame.add_input("Message:", update, 150)
frame.set_draw_handler(draw)
timer = simplegui.create_timer(interval, tick)
# Start the frame animation
frame.start()
timer.start()

Visualizing Drawing and Timers6 min

http://www.codeskulptor.org/viz/#examples-timers.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# Simple "screensaver" program.
# Import modules
import simplegui
import random
# Global state
message = "Python is Fun!"
position = [50, 50]
width = 500
height = 500
interval = 2000
# Handler for text box
def update(text):
global message
message = text
# Handler for timer
def tick():
x = random.randrange(0, width)
y = random.randrange(0, height)
position[0] = x
position[1] = y
# Handler to draw on canvas
def draw(canvas):
canvas.draw_text(message, position, 36, "Red")
# Create a frame
frame = simplegui.create_frame("Home", width, height)
# Register event handlers
text = frame.add_input("Message:", update, 150)
frame.set_draw_handler(draw)
timer = simplegui.create_timer(interval, tick)
# Start the frame animation
frame.start()
timer.start()

Programming Tips - 37 min

http://www.codeskulptor.org/#examples-tips3-events.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#####################
# Example of event-driven code, buggy version
import simplegui
size = 10
radius = 10
# Define event handlers.
def incr_button_handler():
"""Increment the size."""
global size
size += 1
label.set_text("Value: " + str(size))
def decr_button_handler():
"""Decrement the size."""
global size
# Insert check that size > 1, to make sure it stays positive
# NOTE that this restriction has changed from the video
# since draw_circle now throws an error if radius is zero
size -= 1
label.set_text("Value: " + str(size))
def change_circle_handler():
"""Change the circle radius."""
global radius
radius = size
# Insert code to make radius label change.
def draw_handler(canvas):
"""Draw the circle."""
canvas.draw_circle((100, 100), radius, 5, "Red")
# Create a frame and assign callbacks to event handlers.
frame = simplegui.create_frame("Home", 200, 200)
label = frame.add_label("Value: " + str(size))
frame.add_button("Increase", incr_button_handler)
frame.add_button("Decrease", decr_button_handler)
frame.add_label("Radius: " + str(radius))
frame.add_button("Change circle", change_circle_handler)
frame.set_draw_handler(draw_handler)
# Start the frame animation
frame.start()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import simplegui
#####################
# Buggy code -- doesn't start frame
message = "Welcome!"
def click():
"""Change message on mouse click."""
global message
message = "Good job!"
def draw(canvas):
"""Draw message."""
canvas.draw_text(message, [50,112], 36, "Red")
# Create a frame and assign callbacks to event handlers
frame = simplegui.create_frame("Home", 300, 200)
frame.add_button("Click me", click)
frame.set_draw_handler(draw)
#####################
# Buggy code -- doesn't start timers
def timer1_handler():
print "1"
def timer2_handler():
print "2"
simplegui.create_timer(100, timer1_handler)
simplegui.create_timer(300, timer2_handler)

Practice Exercises for Timers (optional)10 min

Quiz: Quiz 3b9 questions

QUIZ
Quiz 3b
9 questions
To Pass70% or higher
Attempts3 every 8 hours
Deadline
November 12, 11:59 PM PST

1 point
1.When the following code is executed, how many times is timer_handler called?

1
2
3
4
5
import simplegui
def timer_handler():
timer = simplegui.create_timer(10, timer_handler)
timer.start()

The body of timer_handler isn’t given, as it is irrelevant for this question. You may want to finish the code and run it before submitting your answer.


0 — The code hasn’t been written correctly.


1


10


Unlimited — It is called repeatedly until you stop the program.


1 point
2.You want a timer to create exactly 1000 events. Which of the following solutions are possible?


In the timer handler, have a local counter for the number of timer calls.
In the timer handler, increment the counter. In the timer handler, check the count and possibly stop the timer.


Have a global counter for the number of timer calls.

In the timer handler, increment the counter. In the timer handler, check the count and possibly stop the timer.


Specify the number of timer events when creating the timer.


Have a global counter for the number of timer calls.

Outside the timer handler, increment the counter. Outside the timer handler, check the count and possibly stop the timer.


1 point
3.How do you change the frequency of a running timer, either increasing or decreasing the frequency? E.g., in the code below, we want code at the question marks that changes the timer.

1
2
3
4
5
timer = simplegui.create_timer(1000, timer_handler)
timer.start()
???


Just use set_timer_interval.

1
timer.set_timer_interval(300)


You can’t. But, you can stop this timer, and start a new one with a different frequency and same handler.

1
2
3
timer.stop()
timer = simplegui.create_timer(300, timer_handler)
timer.start()


Create and start the timer again.

1
2
timer = simplegui.create_timer(300, timer_handler)
timer.start()


Just run create_timer. It will change the timer.

1
timer = simplegui.create_timer(300, timer_handler)



1 point
4.How many timers can you have running at once?


0


1


Unlimited


1 point
5.The function time.time() is used in Python to keep track of time. What unit of time is associated with the value returned by time.time()? Hint: Look in the documentation.


Milli-second


Second


Minute


Hour


1 point
6.In Python, the time module can be used to determine the current time. This module includes the method time which returns the current system time in seconds since a date referred as the Epoch. The Epoch is fixed common date shared by all Python installations. Using the date of the Epoch and the current system time, an application such as a clock or calendar can compute the current time/date using basic arithmetic.

Write a CodeSkulptor program that experiments with the method time.time() and determines what date and time corresponds to the Epoch. Enter the year of the Epoch as a four digit number. (Remember to import time.)




1 point
7.The Python code below uses a timer to execute the function update() 10 times, computing a good approximation to a common mathematical function. Examine the code, and run it while varying the input value n.

What is the common name for what this computes?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# Mystery computation in Python
# Takes input n and computes output named result
import simplegui
# global state
result = 1
iteration = 0
max_iterations = 10
# helper functions
def init(start):
"""Initializes n."""
global n
n = start
print "Input is", n
def get_next(current):
"""??? Part of mystery computation."""
return 0.5 * (current + n / current)
# timer callback
def update():
"""??? Part of mystery computation."""
global iteration, result
iteration += 1
# Stop iterating after max_iterations
if iteration >= max_iterations:
timer.stop()
print "Output is", result
else:
result = get_next(result)
# register event handlers
timer = simplegui.create_timer(1, update)
# start program
init(13)
timer.start()


Multiplication by 2: 2n


Exponentiation: 2n


Cosine of n


Logarithm base 2


Square: n2


Multiplicative inverse: 1/n


Square root of n


1 point
8.Given any initial natural number, consider the sequence of numbers generated by repeatedly following the rule:

divide by two if the number is even or
multiply by 3 and add 1 if the number is odd.
The Collatz conjecture states that this sequence always terminates at 1. For example, the sequence generated by 23 is:

23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1

Write a Python program that takes a global variable n and uses a timer callback to repeatedly apply the rule above to n. Use the code from the previous question as a template. I suggest that your code prints out the sequence of numbers generated by this rule. Run this program for n = 217. What is the largest number in the sequence generated by this starting value?

To test your code, starting at n = 23 generates a sequence with a maximum value of 160.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# Mystery computation in Python
# Takes input n and computes output named result
import simplegui
# global state
result = 1
iteration = 0
max_iterations = 50
l = []
# helper functions
def init(start):
"""Initializes n."""
global n
n = start
l.append(n)
print "Input is", n
def get_next(current):
"""??? Part of mystery computation."""
if current % 2 == 0:
c = current / 2
elif current % 2 == 1:
c = current * 3 + 1
global l
l.append(c)
#print c
return c
# timer callback
def update():
"""??? Part of mystery computation."""
global iteration, n
iteration += 1
#print "result is",result
# Stop iterating after max_iterations
if (iteration >= max_iterations) or (n==1):
timer.stop()
print "Output is", n
print sorted(l, reverse=True)
else:
n = get_next(n)
# register event handlers
timer = simplegui.create_timer(1, update)
# start program
init(217)
timer.start()



1 point
9.CodeSkulptor runs your Python code by converting it into Javascript when you click the “Run” button and then executing this Javascript in your web browser. Open this example and run the provided code. If the SimpleGUI frame is spawned as a separate window, you should see an animation of an explosion in the canvas for this frame. If the SimpleGUI frame is spawned as a separate tab on top of the existing window containing the code (as happens in some browser configurations), the animation will “freeze” and a single static image is displayed. (If the SimpleGUI frame spawns as a separate window, you can also cause the animation to freeze by opening a new tab on top of the code window.)

As explained in the FAQ (check the Resources tab on the left), what is the explanation for this behavior?


Modern browser don’t support running Javascript in multiple windows simultaneously. This situation causes the animation to freeze.


To save resources, modern browsers only execute the Javascript associated with the topmost tab of a window. The animation freezes since the code tab and its associated Javascript is no longer the topmost tab.


Javascript and Python are incompatible languages. As a result, the Python in one tab can’t run at the same time as the Javascript in the SimpleGUI frame.

Mini-project #3 - Stopwatch: The Game

Mini-project Video9 min

http://www.codeskulptor.org/#examples-stopwatch_template.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# template for "Stopwatch: The Game"
# define global variables
# define helper function format that converts time
# in tenths of seconds into formatted string A:BC.D
def format(t):
pass
# define event handlers for buttons; "Start", "Stop", "Reset"
# define event handler for timer with 0.1 sec interval
# define draw handler
# create frame
# register event handlers
# start frame
# Please remember to review the grading rubric

Mini-project Description10 min

Code Clinic Tips10 min

This item will be unlocked when the session begins.

Peer-graded Assignment: Stopwatch: The Game2h

http://www.codeskulptor.org/#user43_VIajy7NaN1_0.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# template for "Stopwatch: The Game"
import simplegui
# define global variables
c = 0
message = "0:00.0"
x = 0
y = 0
# define helper function format that converts time
# in tenths of seconds into formatted string A:BC.D
def format(t):
abc = t / 10
d = t % 10
a = abc / 60
bc = abc % 60
if len(str(bc)) == 1:
return str(a)+':0'+str(bc)+'.'+str(d)
elif len(str(bc)) == 2:
return str(a)+':'+str(bc)+'.'+str(d)
# define event handlers for buttons; "Start", "Stop", "Reset"
def startb():
timer.start()
def stopb():
timer.stop()
global x,y
y = y + 1
if c % 10 == 0:
x = x + 1
def resetb():
if timer.is_running():
timer.stop()
global c, message,x,y
c=0
message = "0:00.0"
x=0
y=0
# define event handler for timer with 0.1 sec interval
def tick():
global c, message
c = c + 1
message = format(c)
# define draw handler
def draw(canvas):
canvas.draw_text(message, [100,100], 36, "Red")
canvas.draw_text(str(x)+'/'+str(y), [240,30], 36, "Red")
# create frame
frame = simplegui.create_frame("Stopwatch: The Game", 300, 200)
# register event handlers
timer = simplegui.create_timer(100, tick)
frame.set_draw_handler(draw)
frame.add_button("Start", startb, 100)
frame.add_button("Stop", stopb, 100)
frame.add_button("Reset", resetb, 100)
# start frame
frame.start()
# Please remember to review the grading rubric

http://www.codeskulptor.org/#user43_VIajy7NaN1_1.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# template for "Stopwatch: The Game"
import simplegui
# define global variables
c = 0
message = "0:00.0"
x = 0
y = 0
# define helper function format that converts time
# in tenths of seconds into formatted string A:BC.D
def format(t):
abc = t / 10
d = t % 10
a = abc / 60
bc = abc % 60
if len(str(bc)) == 1:
return str(a)+':0'+str(bc)+'.'+str(d)
elif len(str(bc)) == 2:
return str(a)+':'+str(bc)+'.'+str(d)
# define event handlers for buttons; "Start", "Stop", "Reset"
def startb():
timer.start()
def stopb():
if timer.is_running():
timer.stop()
global x,y
y = y + 1
if c % 10 == 0:
x = x + 1
def resetb():
timer.stop()
global c, message,x,y
c=0
message = "0:00.0"
x=0
y=0
# define event handler for timer with 0.1 sec interval
def tick():
global c, message
c = c + 1
message = format(c)
# define draw handler
def draw(canvas):
canvas.draw_text(message, [100,100], 36, "Red")
canvas.draw_text(str(x)+'/'+str(y), [240,30], 36, "Red")
# create frame
frame = simplegui.create_frame("Stopwatch: The Game", 300, 200)
# register event handlers
timer = simplegui.create_timer(100, tick)
frame.set_draw_handler(draw)
frame.add_button("Start", startb, 100)
frame.add_button("Stop", stopb, 100)
frame.add_button("Reset", resetb, 100)
# start frame
frame.start()
# Please remember to review the grading rubric

Review Your Peers: Stopwatch: The Game

Week 5 Week 4 - Lists, keyboard input, the basics of modeling motion

Learn the basics of lists in Python, model moving objects in Python, recreate the classic arcade game “Pong”

Week 4a - Basics of Lists

Lists11 min

Keyboard Input9 min

http://www.codeskulptor.org/#examples-keyboard_echo.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# Keyboard echo
import simplegui
# initialize state
current_key = ' '
# event handlers
def keydown(key):
global current_key
current_key = chr(key)
def keyup(key):
global current_key
current_key = ' '
def draw(c):
# NOTE draw_text now throws an error on some non-printable characters
# Since keydown event key codes do not all map directly to
# the printable character via ord(), this example now restricts
# keys to alphanumerics
if current_key in "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789":
c.draw_text(current_key, [10, 25], 20, "Red")
# create frame
f = simplegui.create_frame("Echo", 35, 35)
# register event handlers
f.set_keydown_handler(keydown)
f.set_keyup_handler(keyup)
f.set_draw_handler(draw)
# start frame
f.start()

http://www.codeskulptor.org/#examples-position_control.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# control the position of a ball using the arrow keys
import simplegui
# Initialize globals
WIDTH = 600
HEIGHT = 400
BALL_RADIUS = 20
ball_pos = [WIDTH / 2, HEIGHT / 2]
# define event handlers
def draw(canvas):
canvas.draw_circle(ball_pos, BALL_RADIUS, 2, "Red", "White")
def keydown(key):
vel = 4
if key == simplegui.KEY_MAP["left"]:
ball_pos[0] -= vel
elif key == simplegui.KEY_MAP["right"]:
ball_pos[0] += vel
elif key == simplegui.KEY_MAP["down"]:
ball_pos[1] += vel
elif key == simplegui.KEY_MAP["up"]:
ball_pos[1] -= vel
# create frame
frame = simplegui.create_frame("Positional ball control", WIDTH, HEIGHT)
# register event handlers
frame.set_draw_handler(draw)
frame.set_keydown_handler(keydown)
# start frame
frame.start()

Motion14 min

http://www.codeskulptor.org/#examples-motion_explicit.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# Ball motion with an explicit timer
import simplegui
# Initialize globals
WIDTH = 600
HEIGHT = 400
BALL_RADIUS = 20
init_pos = [WIDTH / 2, HEIGHT / 2]
vel = [0, 3] # pixels per tick
time = 0
# define event handlers
def tick():
global time
time = time + 1
def draw(canvas):
# create a list to hold ball position
ball_pos = [0, 0]
# calculate ball position
ball_pos[0] = init_pos[0] + time * vel[0]
ball_pos[1] = init_pos[1] + time * vel[1]
# draw ball
canvas.draw_circle(ball_pos, BALL_RADIUS, 2, "Red", "White")
# create frame
frame = simplegui.create_frame("Motion", WIDTH, HEIGHT)
# register event handlers
frame.set_draw_handler(draw)
timer = simplegui.create_timer(100, tick)
# start frame
frame.start()
timer.start()

http://www.codeskulptor.org/#examples-motion_implicit.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# Ball motion with an implicit timer
import simplegui
# Initialize globals
WIDTH = 600
HEIGHT = 400
BALL_RADIUS = 20
ball_pos = [WIDTH / 2, HEIGHT / 2]
vel = [0, 1] # pixels per update (1/60 seconds)
# define event handlers
def draw(canvas):
# Update ball position
ball_pos[0] += vel[0]
ball_pos[1] += vel[1]
# Draw ball
canvas.draw_circle(ball_pos, BALL_RADIUS, 2, "Red", "White")
# create frame
frame = simplegui.create_frame("Motion", WIDTH, HEIGHT)
# register event handlers
frame.set_draw_handler(draw)
# start frame
frame.start()

Collisions and Reflections11 min

http://www.codeskulptor.org/#examples-collisions_and_reflections.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import simplegui
# Initialize globals
WIDTH = 600
HEIGHT = 400
BALL_RADIUS = 20
ball_pos = [WIDTH / 2, HEIGHT / 2]
vel = [-40.0 / 60.0, 5.0 / 60.0]
# define event handlers
def draw(canvas):
# Update ball position
ball_pos[0] += vel[0]
ball_pos[1] += vel[1]
# collide and reflect off of left hand side of canvas
if ball_pos[0] <= BALL_RADIUS:
vel[0] = - vel[0]
# Draw ball
canvas.draw_circle(ball_pos, BALL_RADIUS, 2, "Red", "White")
# create frame
frame = simplegui.create_frame("Ball physics", WIDTH, HEIGHT)
# register event handlers
frame.set_draw_handler(draw)
# start frame
frame.start()

Practice Exercises for Lists (optional)10 min

Quiz: Quiz 4a9 questions

QUIZ
Quiz 4a
9 questions
To Pass70% or higher
Attempts3 every 8 hours
Deadline
November 19, 11:59 PM PST

1 point
1.One of the tasks that you will engage in when learning a new programming language is locating the name of a built-in function that performs a common, simple operation. While you might be tempted to write your own code that performs this operation, locating a built-in function is usually preferable since the built-in version is automatically correct and others that read your code will immediately recognize what your code is doing.

Python has a built-in function that adds up the numbers in a list. For example, given the list [1, 2, 5, 4], this function returns 1 + 2 + 5 + 4 = 12. Use your search skills to find the name of this built-in function. Enter the name of the built-in function below, without any parentheses or arguments.

(Note that we could just tell you the name of this function. However, the point of this problem is for you to start learning how to locate useful language features on your own.)




1 point
2.Let my_list be the list [“This”, “course”, “is”, “great”].

What is len(my_list)?
What non-negative number is the index of “great”? I.e., how would you replace the question marks in my_list[???] so that the resulting value is “great”?
Submit two numbers, one for each of these two questions, separated by spaces.




1 point
3.Let my_list be the list [“This”, “course”, “is”, “great”].

We can use Python’s slice notation to get part of this list. What non-negative numbers can be used to get the slice [“course”, “is”]? I.e., what two non-negative numbers should we put in my_list[??? : ???] to get that result?

Submit the two numbers in order, separated only by spaces.




1 point
4.If we want to split a list my_list into two halves, which of the following uses slices to do so correctly?

More precisely, if the length of my_list is 2n, i.e., even, then the two parts should each have length n. If its length is 2n+1, i.e., odd, then the two parts should have lengths n and n+1.


my_list[: len(my_list) // 2] and my_list[len(my_list) // 2 :]


my_list[0 : len(my_list) // 2] and my_list[len(my_list) // 2 + 1 : len(my_list)]


my_list[: len(my_list) // 2 - 1] and my_list[len(my_list) // 2 :]


my_list[0 : len(my_list) // 2] and my_list[len(my_list) // 2 : len(my_list)]


1 point
5.What is the distance between point [4, 7] and the nearest point on the circle centered at [2, 9] with radius 2? Provide at least 4 digits of accuracy.

Hint: The distance between a point and a circle is the distance between the point and the center of the circle minus the radius of the circle. You can use the point-to-point distance code described in this week’s videos.




1 point
6.A ball with velocity [4, 2] reflects off a vertical wall. What is its new velocity?


[-4, 2]


[4, -2]


[4, 2]


[-4, -2]


1 point
7.Which of the following illustrate how to properly structure a keydown or keyup event handler? (For more advanced Python programmers, assume that you have just imported simplegui and haven’t used from.)


1
2
3
def keydown_handler(key):
if "left" == simplegui.KEY_MAP[key]:


1
2
3
def keydown_handler(key):
if key == simplegui.KEY_MAP["left"]:


1
2
3
def keydown_handler(key):
if "left" == KEY_MAP[key]:


1
2
3
def keydown_handler(key):
if key == KEY_MAP["left"]:



1 point
8.Assume you have a program with a keydown handler. You run it, and press a single key and hold it down continuously. How many times does the keydown handler get called?

Experiment in CodeSkulptor to find out.


2 — once at the beginning and once when you release the key


1


Unlimited — i.e., repeatedly until you finally release the key


1 point
9.Several keys on the keyboard, such as Shift, CapsLock, and Ctrl, typically act to modify what happens when you press other keys, rather than doing anything on their own. When using the SimpleGUI keydown handler, how are such keys treated?

Experiment in CodeSkulptor to find out.


Independent key press events — e.g., pressing Shift by itself creates an event


No effect — e.g., pressing the Shift key does not create or modify the behavior of any event.


Modify other key presses — e.g., pressing the ‘a’ key creates an event with a different value than pressing Shift and ‘a’ together.

Week 4b - Keyboard Control

Velocity Control9 min

http://www.codeskulptor.org/#examples-position_control.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# control the position of a ball using the arrow keys
import simplegui
# Initialize globals
WIDTH = 600
HEIGHT = 400
BALL_RADIUS = 20
ball_pos = [WIDTH / 2, HEIGHT / 2]
# define event handlers
def draw(canvas):
canvas.draw_circle(ball_pos, BALL_RADIUS, 2, "Red", "White")
def keydown(key):
vel = 4
if key == simplegui.KEY_MAP["left"]:
ball_pos[0] -= vel
elif key == simplegui.KEY_MAP["right"]:
ball_pos[0] += vel
elif key == simplegui.KEY_MAP["down"]:
ball_pos[1] += vel
elif key == simplegui.KEY_MAP["up"]:
ball_pos[1] -= vel
# create frame
frame = simplegui.create_frame("Positional ball control", WIDTH, HEIGHT)
# register event handlers
frame.set_draw_handler(draw)
frame.set_keydown_handler(keydown)
# start frame
frame.start()

http://www.codeskulptor.org/#examples-velocity_control.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# control the velocity of a ball using the arrow keys
import simplegui
# Initialize globals
WIDTH = 600
HEIGHT = 400
BALL_RADIUS = 20
ball_pos = [WIDTH / 2, HEIGHT / 2]
vel = [0, 0]
# define event handlers
def draw(canvas):
# Update ball position
ball_pos[0] += vel[0]
ball_pos[1] += vel[1]
# Draw ball
canvas.draw_circle(ball_pos, BALL_RADIUS, 2, "Red", "White")
def keydown(key):
acc = 1
if key==simplegui.KEY_MAP["left"]:
vel[0] -= acc
elif key==simplegui.KEY_MAP["right"]:
vel[0] += acc
elif key==simplegui.KEY_MAP["down"]:
vel[1] += acc
elif key==simplegui.KEY_MAP["up"]:
vel[1] -= acc
print ball_pos
# create frame
frame = simplegui.create_frame("Velocity ball control", WIDTH, HEIGHT)
# register event handlers
frame.set_draw_handler(draw)
frame.set_keydown_handler(keydown)
# start frame
frame.start()

Visualizing Lists and Mutation5 min

http://www.codeskulptor.org/viz/#examples_lists_mutation.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
###################################
# Mutation vs. assignment
################
# Look alike, but different
a = [4, 5, 6]
b = [4, 5, 6]
print "Original a and b:", a, b
print "Are they same thing?", a is b
a[1] = 20
print "New a and b:", a, b
print
################
# Aliased
c = [4, 5, 6]
d = c
print "Original c and d:", c, d
print "Are they same thing?", c is d
c[1] = 20
print "New c and d:", c, d
print
################
# Copied
e = [4, 5, 6]
f = list(e)
print "Original e and f:", e, f
print "Are they same thing?", e is f
e[1] = 20
print "New e and f:", e, f
print
###################################
# Interaction with globals
a = [4, 5, 6]
def mutate_part(x):
a[1] = x
def assign_whole(x):
a = x
def assign_whole_global(x):
global a
a = x
mutate_part(100)
print a
assign_whole(200)
print a
assign_whole_global(300)
print a

Programming Tips - 43 min

http://www.codeskulptor.org/#examples-tips4.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
###################################
# Lists (mutable) vs. tuples (immutable)
print [4, 5, 6]
print (4, 5, 6)
print type([4, 5, 6])
print type((4, 5, 6))
a = [4, 5, 6]
a[1] = 100
print a
b = (4, 5, 6)
b[1] = 100
print b

Practice Exercises for Keyboard (optional)10 min

Quiz: Quiz 4b9 questions

QUIZ
Quiz 4b
9 questions
To Pass70% or higher
Attempts3 every 8 hours
Deadline
November 19, 11:59 PM PST

1 point
1.In Python, [1, 2, 3] is of type list. What is the name of the type of (1, 2, 3)?


Pair


Triple


Array


Tuple


Set


1 point
2.Which of the following types of data are immutable in Python?


Tuples


Strings


Numbers


Lists


Booleans


1 point
3.Which of the following functions must include a global point declaration in order to change the global variable point?

1
2
3
4
5
6
point = [0, 0]
def function1():
point[0] += 1
point[1] += 2
def function2():
point = [50, 50]


function2


function1


1 point
4.Consider the following three similar programs. Read them carefully to observe their differences.

1
2
3
4
5
a = range(5)
def mutate(a):
a[3] = 100
mutate(a)
print a[3]

1
2
3
4
5
a = range(5)
def mutate(b):
a[3] = 100
mutate(a)
print a[3]
1
2
3
4
5
a = range(5)
def mutate(b):
b[3] = 100
mutate(a)
print a[3]

We would like to know whether these all accomplish the same thing. What are the three values, respectively, printed by these three pieces of code? Separate the values only with spaces.




1 point
5.In our program, the variable position represents a 2D position on the canvas. We want to be able to change the position by some amount in variable delta. Why is the following code snippet incorrect?

1
2
3
4
position = [50, 50]
delta = [1, -2]
position = position + delta

Note that the ellipses represent that we might have code in between what is shown, but such code is irrelevant and omitted.


The numbers in position cannot be changed.


One of the elements of delta is negative.


The + operator on lists does not mean addition of the numbers in a list.


Lists do not support the + operator.


1 point
6.Consider the following program.

1
2
3
4
5
6
7
8
a = ["green", "blue", "white", "black"]
b = a
c = list(a)
d = c
a[3] = "red"
c[2] = a[1]
b = a[1 : 3]
b[1] = c[2]

At the end of this code, to how many list objects do the variables refer?

If you run the code and print the variables’ values, you can begin to answer this question. After all, if two variables print differently, they certainly can’t refer to the same object. However, if two variables print the same, you still need to determine whether they refer to the same object. One way is to step through the code while drawing reference diagrams. Another is to mutate one and see if others also mutate.


1 — The four variables each refer to the same list.


3


2


4 — The four variables each refer to different lists.


1 point
7.Convert the following specification into code. Do the point and rectangle ever overlap?

A point starts at [10, 20]. It repeatedly changes position by [3, 0.7] — e.g., under button or timer control. Meanwhile, a rectangle stays in place. Its corners are at [50, 50] (upper left), [180, 50] (upper right), [180, 140] (lower right), and [50, 140] (lower left).

To check for overlap, i.e., collision, just run your code and check visually. You do not need to implement a point-rectangle collision test. However, we encourage you to think about how you would implement such a test.


Yes


No


1 point
8.Assume we are using acceleration control for a spaceship in a game. That is, we regularly have the following updates:

The position is incremented by the time interval multiplied by the velocity. This happens on each draw event.
The velocity is incremented by the time interval multiplied by the acceleration. This happens on each draw event.
The acceleration is periodically incremented by some fixed vector (the same vector for each step). This could happen on keyboard or timer events.
Assume that, initially, the ship is stationary and subject to no acceleration. What sort of trajectory will the spaceship fly in?

Either figure this out mathematically, or implement it in CodeSkulptor and see what happens.


Unpredictable


A non-linear, smooth curve


Spiral


A straight line


1 point
9.Write a Python program that initializes a global variable to 5. The keydown event handler updates this global variable by doubling it, while the keyup event handler updates it by decrementing it by 3.

What is the value of the global variable after 12 separate key presses, i.e., pressing and releasing one key at a time, and repeating this 12 times in total?

To test your code, the global variable’s value should be 35 after 4 key presses.



Mini-project #4 - Pong

Mini-project Video11 min

http://www.codeskulptor.org/#examples-pong_template.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# Implementation of classic arcade game Pong
import simplegui
import random
# initialize globals - pos and vel encode vertical info for paddles
WIDTH = 600
HEIGHT = 400
BALL_RADIUS = 20
PAD_WIDTH = 8
PAD_HEIGHT = 80
HALF_PAD_WIDTH = PAD_WIDTH / 2
HALF_PAD_HEIGHT = PAD_HEIGHT / 2
LEFT = False
RIGHT = True
# initialize ball_pos and ball_vel for new bal in middle of table
# if direction is RIGHT, the ball's velocity is upper right, else upper left
def spawn_ball(direction):
global ball_pos, ball_vel # these are vectors stored as lists
# define event handlers
def new_game():
global paddle1_pos, paddle2_pos, paddle1_vel, paddle2_vel # these are numbers
global score1, score2 # these are ints
def draw(canvas):
global score1, score2, paddle1_pos, paddle2_pos, ball_pos, ball_vel
# draw mid line and gutters
canvas.draw_line([WIDTH / 2, 0],[WIDTH / 2, HEIGHT], 1, "White")
canvas.draw_line([PAD_WIDTH, 0],[PAD_WIDTH, HEIGHT], 1, "White")
canvas.draw_line([WIDTH - PAD_WIDTH, 0],[WIDTH - PAD_WIDTH, HEIGHT], 1, "White")
# update ball
# draw ball
# update paddle's vertical position, keep paddle on the screen
# draw paddles
# determine whether paddle and ball collide
# draw scores
def keydown(key):
global paddle1_vel, paddle2_vel
def keyup(key):
global paddle1_vel, paddle2_vel
# create frame
frame = simplegui.create_frame("Pong", WIDTH, HEIGHT)
frame.set_draw_handler(draw)
frame.set_keydown_handler(keydown)
frame.set_keyup_handler(keyup)
# start frame
new_game()
frame.start()

Mini-project Description10 min

Code Clinic Tips10 min

Peer-graded Assignment: Pong2h

http://www.codeskulptor.org/#user43_6MWjxkY0pr_0.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# Implementation of classic arcade game Pong
import simplegui
import random
# initialize globals - pos and vel encode vertical info for paddles
WIDTH = 600
HEIGHT = 400
BALL_RADIUS = 20
PAD_WIDTH = 8
PAD_HEIGHT = 80
HALF_PAD_WIDTH = PAD_WIDTH / 2
HALF_PAD_HEIGHT = PAD_HEIGHT / 2
LEFT = False
RIGHT = True
ball_line_width = 1
ball_pos = [WIDTH / 2, HEIGHT / 2]
ball_vel = [-1, -1] # pixels per tick
time = 0
paddle1_pos = HEIGHT / 2
paddle2_pos = HEIGHT / 2
paddle1_vel, paddle2_vel = 0, 0
score1, score2 = 0, 0
# initialize ball_pos and ball_vel for new bal in middle of table
# if direction is RIGHT, the ball's velocity is upper right, else upper left
def spawn_ball(direction):
global ball_pos, ball_vel # these are vectors stored as lists
ball_pos = [WIDTH / 2, HEIGHT / 2]
ball_vel[1] = - random.randrange(1, 3)
if direction == RIGHT:
ball_vel[0] = (random.randrange(2, 4))
#pass
if direction == LEFT:
ball_vel[0] = - (random.randrange(2, 4))
#pass
# define event handlers
def new_game():
global paddle1_pos, paddle2_pos, paddle1_vel, paddle2_vel # these are numbers
global score1, score2 # these are ints
score1, score2 = 0, 0
spawn_ball(RIGHT)
def draw(canvas):
global score1, score2, paddle1_pos, paddle2_pos, ball_pos, ball_vel
# draw mid line and gutters
canvas.draw_line([WIDTH / 2, 0],[WIDTH / 2, HEIGHT], 1, "White")
canvas.draw_line([PAD_WIDTH, 0],[PAD_WIDTH, HEIGHT], 1, "White")
canvas.draw_line([WIDTH - PAD_WIDTH, 0],[WIDTH - PAD_WIDTH, HEIGHT], 1, "White")
# hit the top or bottom
if (ball_pos[1] + BALL_RADIUS + ball_line_width >= HEIGHT) or \
(ball_pos[1] - BALL_RADIUS - ball_line_width <= 0):
ball_vel[1] = - ball_vel[1]
# update ball
ball_pos[0] += ball_vel[0]
ball_pos[1] += ball_vel[1]
# draw ball
canvas.draw_circle(ball_pos, BALL_RADIUS, ball_line_width, 'White', 'White')
# update paddle's vertical position, keep paddle on the screen
# draw paddles
if paddle1_pos + paddle1_vel >= HALF_PAD_HEIGHT and \
paddle1_pos + paddle1_vel <= HEIGHT - HALF_PAD_HEIGHT:
paddle1_pos += paddle1_vel
if paddle2_pos + paddle2_vel >= HALF_PAD_HEIGHT and \
paddle2_pos + paddle2_vel <= HEIGHT - HALF_PAD_HEIGHT:
paddle2_pos += paddle2_vel
#print paddle2_pos - HALF_PAD_HEIGHT
canvas.draw_polygon([[0, paddle1_pos - HALF_PAD_HEIGHT], \
[PAD_WIDTH, paddle1_pos - HALF_PAD_HEIGHT], \
[PAD_WIDTH, paddle1_pos + HALF_PAD_HEIGHT], \
[0, paddle1_pos + HALF_PAD_HEIGHT]], 1, 'White', 'White')
canvas.draw_polygon([[WIDTH - PAD_WIDTH, paddle2_pos - HALF_PAD_HEIGHT], \
[WIDTH, paddle2_pos - HALF_PAD_HEIGHT], \
[WIDTH, paddle2_pos + HALF_PAD_HEIGHT], \
[WIDTH - PAD_WIDTH, paddle2_pos + HALF_PAD_HEIGHT]], 1, 'White', 'White')
# determine whether paddle and ball collide
# hit the gutters
if (ball_pos[0] + BALL_RADIUS + ball_line_width >= WIDTH - PAD_WIDTH):
# hit the paddle2
if ball_pos[1] <= paddle2_pos + HALF_PAD_HEIGHT and \
ball_pos[1] >= paddle2_pos - HALF_PAD_HEIGHT:
ball_vel[0] = - 1.1 * ball_vel[0]
ball_vel[1] = 1.1 * ball_vel[1]
else:
score1 += 1
spawn_ball(LEFT)
if (ball_pos[0] - BALL_RADIUS - ball_line_width <= PAD_WIDTH):
# hit the paddle1
if ball_pos[1] <= paddle1_pos + HALF_PAD_HEIGHT and \
ball_pos[1] >= paddle1_pos - HALF_PAD_HEIGHT:
ball_vel[0] = - 1.1 * ball_vel[0]
ball_vel[1] = 1.1 * ball_vel[1]
else:
score2 += 1
spawn_ball(RIGHT)
#print ball_vel[0]
# draw scores
canvas.draw_text(str(score1), (WIDTH/4, HEIGHT/4), 50, 'White')
canvas.draw_text(str(score2), (WIDTH*3/4, HEIGHT/4), 50, 'White')
def keydown(key):
global paddle1_vel, paddle2_vel
vel = 4
# palyer 1
if key == simplegui.KEY_MAP["w"]:
paddle1_vel -= vel
if key == simplegui.KEY_MAP["s"]:
paddle1_vel += vel
if key == simplegui.KEY_MAP["w"] and key == simplegui.KEY_MAP["s"]:
pass
# player 2
if key == simplegui.KEY_MAP["up"]:
paddle2_vel -= vel
if key == simplegui.KEY_MAP["down"]:
paddle2_vel += vel
if key == simplegui.KEY_MAP["down"] and key == simplegui.KEY_MAP["up"]:
pass
def keyup(key):
global paddle1_vel, paddle2_vel
# palyer 1
if key == simplegui.KEY_MAP["w"]:
paddle1_vel = 0
if key == simplegui.KEY_MAP["s"]:
paddle1_vel = 0
if key == simplegui.KEY_MAP["w"] and key == simplegui.KEY_MAP["s"]:
pass
# player 2
if key == simplegui.KEY_MAP["up"]:
paddle2_vel = 0
if key == simplegui.KEY_MAP["down"]:
paddle2_vel = 0
if key == simplegui.KEY_MAP["down"] and key == simplegui.KEY_MAP["up"]:
pass
# create frame
frame = simplegui.create_frame("Pong", WIDTH, HEIGHT)
frame.set_draw_handler(draw)
frame.set_keydown_handler(keydown)
frame.set_keyup_handler(keyup)
new_game = frame.add_button('Restart', new_game, 100)
# start frame
#new_game()
frame.start()

http://www.codeskulptor.org/#user43_6MWjxkY0pr_1.py

1
2
3
4
5
6
7
def new_game():
global paddle1_pos, paddle2_pos, paddle1_vel, paddle2_vel # these are numbers
global score1, score2 # these are ints
paddle1_pos = HEIGHT / 2
paddle2_pos = HEIGHT / 2
score1, score2 = 0, 0
spawn_ball(RIGHT)

Review Your Peers: Pong

An Introduction to Interactive Programming in Python (Part 2)

Lecture slides can be found [here]
Coursera can be found here

About this course: This two-part course is designed to help students with very little or no computing background learn the basics of building simple interactive applications. Our language of choice, Python, is an easy-to learn, high-level computer language that is used in many of the computational courses offered on Coursera. To make learning Python easy, we have developed a new browser-based programming environment that makes developing interactive applications in Python simple. These applications will involve windows whose contents are graphical and respond to buttons, the keyboard and the mouse.

In part 2 of this course, we will introduce more elements of programming (such as list, dictionaries, and loops) and then use these elements to create games such as Blackjack. Part 1 of this class will culminate in building a version of the classic arcade game “Asteroids”. Upon completing this course, you will be able to write small, but interesting Python programs. The next course in the specialization will begin to introduce a more principled approach to writing programs and solving computational problems that will allow you to write larger and more complex programs.

Week 5 - Mouse input, list methods, dictionaries

Week 5a - Mouse Input and More Lists

Introduction2 min

Mouse input12 min

http://www.codeskulptor.org/#examples-mouse_input.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# Examples of mouse input
import simplegui
import math
# intialize globals
WIDTH = 450
HEIGHT = 300
ball_pos = [WIDTH / 2, HEIGHT / 2]
BALL_RADIUS = 15
ball_color = "Red"
# helper function
def distance(p, q):
return math.sqrt( (p[0] - q[0]) ** 2 + (p[1] - q[1]) ** 2)
# define event handler for mouse click, draw
def click(pos):
global ball_pos, ball_color
if distance(pos, ball_pos) < BALL_RADIUS:
ball_color = "Green"
else:
ball_pos = list(pos)
ball_color = "Red"
def draw(canvas):
canvas.draw_circle(ball_pos, BALL_RADIUS, 1, "Black", ball_color)
# create frame
frame = simplegui.create_frame("Mouse selection", WIDTH, HEIGHT)
frame.set_canvas_background("White")
# register event handler
frame.set_mouseclick_handler(click)
frame.set_draw_handler(draw)
# start frame
frame.start()

List Methods11 min

http://www.codeskulptor.org/#examples-list_methods.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# Simple task list
import simplegui
tasks = []
# Handler for button
def clear():
global tasks
tasks = []
# Handler for new task
def new(task):
tasks.append(task)
# Handler for remove number
def remove_num(tasknum):
n = int(tasknum)
if n > 0 and n <= len(tasks):
tasks.pop(n-1)
# Handler for remove name
def remove_name(taskname):
if taskname in tasks:
tasks.remove(taskname)
# Handler to draw on canvas
def draw(canvas):
n = 1
for task in tasks:
pos = 30 * n
canvas.draw_text(str(n) + ": " + task, [5, pos], 24, "White")
n += 1
# Create a frame and assign callbacks to event handlers
frame = simplegui.create_frame("Task List", 600, 400)
frame.add_input("New task:", new, 200)
frame.add_input("Remove task number:", remove_num, 200)
frame.add_input("Remove task:", remove_name, 200)
frame.add_button("Clear All", clear)
frame.set_draw_handler(draw)
# Start the frame animation
frame.start()

List Examples11 min

http://www.codeskulptor.org/#examples-list_of_balls.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# Examples of mouse input
import simplegui
import math
# intialize globals
width = 450
height = 300
ball_list = []
ball_radius = 15
ball_color = "Red"
# helper function
def distance(p, q):
return math.sqrt((p[0] - q[0]) ** 2 + (p[1] - q[1]) ** 2)
# define event handler for mouse click, draw
def click(pos):
ball_list.append(pos)
# if distance(ball_pos, pos) < ball_radius:
# if ball_color == "Red":
# ball_color = "Green"
# else:
# ball_pos = [pos[0], pos[1]]
# ball_color = "Red"
def draw(canvas):
for ball_pos in ball_list:
canvas.draw_circle(ball_pos, ball_radius, 1, "Black", ball_color)
# create frame
frame = simplegui.create_frame("Mouse selection", width, height)
frame.set_canvas_background("White")
# register event handler
frame.set_mouseclick_handler(click)
frame.set_draw_handler(draw)
# start frame
frame.start()

http://www.codeskulptor.org/#examples-list_selection.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# Examples of mouse input
import simplegui
import math
# intialize globals
width = 450
height = 300
ball_list = []
ball_radius = 15
# helper function
def distance(p, q):
return math.sqrt((p[0] - q[0]) ** 2 + (p[1] - q[1]) ** 2)
# define event handler for mouse click, draw
def click(pos):
changed = False
for ball in ball_list:
if distance([ball[0], ball[1]], pos) < ball_radius:
ball[2] = "Green"
changed = True
if not changed:
ball_list.append([pos[0], pos[1], "Red"])
def draw(canvas):
for ball in ball_list:
canvas.draw_circle([ball[0], ball[1]], ball_radius, 1, "Black", ball[2])
# create frame
frame = simplegui.create_frame("Mouse selection", width, height)
frame.set_canvas_background("White")
# register event handler
frame.set_mouseclick_handler(click)
frame.set_draw_handler(draw)
# start frame
frame.start()

http://www.codeskulptor.org/#examples-list_removal.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# Examples of mouse input
import simplegui
import math
# intialize globals
width = 450
height = 300
ball_list = []
ball_radius = 15
ball_color = "Red"
# helper function
def distance(p, q):
return math.sqrt((p[0] - q[0]) ** 2 + (p[1] - q[1]) ** 2)
# define event handler for mouse click, draw
def click(pos):
remove = []
for ball in ball_list:
if distance(ball, pos) < ball_radius:
remove.append(ball)
if remove == []:
ball_list.append(pos)
else:
for ball in remove:
ball_list.pop(ball_list.index(ball))
def draw(canvas):
for ball in ball_list:
canvas.draw_circle([ball[0], ball[1]], ball_radius, 1, "Black", ball_color)
# create frame
frame = simplegui.create_frame("Mouse selection", width, height)
frame.set_canvas_background("White")
# register event handler
frame.set_mouseclick_handler(click)
frame.set_draw_handler(draw)
# start frame
frame.start()

Iteration12 min

http://www.codeskulptor.org/#examples-iteration.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# Iterating over lists
def count_odd(numbers):
count = 0
for num in numbers:
if num % 2 == 1:
count += 1
return count
def check_odd(numbers):
for num in numbers:
if num % 2 == 1:
return True
return False
def remove_odd(numbers):
for num in numbers:
if num % 2 == 1:
numbers.remove(num)
def remove_odd2(numbers):
remove = []
for num in numbers:
if num % 2 == 1:
remove.append(numbers.index(num))
for idx in remove:
numbers.pop(idx)
def remove_odd3(numbers):
remove = []
for num in numbers:
if num % 2 == 1:
remove.append(num)
for num in remove:
numbers.remove(num)
def remove_odd4(numbers):
newnums = []
for num in numbers:
if num % 2 == 0:
newnums.append(num)
return newnums
def remove_last_odd(numbers):
has_odd = False
last_odd = 0
for num in numbers:
if num % 2 == 1:
has_odd = True
last_odd = num
if has_odd:
numbers.remove(last_odd)
def run():
numbers = [1, 7, 2, 34, 8, 7, 2, 5, 14, 22, 93, 48, 76, 15, 7]
print numbers
remove_last_odd(numbers)
print numbers
run()

Practice Exercises for Mouse and List Methods (optional)10 min

Quiz: Quiz 5a9 questions

QUIZ
Quiz 5a
9 questions
To Pass70% or higher
Attempts3 every 8 hours
Deadline
November 19, 11:59 PM PST

1 point
1.What is the type of the parameter for a mouseclick handler?

Refer to the CodeSkulptor documentation.


There is no parameter.


Boolean


String


Number


List


Tuple


1 point
2.Which of the following expressions mutate, i.e., change, list my_list? If you’ve forgotten what the operations do, you can look in the CodeSkulptor documentation.


my_list + [10, 20]


my_list.reverse()


my_list.append(10)


another_list.extend(my_list)


my_list.extend([10, 20])


1 point
3.We want to remove the element at the front of a list. For example, we want the following code to print “apple” and [“pear”, “blueberry”], respectively. What function or method call should replace the question marks?

1
2
3
fruits = ["apple", "pear", "blueberry"]
fruit = ???
print fruit, fruits


fruits.remove(0)


fruits[1:]


fruits[0]


fruits.pop(0)


fruits.pop()


fruits.remove(“apple”)


1 point
4.Which of the following uses of range() will generate the list [2, 5, 8, 11, 14]?

First, think about what each of these returns, but also try each in CodeSkulptor.


range(2, 15) * 3


range(1, 15, 3)


range(2, 15, 3)


1 point
5.To correctly compute the product of a list numbers of numbers, what statement should replace the question marks?

1
2
3
4
numbers = …
???
for n in numbers:
product *= n


product = numbers[1]


product = numbers[0]


product = 1


product = []


product = 0


1 point
6.We can loop over strings, too!

The following incomplete function is a simple, but inefficient, way to reverse a string. What line of code needs to replace the questions marks for the code to work correctly?

1
2
3
4
5
6
7
def reverse_string(s):
"""Returns the reversal of the given string."""
???
for char in s:
result = char + result
return result
print reverse_string("hello")


result = []


result = “”


result = 0


result = “ “


1
point

  1. Imagine a game on a map. At the beginning, we might want to randomly assign each player a starting point. Which of the following expressions may we use in place of the question marks to correctly implement this functionality?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import random
    def random_point():
    """Returns a random point on a 100x100 grid."""
    return (random.randrange(100), random.randrange(100))
    def starting_points(players):
    """Returns a list of random points, one for each player."""
    points = []
    for player in players:
    point = random_point()
    ???
    return points


point.append(points)


points.append(point)


points + point


points += point


points.extend(point)


point.extend(points)


1 point
8.The following function is supposed to check whether the given list of numbers is in ascending order. For example, we want is_ascending([2, 6, 9, 12, 400]) to return True while is_ascending([4, 8, 2, 13]) should return False.

1
2
3
4
5
6
def is_ascending(numbers):
"""Returns whether the given list of numbers is in ascending order."""
for i in range(len(numbers)):
if numbers[i+1] < numbers[i]:
return False
return True

However, the function doesn’t quite work. Try it on the suggested tests to verify this for yourself. The easiest fix is to make a small change to the highlighted code. What should it be replaced with?


range(len(numbers)) - 1


range(len(numbers) - 1)


range(len(numbers - 1))


range(1, len(numbers))


1 point
9.Turn the following English description into code:

Create a list with two numbers, 0 and 1, respectively.
For 40 times, add to the end of the list the sum of the last two numbers.
What is the last number in the list?

To test your code, if you repeat 10 times, rather than 40, your answer should be 89.



Week 5b - Dictionaries and Images

Dictionaries12 min

http://www.codeskulptor.org/#examples-dictionaries.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# Cipher
import simplegui
CIPHER = {'a': 'x', 'b': 'c', 'c': 'r', 'd': 'm', 'e': 'l'}
message = ""
# Encode button
def encode():
emsg = ""
for ch in message:
emsg += CIPHER[ch]
print message, "encodes to", emsg
# Decode button
def decode():
dmsg = ""
for ch in message:
for key, value in CIPHER.items():
if ch == value:
dmsg += key
print message, "decodes to", dmsg
# Update message input
def newmsg(msg):
global message
message = msg
label.set_text(msg)
# Create a frame and assign callbacks to event handlers
frame = simplegui.create_frame("Cipher", 2, 200, 200)
frame.add_input("Message:", newmsg, 200)
label = frame.add_label("", 200)
frame.add_button("Encode", encode)
frame.add_button("Decode", decode)
# Start the frame animation
frame.start()

Images11 min

http://www.codeskulptor.org/#examples-images.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# Demonstration of a magnifier on a map
import simplegui
# 1521x1818 pixel map of native American language
# source - Gutenberg project
image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/gutenberg.jpg")
# Image dimensions
MAP_WIDTH = 1521
MAP_HEIGHT = 1818
# Scaling factor
SCALE = 3
# Canvas size
CAN_WIDTH = MAP_WIDTH // SCALE
CAN_HEIGHT = MAP_HEIGHT // SCALE
# Size of magnifier pane and initial center
MAG_SIZE = 120
mag_pos = [CAN_WIDTH // 2, CAN_HEIGHT // 2]
# Event handlers
# Move magnifier to clicked position
def click(pos):
global mag_pos
mag_pos = list(pos)
# Draw map and magnified region
def draw(canvas):
# Draw map
canvas.draw_image(image,
[MAP_WIDTH // 2, MAP_HEIGHT // 2], [MAP_WIDTH, MAP_HEIGHT],
[CAN_WIDTH // 2, CAN_HEIGHT // 2], [CAN_WIDTH, CAN_HEIGHT])
# Draw magnifier
map_center = [SCALE * mag_pos[0], SCALE * mag_pos[1]]
map_rectangle = [MAG_SIZE, MAG_SIZE]
mag_center = mag_pos
mag_rectangle = [MAG_SIZE, MAG_SIZE]
canvas.draw_image(image, map_center, map_rectangle, mag_center, mag_rectangle)
# Create frame for scaled map
frame = simplegui.create_frame("Map magnifier", CAN_WIDTH, CAN_HEIGHT)
# register even handlers
frame.set_mouseclick_handler(click)
frame.set_draw_handler(draw)
# Start frame
frame.start()

Visualizing Iteration13 min

http://www.codeskulptor.org/viz/#examples_iteration_lists.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
def square_list1(numbers):
"""Returns a list of the squares of the numbers in the input."""
result = []
for n in numbers:
result.append(n ** 2)
return result
def square_list2(numbers):
"""Returns a list of the squares of the numbers in the input."""
return [n ** 2 for n in numbers]
print square_list1([4, 5, -2])
print square_list2([4, 5, -2])
def is_in_range(ball):
"""Returns whether the ball is in the desired range. """
return ball[0] >= 0 and ball[0] <= 100 and ball[1] >= 0 and ball[1] <= 100
def balls_in_range1(balls):
"""Returns a list of those input balls that are within the desired range."""
result = []
for ball in balls:
if is_in_range(ball):
result.append(ball)
return result
def balls_in_range2(balls):
return [ball for ball in balls if is_in_range(ball)]
print balls_in_range1([[-5,40], [30,20], [70,140], [60,50]])
print balls_in_range2([[-5,40], [30,20], [70,140], [60,50]])

http://www.codeskulptor.org/viz/#examples-dictionaries.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# Cipher
import simplegui
CIPHER = {'a': 'x', 'b': 'c', 'c': 'r', 'd': 'm', 'e': 'l'}
message = ""
# Encode button
def encode():
emsg = ""
for ch in message:
emsg += CIPHER[ch]
print message, "encodes to", emsg
# Decode button
def decode():
dmsg = ""
for ch in message:
for key, value in CIPHER.items():
if ch == value:
dmsg += key
print message, "decodes to", dmsg
# Update message input
def newmsg(msg):
global message
message = msg
label.set_text(msg)
# Create a frame and assign callbacks to event handlers
frame = simplegui.create_frame("Cipher", 2, 200, 200)
frame.add_input("Message:", newmsg, 200)
label = frame.add_label("", 200)
frame.add_button("Encode", encode)
frame.add_button("Decode", decode)
# Start the frame animation
frame.start()

Programming Tips - 510 min

Practice Exercises for Dictionaries and Images (optional)10 min

Quiz: Quiz 5b9 questions

QUIZ
Quiz 5b
9 questions
To Pass70% or higher
Attempts3 every 8 hours
Deadline
November 19, 11:59 PM PST

1 point
1.Which of the following expressions corresponds to a dictionary with no elements?


()


{}


None


[]


<>


dict()


1 point
2.Given an existing dictionary favorites, what Python statement adds the key “fruit” to this dictionary with the corresponding value “blackberry”?


favorites{“fruit” : “blackberry”}


favorites[“fruit” = “blackberry”]


favorites[“fruit” : “blackberry”]


favorites[“fruit”] = “blackberry”


favorites = {“fruit” : “blackberry”}


1 point
3.Keys in a dictionary can have which of the following types?


Lists


Booleans


Strings


Dictionaries


Numbers


Tuples


1 point
4.Values in a dictionary can have which of the following types?


Strings


Booleans


Tuples


Dictionaries


Numbers


Lists


1 point
5.We often want to loop over all the key/value pairs in a dictionary. Assume the variable my_dict stores a dictionary. One way of looping like this is as follows:

1
2
3
for key in my_dict:
value = my_dict[key]

However, there is a better way. We can instead write the following:

1
2
for key, value in ???:

What code should replace the question marks so that the two forms are equivalent?

Refer to the video on dictionaries or the CodeSkulptor documentation.


list(my_dict)


my_dict.values()


my_dict.items()


my_dict.keys()


my_dict.keys_values()


items(my_dict)


1 point
6.Conceptually, the purpose of a dictionary is to represent a relationship between two collections of data — each key in the dictionary is related to one value. Which of the following situations are instances of such a relationship?

Do not include situations where you have to introduce additional information in order to fit them into such a relationship.


Storing where each person lives


Storing a sensor’s data samples


Storing x and y coordinates of an arbitrary collection of 2-dimensional points


Storing x and y coordinates of 2-dimensional points taken from a function, so that each x coordinate occurs at most once.


1 point
7.In the previous quiz, you were asked to complete the following code:

1
2
3
4
5
6
7
8
9
10
11
import random
def random_point():
"""Returns a random point on a 100x100 grid."""
return (random.randrange(100), random.randrange(100))
def starting_points(players):
"""Returns a list of random points, one for each player."""
points = []
for player in players:
point = random_point()
???
return points

Now, we want to rewrite starting_points using a list comprehension. Which list comprehensions could replace the following question marks?

1
2
3
def starting_points(players):
"""Returns a list of random points, one for each player."""
return ???

Refer to this week’s “Visualizing iteration” video for examples of list comprehensions. Also, try each example in CodeSkulptor before answering the question.


[random_point for players]


[random_point(player) for player in players]


[for player in players: random_point()]


[random_point() for player in players]


[random_point() for p in players]


[random_point for player in players]


1 point
8.You have the following code. The goal is to display a portion of the image, rescaling it to fill the canvas.

1
2
3
4
5
6
7
8
9
10
11
12
import simplegui
frame_size = [200, 200]
image_size = [1521, 1818]
def draw(canvas):
canvas.draw_image(image, image_size,
[image_size[0] / 2, image_size[1] / 2],
[frame_size[0] / 2, frame_size[1] / 2],
frame_size)
frame = simplegui.create_frame("test", frame_size[0], frame_size[1])
frame.set_draw_handler(draw)
image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/gutenberg.jpg")
frame.start()

Run it, and observe that nothing is displayed in the frame. What is the problem?


The source arguments in draw_image are incorrect. We are trying to load pixels that are not within the image, and thus the draw fails.


The destination arguments in draw_image are incorrect. We aren’t specifying values that would draw the image on this size canvas.


The file doesn’t exist.


The file is not an image.


One or more of the draw_image arguments are of the wrong type.


1 point
9.Write a CodeSkulptor program that loads and draws the following image:

1
http://commondatastorage.googleapis.com/codeskulptor-assets/alphatest.png

with a source center of [220, 100] and a source size of [100, 100]. What one word appears in the canvas? If a letter is capitalized in the image, enter it as a capital.

Note that you do have to position the image as stated to see the correct word.



Mini-project #5 - Memory

Mini-project Video12 min

http://www.codeskulptor.org/#examples-memory_template.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# implementation of card game - Memory
import simplegui
import random
# helper function to initialize globals
def new_game():
pass
# define event handlers
def mouseclick(pos):
# add game state logic here
pass
# cards are logically 50x100 pixels in size
def draw(canvas):
pass
# create frame and add a button and labels
frame = simplegui.create_frame("Memory", 800, 100)
frame.add_button("Reset", new_game)
label = frame.add_label("Turns = 0")
# register event handlers
frame.set_mouseclick_handler(mouseclick)
frame.set_draw_handler(draw)
# get things rolling
new_game()
frame.start()
# Always remember to review the grading rubric

http://www.codeskulptor.org/#examples-memory_states.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# simple state example for Memory
import simplegui
# define event handlers
def new_game():
global state
state = 0
def buttonclick():
global state
if state == 0:
state = 1
elif state == 1:
state = 2
else:
state = 1
def draw(canvas):
canvas.draw_text(str(state) + " card exposed", [30, 62], 24, "White")
# create frame and add a button and labels
frame = simplegui.create_frame("Memory states", 200, 100)
frame.add_button("Restart", new_game, 200)
frame.add_button("Simulate mouse click", buttonclick, 200)
# register event handlers
frame.set_draw_handler(draw)
# get things rolling
new_game()
frame.start()

Mini-project Description10 min

http://www.codeskulptor.org/#examples-memory_template.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# implementation of card game - Memory
import simplegui
import random
# helper function to initialize globals
def new_game():
pass
# define event handlers
def mouseclick(pos):
# add game state logic here
pass
# cards are logically 50x100 pixels in size
def draw(canvas):
pass
# create frame and add a button and labels
frame = simplegui.create_frame("Memory", 800, 100)
frame.add_button("Reset", new_game)
label = frame.add_label("Turns = 0")
# register event handlers
frame.set_mouseclick_handler(mouseclick)
frame.set_draw_handler(draw)
# get things rolling
new_game()
frame.start()
# Always remember to review the grading rubric

Code Clinic Tips10 min

Peer-graded Assignment: Memory 2h

http://www.codeskulptor.org/#user43_L8JriAHgg6_0.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# implementation of card game - Memory
import simplegui
import random
num = 8
CardNumber = range(num)*2
exposed = [False]*len(CardNumber)
#exposed = [True, False]*(len(CardNumber)/2)
pre = None
post = None
counter = 0
# helper function to initialize globals
def new_game():
global CardNumber, state, counter, exposed
random.shuffle(CardNumber)
exposed = [False]*len(CardNumber)
state = 0
counter = 0
label.set_text("Turns = " + str(counter))
# define event handlers
def mouseclick(pos):
# add game state logic here
global exposed, state, pre, post, CardNumber, counter
idx = pos[0] / 50
if state == 0:
state = 1
exposed[idx] = True
pre = idx
counter = 1
elif state == 1:
if exposed[idx] == False:
exposed[idx] = True
state = 2
post = idx
else:
if exposed[idx] == False:
exposed[idx] = True
if CardNumber[pre]==CardNumber[post]:
exposed[pre] = True
exposed[post] = True
else:
exposed[pre] = False
exposed[post] = False
counter += 1
state = 1
pre = idx
label.set_text("Turns = " + str(counter))
#print state,counter
# cards are logically 50x100 pixels in size
def draw(canvas):
global CardNumber
for i in range(16):
if exposed[i]:
canvas.draw_text(str(CardNumber[i]), [9+50*i, 75], 72, "White")
else:
canvas.draw_polygon([(i*50, 0), (50+i*50, 0), (50+i*50, 100), (i*50, 100)], 2, "Red", "Green")
# create frame and add a button and labels
frame = simplegui.create_frame("Memory", 800, 100)
frame.add_button("Reset", new_game)
label = frame.add_label('Turns = 0')
# register event handlers
frame.set_mouseclick_handler(mouseclick)
frame.set_draw_handler(draw)
# get things rolling
new_game()
frame.start()
# Always remember to review the grading rubric

Review Your Peers: Memory

Week 6 - Classes and object-oriented programming

Learn the basics of object-oriented programming in Python using classes, work with tiled images

Week 6a - Classes

Object-oriented Programming - 19 min

http://www.codeskulptor.org/#examples-oo-character.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Character:
def __init__(self, name, initial_health):
self.name = name
self.health = initial_health
self.inventory = []
def __str__(self):
s = "Name: " + self.name
s += " Health: " + str(self.health)
s += " Inventory: " + str(self.inventory)
return s
def grab(self, item):
self.inventory.append(item)
def get_health(self):
return self.health
def example():
me = Character("Bob", 20)
print str(me)
me.grab("pencil")
me.grab("paper")
print str(me)
print "Health:", me.get_health()
example()

Object-oriented Programming - 2 8 min

http://www.codeskulptor.org/#examples-oo-ball.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# ball physics code for generic 2D domain
# the functions inside() and normal() encode the shape of the ennvironment
import simplegui
import random
import math
# Canvas size
width = 600
height = 400
# Ball traits
radius = 20
color = "White"
# math helper function
def dot(v, w):
return v[0] * w[0] + v[1] * w[1]
class RectangularDomain:
def __init__(self, width, height):
self.width = width
self.height = height
self.border = 2
# return if bounding circle is inside the domain
def inside(self, center, radius):
in_width = ((radius + self.border) < center[0] <
(self.width - self.border - radius))
in_height = ((radius + self.border) < center[1] <
(self.height - self.border - radius))
return in_width and in_height
# return a unit normal to the domain boundary point nearest center
def normal(self, center):
left_dist = center[0]
right_dist = self.width - center[0]
top_dist = center[1]
bottom_dist = self.height - center[1]
if left_dist < min(right_dist, top_dist, bottom_dist):
return (1, 0)
elif right_dist < min(left_dist, top_dist, bottom_dist):
return (-1, 0)
elif top_dist < min(bottom_dist, left_dist, right_dist):
return (0, 1)
else:
return (0, -1)
# return random location
def random_pos(self, radius):
x = random.randrange(radius, self.width - radius - self.border)
y = random.randrange(radius, self.height - radius - self.border)
return [x, y]
# Draw boundary of domain
def draw(self, canvas):
canvas.draw_polygon([[0, 0], [self.width, 0],
[self.width, self.height], [0, self.height]],
self.border*2, "Red")
class CircularDomain:
def __init__(self, center, radius):
self.center = center
self.radius = radius
self.border = 2
# return if bounding circle is inside the domain
def inside(self, center, radius):
dx = center[0] - self.center[0]
dy = center[1] - self.center[1]
dr = math.sqrt(dx ** 2 + dy ** 2)
return dr < (self.radius - radius - self.border)
# return a unit normal to the domain boundary point nearest center
def normal(self, center):
dx = center[0] - self.center[0]
dy = center[1] - self.center[1]
dr = math.sqrt(dx ** 2 + dy ** 2)
return [dx / dr, dy / dr]
# return random location
def random_pos(self, radius):
r = random.random() * (self.radius - radius - self.border)
theta = random.random() * 2 * math.pi
x = r * math.cos(theta) + self.center[0]
y = r * math.sin(theta) + self.center[1]
return [x, y]
# Draw boundary of domain
def draw(self, canvas):
canvas.draw_circle(self.center, self.radius, self.border*2, "Red")
class Ball:
def __init__(self, radius, color, domain):
self.radius = radius
self.color = color
self.domain = domain
self.pos = self.domain.random_pos(self.radius)
self.vel = [random.random() + .1, random.random() + .1]
# bounce
def reflect(self):
norm = self.domain.normal(self.pos)
norm_length = dot(self.vel, norm)
self.vel[0] = self.vel[0] - 2 * norm_length * norm[0]
self.vel[1] = self.vel[1] - 2 * norm_length * norm[1]
# update ball position
def update(self):
self.pos[0] += self.vel[0]
self.pos[1] += self.vel[1]
if not self.domain.inside(self.pos, self.radius):
self.reflect()
# draw
def draw(self, canvas):
canvas.draw_circle(self.pos, self.radius, 1,
self.color, self.color)
# generic update code for ball physics
def draw(canvas):
ball.update()
field.draw(canvas)
ball.draw(canvas)
field = RectangularDomain(width, height)
# field = CircularDomain([width/2, height/2], 180)
ball = Ball(radius, color, field)
frame = simplegui.create_frame("Ball physics", width, height)
frame.set_draw_handler(draw)
frame.start()

Working with Objects13 min

http://www.codeskulptor.org/#examples-particle_class.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# Particle class example used to simulate diffusion of molecules
import simplegui
import random
# global constants
WIDTH = 600
HEIGHT = 400
PARTICLE_RADIUS = 5
COLOR_LIST = ["Red", "Green", "Blue", "White"]
DIRECTION_LIST = [[1,0], [0, 1], [-1, 0], [0, -1]]
# definition of Particle class
class Particle:
# initializer for particles
def __init__(self, position, color):
self.position = position
self.color = color
# method that updates position of a particle
def move(self, offset):
self.position[0] += offset[0]
self.position[1] += offset[1]
# draw method for particles
def draw(self, canvas):
canvas.draw_circle(self.position, PARTICLE_RADIUS, 1, self.color, self.color)
# string method for particles
def __str__(self):
return "Particle with position = " + str(self.position) + " and color = " + self.color
# draw handler
def draw(canvas):
for p in particle_list:
p.move(random.choice(DIRECTION_LIST))
for p in particle_list:
p.draw(canvas)
# create frame and register draw handler
frame = simplegui.create_frame("Particle simulator", WIDTH, HEIGHT)
frame.set_draw_handler(draw)
# create a list of particles
particle_list = []
for i in range(100):
p = Particle([WIDTH / 2, HEIGHT / 2], random.choice(COLOR_LIST))
particle_list.append(p)
# start frame
frame.start()

http://www.codeskulptor.org/#examples-particle_testing_template.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# Testing template for Particle class
###################################################
# Student should add code for the Particle class here
###################################################
# Test code for the Particle class
p = Particle([20, 20], "Red")
print p
print type(p)
p.move([10, 20])
print p
p.move([-15, -25])
print p
print
q = Particle([15, 30], "Green")
print q
print type(q)
q.move([0, 0])
print q
###################################################
# Output from test
#Particle with position = [20, 20] and color = Red
#<class '__main__.Particle'>
#Particle with position = [30, 40] and color = Red
#Particle with position = [15, 15] and color = Red
#
#Particle with position = [15, 30] and color = Green
#<class '__main__.Particle'>
#Particle with position = [15, 30] and color = Green

Classes for Blackjack11 min

http://www.codeskulptor.org/#examples-blackjack.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# Mini-project #6 - Blackjack
import simplegui
import random
# load card sprite - 950x392 - source: jfitz.com
CARD_SIZE = (73, 98)
card_images = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/cards.jfitz.png")
CARD_BACK_SIZE = (71, 96)
card_back = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/card_back.png")
# initialize global variables
deck = []
in_play = False
outcome = ""
score = 0
# define globals for cards
SUITS = ['C', 'S', 'H', 'D']
RANKS = ['A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K']
VALUES = {'A':1, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9, 'T':10, 'J':10, 'Q':10, 'K':10}
# define card class
class Card:
def __init__(self, suit, rank):
if (suit in SUITS) and (rank in RANKS):
self.suit = suit
self.rank = rank
else:
print "Invalid card: ", self.suit, self.rank
def __str__(self):
return self.suit + self.rank
def get_suit(self):
return self.suit
def get_rank(self):
return self.rank
def draw(self, canvas, pos):
card_loc = (card_size[0] * (0.5 + RANKS.index(self.rank)), card_size[1] * (0.5 + SUITS.index(self.suit)))
canvas.draw_image(card_images, card_loc, card_size, [pos[0] + card_size[0] / 2, pos[1] + card_size[1] / 2], card_size)
# define hand class
class Hand:
def __init__(self):
pass # replace with your code
def __str__(self):
pass # replace with your code
def add_card(self, card):
pass # replace with your code
# count aces as 1, if the hand has an ace, then add 10 to hand value if don't bust
def get_value(self):
pass # replace with your code
def busted(self):
pass # replace with your code
def draw(self, canvas, p):
pass # replace with your code
# define deck class
class Deck:
def __init__(self):
pass # replace with your code
# add cards back to deck and shuffle
def shuffle(self):
pass # replace with your code
def deal_card(self):
pass # replace with your code
#define callbacks for buttons
def deal():
global outcome, in_play
# your code goes here
outcome = ""
in_play = True
def hit():
pass # replace with your code below
# if the hand is in play, hit the player
# if busted, assign an message to outcome, update in_play and score
def stand():
pass # replace with your code below
# if hand is in play, repeatedly hit dealer until his hand has value 17 or more
# assign a message to outcome, update in_play and score
def draw(canvas):
pass # replace with your code below
# initialization frame
frame = simplegui.create_frame("Blackjack", 600, 600)
frame.set_canvas_background("Green")
#create buttons and canvas callback
frame.add_button("Deal", deal, 200)
frame.add_button("Hit", hit, 200)
frame.add_button("Stand", stand, 200)
frame.set_draw_handler(draw)
# deal an initial hand
# get things rolling
frame.start()
# Grading rubric - 18 pts total (scaled to 100)
# 1 pt - The program opens a frame with the title "Blackjack" appearing on the canvas.
# 3 pts - The program displays 3 buttons ("Deal", "Hit" and "Stand") in the control area. (1 pt per button)
# 2 pts - The program graphically displays the player's hand using card sprites.
# (1 pt if text is displayed in the console instead)
# 2 pts - The program graphically displays the dealer's hand using card sprites.
# Displaying both of the dealer's cards face up is allowable when evaluating this bullet.
# (1 pt if text displayed in the console instead)
# 1 pt - Hitting the "Deal" button deals out new hands to the player and dealer.
# 1 pt - Hitting the "Hit" button deals another card to the player.
# 1 pt - Hitting the "Stand" button deals cards to the dealer as necessary.
# 1 pt - The program correctly recognizes the player busting.
# 1 pt - The program correctly recognizes the dealer busting.
# 1 pt - The program correctly computes hand values and declares a winner.
# Evalute based on player/dealer winner messages.
# 1 pt - The dealer's hole card is hidden until the hand is over when it is then displayed.
# 2 pts - The program accurately prompts the player for an action with the messages
# "Hit or stand?" and "New deal?". (1 pt per message)
# 1 pt - The program keeps score correctly.

Practice Exercises for Classes (part 1) (optional)10 min

Practice Exercise for Avatar class (optional)10 min

Quiz: Quiz 6a8 questions

QUIZ
Quiz 6a
8 questions
To Pass70% or higher
Attempts3 every 8 hours
Deadline
November 26, 11:59 PM PST

1 point
1.Every class definition should include an initializer method. What is the name of the initializer method?

Refer to the first object-oriented programming video.

Note: While you can get away with not having an initializer method, doing so almost always implies using techniques beyond the scope of this course or bad program design. So, beginners should always define an initializer method.


init


The same as the name of the class


init (1 underscore on each side)


init (2 underscores on each side)


1 point
2.In Python, what is the main difference between a function and a method?


Methods are defined in built-in library modules, while functions are defined in your own code.


There is no difference. They are interchangeable terms.


Functions are defined outside of classes, while methods are defined inside of and part of classes.


Methods have a parameter named self, while functions do not.


1 point
3.As an example class, consider the following code from one of the videos:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Character:
def __init__(self, name, initial_health):
self.name = name
self.health = initial_health
self.inventory = []
def __str__(self):
s = "Name: " + self.name
s += " Health: " + str(self.health)
s += " Inventory: " + str(self.inventory)
return s
def grab(self, item):
self.inventory.append(item)
def get_health(self):
return self.health

What does the self parameter represent?


An object (instance) of the Character class


Whatever happens to be passed to it.


The method that is being defined


The Character class


1 point
4.Assume you have the following class and method definition, parts of which have been omitted.

1
2
3
4
5
6
class My_Class:
def my_method(self, value1, value2):
"""Assumes its inputs are two values and does something."""
my_object = My_Class()

The last line defines the variable my_object as an object of My_Class class. Which of the following is proper syntax for using the method on this object?


My_Class.my_method(my_object, 1, 2)


my_method(my_object, 1, 2)


My_Class.my_object.my_method(1, 2)


my_object.my_method(1, 2)


my_method(My_Class, 1, 2)


1 point
5.We want to have balls that move around. Which of the following designs represents encapsulation best?


1
2
3
4
5
6
7
8
9
10
# centers : A list of points, the balls' center points
centers = …
# radii : A list of numbers, the balls' radii
radii = …
def move(ball_number, move_vector):
"""
Changes the position of the ball by the given vector.
"""
centers[ball_number][0] += move_vector[0]
centers[ball_number][1] += move_vector[1]


1
2
3
4
5
6
7
8
9
10
11
12
class Ball:
def __init__(self, c, r):
self.center = c
self.radius = r
def move(self, move_vector):
"""
Changes the position of the ball by the given vector.
"""
self.center[0] += move_vector[0]
self.center[1] += move_vector[1]
# balls : A list of Ball objects
balls = …


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Ball:
def __init__(self, c, r):
self.center = c
self.radius = r
def get_position(self):
return self.center
def set_position(self, new_position):
self.center = new_position
# balls : A list of Ball objects
balls = …
def move(ball, move_vector):
"""
Changes the position of the ball by the given vector.
"""
position = ball.get_position()
position[0] += move_vector[0]
position[1] += move_vector[1]
ball.set_position(position)


1
2
3
4
5
6
7
8
9
10
11
12
class Ball:
def __init__(self, c, r):
self.center = c
self.radius = r
# balls : A list of Ball objects
balls = …
def move(ball, move_vector):
"""
Changes the position of the ball by the given vector.
"""
ball.center[0] += move_vector[0]
ball.center[1] += move_vector[1]



1 point
6.A common feature in many object-oriented languages is method overloading. In this quiz question, you will learn by example what overloading is and whether or not Python supports it.

Turn the following English description into code.

Start a class definition. We’ll call the class Overload.
Define an init method. Along with the standard self it has one parameter. The method does nothing useful for this example — use the Python do-nothing statement pass for the body.
Define a second init method. Along with self it has two parameters. This method also does nothing useful.
Outside of the class, we want to create two Overload objects. If Python supports overloading, you will be able to create an Overload object with one argument, and create another Overload object with two arguments. Does Python support overloading?


No


Yes


1 point
7.First, complete the following class definition:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class BankAccount:
def __init__(self, initial_balance):
"""Creates an account with the given balance."""
self.balance = initial_balance
self.fees = 0
def deposit(self, amount):
"""Deposits the amount into the account."""
self.balance += amount - self.fees
def withdraw(self, amount):
"""
Withdraws the amount from the account. Each withdrawal
resulting in a negative balance also deducts a penalty
fee of 5 dollars from the balance.
"""
self.balance -= amount
if self.balance < 0:
self.fees += 5
def get_balance(self):
"""Returns the current balance in the account."""
return self.balance
def get_fees(self):
"""Returns the total fees ever deducted from the account."""
return self.fees

The deposit and withdraw methods each change the account balance. The withdraw method also deducts a fee of 5 dollars from the balance if the withdrawal (before any fees) results in a negative balance. Since we also have the method get_fees you will need to have a variable to keep track of the fees paid.

Here’s one possible test of the class. It should print the values 10 and 5, respectively, since the withdrawal incurs a fee of 5 dollars.

1
2
3
4
my_account = BankAccount(10)
my_account.withdraw(15)
my_account.deposit(20)
print my_account.get_balance(), my_account.get_fees()

Copy-and-paste the following much longer test. What two numbers are printed at the end? Enter the two numbers, separated only by spaces.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
my_account = BankAccount(10)
my_account.withdraw(5)
my_account.deposit(10)
my_account.withdraw(5)
my_account.withdraw(15)
my_account.deposit(20)
my_account.withdraw(5)
my_account.deposit(10)
my_account.deposit(20)
my_account.withdraw(15)
my_account.deposit(30)
my_account.withdraw(10)
my_account.withdraw(15)
my_account.deposit(10)
my_account.withdraw(50)
my_account.deposit(30)
my_account.withdraw(15)
my_account.deposit(10)
my_account.withdraw(5)
my_account.deposit(20)
my_account.withdraw(15)
my_account.deposit(10)
my_account.deposit(30)
my_account.withdraw(25)
my_account.withdraw(5)
my_account.deposit(10)
my_account.withdraw(15)
my_account.deposit(10)
my_account.withdraw(10)
my_account.withdraw(15)
my_account.deposit(10)
my_account.deposit(30)
my_account.withdraw(25)
my_account.withdraw(10)
my_account.deposit(20)
my_account.deposit(10)
my_account.withdraw(5)
my_account.withdraw(15)
my_account.deposit(10)
my_account.withdraw(5)
my_account.withdraw(15)
my_account.deposit(10)
my_account.withdraw(5)
print my_account.get_balance(), my_account.get_fees()




1 point
8.We will again use the BankAccount class from the previous problem. You should be able to use the same definition for both problems.

Of course, a bank with only one account will go out of business, so we want our BankAccount class to work correctly with many accounts. Naturally, each bank account should have its own balance, with deposits and withdrawals going to the appropriate account. Similarly, the penalty fees for each account should be kept separate.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class BankAccount:
def __init__(self, initial_balance):
"""Creates an account with the given balance."""
self.balance = initial_balance
self.fees = 0
def deposit(self, amount):
"""Deposits the amount into the account."""
self.balance += amount - self.fees
def withdraw(self, amount):
"""
Withdraws the amount from the account. Each withdrawal
resulting in a negative balance also deducts a penalty
fee of 5 dollars from the balance.
"""
self.balance -= amount
if self.balance < 0:
self.fees += 5
def get_balance(self):
"""Returns the current balance in the account."""
return self.balance
def get_fees(self):
"""Returns the total fees ever deducted from the account."""
return self.fees

Here’s one possible test with multiple accounts. It should print the values 10, 5, 5, and 0.

1
2
3
4
5
6
7
8
account1 = BankAccount(10)
account1.withdraw(15)
account2 = BankAccount(15)
account2.deposit(10)
account1.deposit(20)
account2.withdraw(20)
print account1.get_balance(), account1.get_fees(), account2.get_balance(),
account2.get_fees()

Copy-and-paste the following much longer test. What four numbers are printed at the end? Enter the four numbers, separated only by spaces.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
account1 = BankAccount(20)
account1.deposit(10)
account2 = BankAccount(10)
account2.deposit(10)
account2.withdraw(50)
account1.withdraw(15)
account1.withdraw(10)
account2.deposit(30)
account2.withdraw(15)
account1.deposit(5)
account1.withdraw(10)
account2.withdraw(10)
account2.deposit(25)
account2.withdraw(15)
account1.deposit(10)
account1.withdraw(50)
account2.deposit(25)
account2.deposit(25)
account1.deposit(30)
account2.deposit(10)
account1.withdraw(15)
account2.withdraw(10)
account1.withdraw(10)
account2.deposit(15)
account2.deposit(10)
account2.withdraw(15)
account1.deposit(15)
account1.withdraw(20)
account2.withdraw(10)
account2.deposit(5)
account2.withdraw(10)
account1.deposit(10)
account1.deposit(20)
account2.withdraw(10)
account2.deposit(5)
account1.withdraw(15)
account1.withdraw(20)
account1.deposit(5)
account2.deposit(10)
account2.deposit(15)
account2.deposit(20)
account1.withdraw(15)
account2.deposit(10)
account1.deposit(25)
account1.deposit(15)
account1.deposit(10)
account1.withdraw(10)
account1.deposit(10)
account2.deposit(20)
account2.withdraw(15)
account1.withdraw(20)
account1.deposit(5)
account1.deposit(10)
account2.withdraw(20)
print account1.get_balance(), account1.get_fees(), account2.get_balance(),
account2.get_fees()



Week 6b - Tiled Images

Tiled Images15 min

http://www.codeskulptor.org/#examples-tiled_images.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# demo for drawing using tiled images
import simplegui
# define globals for cards
RANKS = ('A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K')
SUITS = ('C', 'S', 'H', 'D')
# card sprite - 950x392
CARD_CENTER = (36.5, 49)
CARD_SIZE = (73, 98)
card_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/cards.jfitz.png")
# define card class
class Card:
def __init__(self, suit, rank):
self.rank = rank
self.suit = suit
def draw(self, canvas, loc):
i = RANKS.index(self.rank)
j = SUITS.index(self.suit)
card_pos = [CARD_CENTER[0] + i * CARD_SIZE[0],
CARD_CENTER[1] + j * CARD_SIZE[1]]
canvas.draw_image(card_image, card_pos, CARD_SIZE, loc, CARD_SIZE)
# define draw handler
def draw(canvas):
one_card.draw(canvas, (155, 90))
# define frame and register draw handler
frame = simplegui.create_frame("Card draw", 300, 200)
frame.set_draw_handler(draw)
# createa card
one_card = Card('S', '6')
frame.start()

Visualizing Objects8 min

http://www.codeskulptor.org/viz/#examples_points.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
##################
# Object creation and use
# Mutation with Aliasing
class Point1:
def __init__(self, x, y):
self.x = x
self.y = y
def set_x(self, newx):
self.x = newx
def get_x(self):
return self.x
p = Point1(4, 5)
q = Point1(4, 5)
r = p
p.set_x(10)
print p.get_x()
print q.get_x()
print r.get_x()
##################
# Object shared state
# Mutation of shared state
class Point2:
def __init__(self, coordinates):
self.coords = coordinates
def set_coord(self, index, value):
self.coords[index] = value
def get_coord(self, index):
return self.coords[index]
coordinates = [4, 5]
p = Point2(coordinates)
q = Point2(coordinates)
r = Point2([4, 5])
p.set_coord(0, 10)
print p.get_coord(0)
print q.get_coord(0)
print r.get_coord(0)
##################
# Objects not sharing state
class Point3:
def __init__(self, coordinates):
self.coords = list(coordinates)
def set_coord(self, index, value):
self.coords[index] = value
def get_coord(self, index):
return self.coords[index]
coordinates = [4, 5]
p = Point3(coordinates)
q = Point3(coordinates)
r = Point3([4, 5])
p.set_coord(0, 10)
print p.get_coord(0)
print q.get_coord(0)
print r.get_coord(0)

Programming Tips - 613 min

http://www.codeskulptor.org/#examples-tips6.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
###################
# Broken code
class ball:
def ball(pos, rad):
position = pos
radius = rad
return ball
def get_position():
return position
b = ball([0,0], 10)
print get_position(b)
###################
# Fixed code
class Ball:
def __init__(self, pos, rad):
self.position = pos
self.radius = rad
def get_position(self):
return self.position
b = Ball([0,0], 10)
print b.get_position()
##################
# Example while
def countdown(n):
"""Print the values from n to 0."""
i = n
while i >= 0:
print i
i -= 1
countdown(5)
##################
# Collatz
def collatz(n):
"""Prints the values in the Collatz sequence for n."""
i = n
while i > 1:
print i
if i % 2 == 0:
i = i / 2
else:
i = 3 * i + 1
colnatz(1000)
#################
# Timeout
i = 1
while i > 0:
i += 1
print "Done!"

Practice Exercises for Classes (part 2) (optional)10 min

Quiz:Quiz 6b8 questions

QUIZ
Quiz 6b
8 questions
To Pass70% or higher
Attempts3 every 8 hours
Deadline
November 26, 11:59 PM PST

1 point
1.What is the position of the center of the top-left card (Ace of Clubs, A♣) in the tiled image discussed in the “Tiled images“ video? Remember that each card in this tiled image has size 73 x 98 pixels.

(Note that the tiled image used in the current version of your Blackjack mini-project is slightly smaller.)


(36.5, 49)


(5 73 + 36.5, 1 98 + 49)


(0, 0)


(73, 98)


1 point
2.What is the position of the center of the bottom-right card (King of Diamonds, K♦) in the tiled image discussed in the “Tiled images” video? Again, remember that each card in this tiled image has size 73 x 98 pixels.

Enter two numbers, separated only by spaces.




1 point
3.When using Dropbox to store images for use with CodeSkulptor, what should the www portion of the DropBox URL be replaced by?

Refer to the video on tiled images.


dl


jpg


www


html


gif


1 point
4.Within the init method, the new object should be returned with what code?


return whatever_the_object_is_named (Use the appropriate variable name.)


No return statement is needed in init.


return


return self


1 point
5.One way of understanding code is to think about other code that accomplishes the same thing — i.e., given the same starting values, it returns and/or mutates the same values.

This following defines one way to concatenate multiple lists. For example, list_extend_many([[1,2], [3], [4, 5, 6], [7]]) returns [1, 2, 3, 4, 5, 6, 7] and doesn’t mutate anything.

1
2
3
4
5
6
7
def list_extend_many(lists):
"""Returns a list that is the concatenation of all the lists in the given
list-of-lists."""
result = []
for l in lists:
result.extend(l)
return result

Which of the following definitions are equivalent? I.e., which always produce the same output for the same input, and never mutate the input or any global variable?


1
2
3
4
5
6
7
def list_extend_many(lists):
result = []
i = 0
while i <= len(lists):
result.extend(lists[i])
i += 1
return result


1
2
3
4
5
6
7
def list_extend_many(lists):
result = []
i = 0
while i < len(lists):
result.extend(lists[i])
i += 1
return result


1
2
3
4
5
6
7
def list_extend_many(lists):
result = []
i = 0
while i < len(lists):
result += lists[i]
i += 1
return result


1
2
3
4
5
6
7
def list_extend_many(lists):
result = []
i = 0
while i < len(lists):
i += 1
result.extend(lists[i])
return result



1 point
6.Which of the following programs would never end if it weren’t for CodeSkulptor’s timeout? Assume no break or return statement is used in the elided loop bodies.

You might want to add a print statement to each loop to better understand the behavior.


1
2
3
4
n = 1
while n > 0:
# Assume this doesn't modify n.
n += 1


1
2
while True:


1
2
3
4
n = 1000
while n > 0:
# Assume this doesn't modify n.
n -= 1


1
2
3
my_list = …
for x in my_list:
# Assume this doesn't mutate my_list.



1 point
7.Convert the following English description into code.

Initialize n to be 1000. Initialize numbers to be a list of numbers from 2 to n but not including n.
With results starting as the empty list, repeat the following as long as numbers contains any numbers.
Add the first number in numbers to the end of results.
Remove every number in numbers that is evenly divisible by (has no remainder when divided by) the number that you had just added to results.
How long is results?

To test your code, when n is instead 100, the length of results is 25.


1
2
3
4
5
6
7
8
9
10
n=1000
number = range(2,n)
r = []
while len(number)>0:
r.extend([number[0]])
for i in number:
if i % r[-1]==0:
number.remove(i)
print len(r)



1 point
8.We can use loops to simulate natural processes over time. Write a program that calculates the populations of two kinds of “wumpuses” over time. At the beginning of year 1, there are 1000 slow wumpuses and 1 fast wumpus. This one fast wumpus is a new mutation. Not surprisingly, being fast gives it an advantage, as it can better escape from predators. Each year, each wumpus has one offspring. (We’ll ignore the more realistic niceties of sexual reproduction, like distinguishing males and females.). There are no further mutations, so slow wumpuses beget slow wumpuses, and fast wumpuses beget fast wumpuses. Also, each year 40% of all slow wumpuses die each year, while only 30% of the fast wumpuses do.

So, at the beginning of year one there are 1000 slow wumpuses. Another 1000 slow wumpuses are born. But, 40% of these 2000 slow wumpuses die, leaving a total of 1200 at the end of year one. Meanwhile, in the same year, we begin with 1 fast wumpus, 1 more is born, and 30% of these die, leaving 1.4. (We’ll also allow fractional populations, for simplicity.)

Beginning of Year Slow Wumpuses Fast Wumpuses
1 1000 1
2 1200 1.4
3 1440 1.96

Enter the first year in which the fast wumpuses outnumber the slow wumpuses. Remember that the table above shows the populations at the start of the year.


1
2
3
4
5
6
7
8
s=1000
f=1
n=1
while f<=s:
f=2*f*0.7
s=2*s*0.6
n+=1
print f,s,n


Mini-project #6 - Blackjack

Mini-project Video14 min

http://www.codeskulptor.org/#examples-blackjack_template.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# Mini-project #6 - Blackjack
import simplegui
import random
# load card sprite - 936x384 - source: jfitz.com
CARD_SIZE = (72, 96)
CARD_CENTER = (36, 48)
card_images = simplegui.load_image("http://storage.googleapis.com/codeskulptor-assets/cards_jfitz.png")
CARD_BACK_SIZE = (72, 96)
CARD_BACK_CENTER = (36, 48)
card_back = simplegui.load_image("http://storage.googleapis.com/codeskulptor-assets/card_jfitz_back.png")
# initialize some useful global variables
in_play = False
outcome = ""
score = 0
# define globals for cards
SUITS = ('C', 'S', 'H', 'D')
RANKS = ('A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K')
VALUES = {'A':1, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9, 'T':10, 'J':10, 'Q':10, 'K':10}
# define card class
class Card:
def __init__(self, suit, rank):
if (suit in SUITS) and (rank in RANKS):
self.suit = suit
self.rank = rank
else:
self.suit = None
self.rank = None
print "Invalid card: ", suit, rank
def __str__(self):
return self.suit + self.rank
def get_suit(self):
return self.suit
def get_rank(self):
return self.rank
def draw(self, canvas, pos):
card_loc = (CARD_CENTER[0] + CARD_SIZE[0] * RANKS.index(self.rank),
CARD_CENTER[1] + CARD_SIZE[1] * SUITS.index(self.suit))
canvas.draw_image(card_images, card_loc, CARD_SIZE, [pos[0] + CARD_CENTER[0], pos[1] + CARD_CENTER[1]], CARD_SIZE)
# define hand class
class Hand:
def __init__(self):
pass # create Hand object
def __str__(self):
pass # return a string representation of a hand
def add_card(self, card):
pass # add a card object to a hand
def get_value(self):
# count aces as 1, if the hand has an ace, then add 10 to hand value if it doesn't bust
pass # compute the value of the hand, see Blackjack video
def draw(self, canvas, pos):
pass # draw a hand on the canvas, use the draw method for cards
# define deck class
class Deck:
def __init__(self):
pass # create a Deck object
def shuffle(self):
# shuffle the deck
pass # use random.shuffle()
def deal_card(self):
pass # deal a card object from the deck
def __str__(self):
pass # return a string representing the deck
#define event handlers for buttons
def deal():
global outcome, in_play
# your code goes here
in_play = True
def hit():
pass # replace with your code below
# if the hand is in play, hit the player
# if busted, assign a message to outcome, update in_play and score
def stand():
pass # replace with your code below
# if hand is in play, repeatedly hit dealer until his hand has value 17 or more
# assign a message to outcome, update in_play and score
# draw handler
def draw(canvas):
# test to make sure that card.draw works, replace with your code below
card = Card("S", "A")
card.draw(canvas, [300, 300])
# initialization frame
frame = simplegui.create_frame("Blackjack", 600, 600)
frame.set_canvas_background("Green")
#create buttons and canvas callback
frame.add_button("Deal", deal, 200)
frame.add_button("Hit", hit, 200)
frame.add_button("Stand", stand, 200)
frame.set_draw_handler(draw)
# get things rolling
deal()
frame.start()
# remember to review the gradic rubric

Mini-project Description10 min

Code Clinic Tips10 min

Peer-graded Assignment: Blackjack2h

http://www.codeskulptor.org/#user43_fY8KwOeCws_0.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# Mini-project #6 - Blackjack
import simplegui
import random
# load card sprite - 936x384 - source: jfitz.com
CARD_SIZE = (72, 96)
CARD_CENTER = (36, 48)
card_images = simplegui.load_image("http://storage.googleapis.com/codeskulptor-assets/cards_jfitz.png")
CARD_BACK_SIZE = (72, 96)
CARD_BACK_CENTER = (36, 48)
card_back = simplegui.load_image("http://storage.googleapis.com/codeskulptor-assets/card_jfitz_back.png")
# initialize some useful global variables
in_play = False
outcome = ""
score = 0
# define globals for cards
SUITS = ('C', 'S', 'H', 'D')
RANKS = ('A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K')
VALUES = {'A':1, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9, 'T':10, 'J':10, 'Q':10, 'K':10}
# define card class
class Card:
def __init__(self, suit, rank):
if (suit in SUITS) and (rank in RANKS):
self.suit = suit
self.rank = rank
else:
self.suit = None
self.rank = None
print "Invalid card: ", suit, rank
def __str__(self):
return self.suit + self.rank
def get_suit(self):
return self.suit
def get_rank(self):
return self.rank
def draw(self, canvas, pos):
card_loc = (CARD_CENTER[0] + CARD_SIZE[0] * RANKS.index(self.rank),
CARD_CENTER[1] + CARD_SIZE[1] * SUITS.index(self.suit))
canvas.draw_image(card_images, card_loc, CARD_SIZE, [pos[0] + CARD_CENTER[0], pos[1] + CARD_CENTER[1]], CARD_SIZE)
# define hand class
class Hand:
def __init__(self):
# create Hand object
self.hand = []
def __str__(self):
# return a string representation of a hand
s = "Hand contains"
for i in self.hand:
s+=" "+str(i)
return s
def add_card(self, card):
# add a card object to a hand
self.hand.append(card)
def get_value(self):
# count aces as 1, if the hand has an ace, then add 10 to hand value if it doesn't bust
# compute the value of the hand, see Blackjack video
ace = False
value = 0
for card in self.hand:
rank = card.get_rank()
if rank == "A":
ace = True
value += VALUES[rank]
if ace:
if value + 10 <= 21:
return value+10
else:
return value
else:
return value
def draw(self, canvas, pos):
# draw a hand on the canvas, use the draw method for cards
for card in self.hand:
card.draw(canvas, pos)
pos[0] += CARD_SIZE[0]
# define deck class
class Deck:
def __init__(self):
# create a Deck object
self.deck = [Card(suit,rank) for suit in SUITS for rank in RANKS]
def shuffle(self):
# shuffle the deck
# use random.shuffle()
random.shuffle(self.deck)
def deal_card(self):
# deal a card object from the deck
return self.deck.pop()
def __str__(self):
# return a string representing the deck
s = "Deck contains"
for i in self.deck:
s+=" "+str(i)
return s
#define event handlers for buttons
def deal():
global outcome, in_play, score
# your code goes here
if in_play:
score -= 1
in_play = True
outcome = "Hit or stand?"
# create a Deck object and shuffle the deck
global deck
deck = Deck()
deck.shuffle()
# create Hand object
global dealer, player
dealer = Hand()
player = Hand()
# deal a card object from the deck and add a card object to a hand
player.add_card(deck.deal_card())
dealer.add_card(deck.deal_card())
player.add_card(deck.deal_card())
dealer.add_card(deck.deal_card())
#print dealer, player
def hit():
# replace with your code below
global in_play
# if the hand is in play, hit the player
if in_play:
global player, deck, outcome, score
outcome = "Hit or stand?"
player.add_card(deck.deal_card())
# if busted, assign a message to outcome, update in_play and score
if player.get_value()>21:
outcome = "the player has busted. New deal?"
in_play = False
score -= 1
def stand():
# replace with your code below
# if hand is in play, repeatedly hit dealer until his hand has value 17 or more
global in_play
#print "before " +str(in_play)
if in_play:
global dealer, deck, outcome, player, score
while dealer.get_value() < 17:
dealer.add_card(deck.deal_card())
#print dealer.get_value()
# assign a message to outcome, update in_play and score
if dealer.get_value() > 21:
outcome = "the dealer has busted. New deal?"
score += 1
elif player.get_value() <= dealer.get_value():
outcome = "the dealer wins. New deal?"
score -= 1
else:
outcome = "the player wins. New deal?"
score += 1
in_play = False
#print in_play
# draw handler
def draw(canvas):
# test to make sure that card.draw works, replace with your code below
global outcome
canvas.draw_text(outcome, (30, 300), 36, 'Blue')
canvas.draw_text("Dealer", (30, 140), 48, 'Black')
global dealer
dealer.draw(canvas, [30, 150])
dealer_pos = [30, 150]
global in_play
#print in_play
if in_play:
card_loc = (CARD_CENTER[0] + CARD_SIZE[0], CARD_CENTER[1] + CARD_SIZE[1])
#print card_loc
canvas.draw_image(card_back, CARD_CENTER, CARD_SIZE, [dealer_pos[0] + CARD_CENTER[0],
dealer_pos[1] + CARD_CENTER[1]], CARD_SIZE)
else:
card_loc = (CARD_CENTER[0] + CARD_SIZE[0] * RANKS.index(dealer.hand[0].get_rank()),
CARD_CENTER[1] + CARD_SIZE[1] * SUITS.index(dealer.hand[0].get_suit()))
canvas.draw_image(card_images, card_loc, CARD_SIZE, [dealer_pos[0] + CARD_CENTER[0],
dealer_pos[1] + CARD_CENTER[1]], CARD_SIZE)
global player
canvas.draw_text("Player: "+str(player.get_value()), (30, 370), 48, 'Black')
player.draw(canvas, [30, 380])
canvas.draw_text("Blackjack", (200, 50), 48, 'Black')
global score
canvas.draw_text("Score: "+str(score), (350, 100), 48, 'Red')
# initialization frame
frame = simplegui.create_frame("Blackjack", 600, 600)
frame.set_canvas_background("Green")
#create buttons and canvas callback
frame.add_button("Deal", deal, 200)
frame.add_button("Hit", hit, 200)
frame.add_button("Stand", stand, 200)
frame.set_draw_handler(draw)
# get things rolling
deal()
frame.start()
# remember to review the gradic rubric

Review Your Peers: Blackjack

Week 7 - Basic game physics, sprites

Understand the math of acceleration and friction, work with sprites, add sound to your game

Week 7a - More Classes

Acceleration and Friction14 min

Spaceship Class7 min

http://www.codeskulptor.org/#examples-spaceship.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# Partial example code for Spaceship
import simplegui
class ImageInfo:
def __init__(self, center, size, radius = 0, lifespan = None, animated = False):
self.center = center
self.size = size
self.radius = radius
if lifespan:
self.lifespan = lifespan
else:
self.lifespan = float('inf')
self.animated = animated
def get_center(self):
return self.center
def get_size(self):
return self.size
def get_radius(self):
return self.radius
def get_lifespan(self):
return self.lifespan
def get_animated(self):
return self.animated
# art assets created by Kim Lathrop, may be freely re-used in non-commercial projects, please credit Kim
# ship image
ship_info = ImageInfo([45, 45], [90, 90], 35)
ship_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/double_ship.png")
# sound assets purchased from sounddogs.com, please do not redistribute
ship_thrust_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/thrust.mp3")
# Ship class
class Ship:
def __init__(self, pos, vel, angle, image, info):
self.pos = [pos[0],pos[1]]
self.vel = [vel[0],vel[1]]
self.thrust = False
self.angle = angle
self.angle_vel = 0
self.image = image
self.image_center = info.get_center()
self.image_size = info.get_size()
self.radius = info.get_radius()
def draw(self,canvas):
canvas.draw_circle(self.pos, self.radius, 1, "White", "White")
def update(self):
pass

Sound5 min

http://www.codeskulptor.org/#examples-sound.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# simple music player, uses buttons and sounds
# note that .ogg sounds are not supported in Safari
import simplegui
# define callbacks
def play():
"""play some music, starts at last paused spot"""
music.play()
def pause():
"""pause the music"""
music.pause()
def rewind():
"""rewind the music to the beginning """
music.rewind()
def laugh():
"""play an evil laugh
will overlap since it is separate sound object"""
laugh.play()
def vol_down():
"""turn the current volume down"""
global vol
if vol > 0:
vol = vol - 1
music.set_volume(vol / 10.0)
volume_button.set_text("Volume = " + str(vol))
def vol_up():
"""turn the current volume up"""
global vol
if vol < 10:
vol = vol + 1
music.set_volume(vol / 10.0)
volume_button.set_text("Volume = " + str(vol))
# create frame - canvas will be blank
frame = simplegui.create_frame("Music demo", 250, 250, 100)
# set up control elements
frame.add_button("play", play,100)
frame.add_button("pause", pause,100)
frame.add_button("rewind",rewind,100)
frame.add_button("laugh",laugh,100)
frame.add_button("Vol down", vol_down,100)
frame.add_button("Vol up", vol_up,100)
# initialize volume, create button whose label will display the volume
vol = 7
volume_button = frame.add_label("Volume = " + str(vol))
# load some sounds
music = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/Epoq-Lepidoptera.ogg")
laugh = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/Evillaugh.ogg")
# make the laugh quieter so my ears don't bleed
laugh.set_volume(.1)
frame.start()

Quiz: Quiz 7a7 questions

QUIZ
Quiz 7a
7 questions
To Pass70% or higher
Attempts3 every 8 hours
Deadline
December 3, 11:59 PM PST

point 1. Question 1
Let’s define a class for 2-dimensional points.

1
2
3
4
5
6
7
8
9
10
class Point2D:
def __init__(self, x = 0, y = 0):
self.x = x
self.y = y
def translate(self, deltax = 0, deltay = 0):
"""Translate the point in the x direction by deltax
and in the y direction by deltay."""
self.x += deltax
self.y += deltay

Which of the following code snippets are valid usages of the Point2D initializer and its translate method? For your first attempt at this problem, we suggest that you try to answer without using CodeSkulptor.


1
2
Point2D(3, 9)
Point2D.translate(5, -2)


1
2
point = Point2D(3, 9)
point.translate(5, -2)


1
2
3
point1 = Point2D(3, 9)
point2 = Point2D()
point2.translate(20, 4)


1
2
Point2D = (3, 9)
Point2D.translate(5, -2)



point 2. Question 2
Let’s continue to use the same class for 2-dimensional points.

1
2
3
4
5
6
7
8
9
10
class Point2D:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def translate(self, deltax=0, deltay=0):
"""Translate the point in the x direction by deltax
and in the y direction by deltay."""
self.x += deltax
self.y += deltay

Which of the following code snippets are valid usages of the Point2D initializer and its translate method? For your first attempt at this problem, we suggest that you try to answer without using CodeSkulptor.


1
2
3
4
5
point0 = Point2D(2, 5)
point1 = Point2D(8, 3)
point2 = Point2D(0, 2)
points = [point0, point1, point2]
points.translate(-1, -1)


1
2
3
points = [(2, 5), (8, 3), (0, 2)]
for point in points:
point.translate(-1, -1)


1
2
3
4
5
6
point0 = Point2D(2, 5)
point1 = Point2D(8, 3)
point2 = Point2D(0, 2)
points = [point0, point1, point2]
for point in points:
point.translate(-1, -1)



point 3. Question 3
Now, let’s make this class definition for 2-dimensional points more specific.

1
2
3
4
5
6
7
8
9
10
11
class Point2D:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def translate(self, deltax=0, deltay=0):
"""Translate the point in the x direction by deltax
and in the y direction by deltay."""
self.x += deltax
self.y += deltay
def __str__(self):
return "<" + str(self.x) + ", " + str(self.y) + ">"

For the Point2D class above, having only the three methods shown, which of the following code snippets are valid usages of the Point2D class? For your first attempt at this problem, we suggest that you try to answer without using CodeSkulptor.


1
2
3
point = Point2D(3, 6)
lst = list(point)
x = lst[0]


1
2
3
point = Point2D(3, 6)
s = str(point)
newpoint = Point(s)


1
2
point = Point2D(3, 6)
tup = tuple(point)


1
2
point = Point2D(3, 6)
s = str(point)



point 4. Question 4
In SimpleGUI, the function draw_image takes an optional sixth parameter that determines the angle of rotation of the destination rectangle around its center. Do positive values for the angle rotate the image clockwise or counterclockwise? Is the angle specified in degrees or radians?

Refer to the CodeSkulptor documentation.


counterclockwise, degrees


clockwise, radians


clockwise, degrees


counterclockwise, radians


point 5. Question 5
One interesting extension of Rice Rocks would be to have two ships, with each controlled by a separate player, instead of one single ship. Using the provided class definitions, what is the best way to represent the two ships in this new variant?


Add another call to the Ship constructor, assigning the result to another global variable.

1
2
ship1 = Ship(…)
ship2 = Ship(…)


In the Ship class definition, change the variables pos, vel, angle to be lists of two values each. Then, change each method to take an additional number argument that indicates which ship should be used.

Thus, when we call the constructor now, we are creating both ships.

1
ships = Ship(…)


Copy the Ship class code, e.g.,

1
2
3
4
class Another_Ship:
def __init__(self, pos, vel, angle):

Then create two ship objects, one of each class, assigning each to a global variable.

1
2
ship1 = Ship(…)
ship2 = Another_Ship(…)


In the Ship class definition, duplicate every method. For example, Ship.draw1(…) would be used to draw the first ship, while Ship.draw2(…) would be used to draw the second ship.


point 6. Question 6
Which of the following browsers fully support MP3 audio files? Refer to the CodeSkulptor documentation.


Chrome


Firefox


Safari


point 7. Question 7
Consider a spaceship where the ship’s thrusters can accelerate the ship by 10 pixels per second for each second that the thrust key is held down. If the friction induces a deceleration that is 10% of the ship’s velocity per second, what is the maximal velocity of the ship? If you are having trouble, consider writing a short program to help understand this problem.


Around 100 pixels per second


Around 10 pixels per second


The ship has no maximal velocity. It can reach any velocity the player desires if you hold the thrust key down long enough.


Around 1000 pixels per second


Correct
At a velocity of 100 pixels per second, friction would induce a deceleration of 10 pixels per second. This deceleration would exactly cancel an acceleration of 10 pixels per second from the thrusters. We used “around” here since the true maximal velocity depends on the rate at which the frame is drawn.

Week 7b - Sprites

Sprite Class14 min

http://www.codeskulptor.org/#examples-sprite_example.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# Sprite class emo
import simplegui
import math
# helper class to organize image information
class ImageInfo:
def __init__(self, center, size, radius = 0, lifespan = None, animated = False):
self.center = center
self.size = size
self.radius = radius
if lifespan:
self.lifespan = lifespan
else:
self.lifespan = float('inf')
self.animated = animated
def get_center(self):
return self.center
def get_size(self):
return self.size
def get_radius(self):
return self.radius
def get_lifespan(self):
return self.lifespan
def get_animated(self):
return self.animated
# load ship image
asteroid_info = ImageInfo([45, 45], [90, 90], 40)
asteroid_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blue.png")
# Sprite class
class Sprite():
def __init__(self, pos, vel, ang, ang_vel, image, info, sound = None):
self.pos = [pos[0],pos[1]]
self.vel = [vel[0],vel[1]]
self.angle = ang
self.angle_vel = ang_vel
self.image = image
self.image_center = info.get_center()
self.image_size = info.get_size()
self.radius = info.get_radius()
self.lifespan = info.get_lifespan()
self.animated = info.get_animated()
self.age = 0
if sound:
sound.rewind()
sound.play()
def draw(self, canvas):
#canvas.draw_circle(self.pos, self.radius, 1, "Red", "Red")
canvas.draw_image(self.image, self.image_center, self.image_size, self.pos, self.image_size, self.angle)
def update(self):
self.angle += self.angle_vel
self.pos[0] += self.vel[0]
self.pos[1] += self.vel[1]
def draw(canvas):
# draw ship and sprites
a_rock.draw(canvas)
# update ship and sprites
a_rock.update()
# initialize frame
frame = simplegui.create_frame("Sprite demo", 800, 600)
# initialize ship and two sprites
a_rock = Sprite([400, 300], [0.3, 0.4], 0, 0.1, asteroid_image, asteroid_info)
# register handlers
frame.set_draw_handler(draw)
# get things rolling
frame.start()

Programming Tips - 720 min

http://www.codeskulptor.org/#examples-tips7.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
########################
# Incomplete code from Pong
# Repeated code
def draw(c):
global paddle1_pos, paddle2_pos
paddle_width = 80
if paddle_width/2 <= paddle1_pos + paddle1_vel <= width - paddle_width/2:
paddle1_pos += paddle1_vel
if paddle_width/2 <= paddle2_pos + paddle2_vel <= width - paddle_width/2:
paddle2_pos += paddle2_vel
c.draw_line([width/2, 0],[width/2, height], 1, "White")
c.draw_line([4, paddle1_pos-paddle_width/2], [4, paddle1_pos+paddle_width/2], 4, "White")
c.draw_line([width-4, paddle2_pos-paddle_width/2], [width-4, paddle2_pos+paddle_width/2], 4, "White")
...
########################
# Incomplete code from Pong
# Avoiding repetition with functions
paddle_width = 80
def paddle_move(paddle_num):
if paddle_width/2 <= paddle_pos[paddle_num] + paddle_vel[paddle_num] <= width - paddle_width/2:
paddle_pos[paddle_num] += paddle_vel[paddle_num]
def paddle_draw(c, paddle_num):
c.draw_line([paddle_loc[paddle_num], paddle_pos[paddle_num] - paddle_width/2],
PADDLE_THICKNESS, "White")
def draw(c):
paddle_move(0)
paddle_move(1)
c.draw_line([width / 2, 0],[width / 2, height], 1, "White")
paddle_draw(c,0)
paddle_draw(c,1)
...
########################
# Incomplete code from Pong
# Avoiding repetition with classes and methods
class Paddle:
def __init__(self, loc, pos, vel):
self.loc = loc
self.pos = pos
self.vel = vel
self.width = 80
def move(self):
if self.width/2 <= self.pos + self.vel <= width - self.width/2:
self.pos += self.vel
def draw(c, self):
c.draw_line([self.loc, self.pos-self.width / 2], PADDLE_THICKNESS, "White")
def draw(c):
paddle1.move()
paddle2.move()
c.draw_line([width / 2, 0],[width / 2, height], 1, "White")
paddle1.draw(c)
paddle2.draw(c)
...
########################
# Incomplete code from Pong
# Long if/elif chain
def keydown(key):
global paddle1_vel, paddle2_vel
if key == simplegui.KEY_MAP["up"]:
paddle2_vel -= 2
elif key == simplegui.KEY_MAP["down"]:
paddle2_vel += 2
elif key == simplegui.KEY_MAP["w"]:
paddle1_vel -= 2
elif key == simplegui.KEY_MAP["s"]:
paddle1_vel += 2
########################
# Incomplete code from Pong
# Avoiding long if/elif chain with dictionary mapping values to actions
def paddle1_faster():
global paddle1_vel
paddle1_vel += 2
def paddle1_slower():
global paddle1_vel
paddle1_vel -= 2
def paddle2_faster():
global paddle2_vel
paddle2_vel += 2
def paddle2_slower():
global paddle2_vel
paddle2_vel -= 2
inputs = {"up": paddle2_slower,
"down": paddle2_faster,
"w": paddle1_slower,
"s": paddle1_faster}
def keydown(key):
for i in inputs:
if key == simplegui.KEY_MAP[i]:
inputs[i]()
########################
# Illustration of a dictionary mapping values to functions
def f():
print "hi"
d = {0: f}
d[0]()
########################
# Incomplete code from Pong
# Avoiding long if/elif chain with dictionary mapping values to action arguments
inputs = {"up": [1, -2],
"down": [1, 2],
"w": [0, -2],
"s": [0, 2]}
def keydown(key):
for i in inputs:
if key == simplegui.KEY_MAP[i]:
paddle_vel[inputs[i][0]] += inputs[i][1]
########################
# Sample of using tiled image
# Has some uses of "magic" (unexplained) constants.
# demo for drawing using tiled images
import simplegui
# define globals for cards
RANKS = ['A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K']
SUITS = ['C', 'S', 'H', 'D']
# card sprite - 950x392
CARD_CENTER = (36.5, 49)
CARD_SIZE = (73, 98)
card_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/cards.jfitz.png")
# define card class
class Card:
def __init__(self, suit, rank):
self.rank = rank
self.suit = suit
def draw(self, canvas, pos):
i = RANKS.index(self.rank)
j = SUITS.index(self.suit)
card_pos = [CARD_CENTER[0] + i * CARD_SIZE[0],
CARD_CENTER[1] + j * CARD_SIZE[1]]
canvas.draw_image(card_image, card_pos, CARD_SIZE, pos, CARD_SIZE)
# define draw handler
def draw(canvas):
one_card.draw(canvas, (155, 90))
# define frame and register draw handler
frame = simplegui.create_frame("Card draw", 300, 200)
frame.set_draw_handler(draw)
# createa card
one_card = Card('S', '6')
frame.start()
########################
# Sample of using tiled image
# Naming constants and calculating other constants from those
# demo for drawing using tiled images
import simplegui
# define globals for cards
RANKS = ['A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K']
SUITS = ['C', 'S', 'H', 'D']
# card sprite - 950x392
CARD_SIZE = (73, 98)
card_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/cards.jfitz.png")
FRAME_SIZE = (300, 200)
# define card class
class Card:
def __init__(self, suit, rank):
self.rank = rank
self.suit = suit
def draw(self, canvas, pos):
i = RANKS.index(self.rank)
j = SUITS.index(self.suit)
card_loc = [(.5 + i) * CARD_SIZE[0],
(.5 + j) * CARD_SIZE[1]]
canvas.draw_image(card_image, card_loc, CARD_SIZE, pos, CARD_SIZE)
# define draw handler
def draw(canvas):
one_card.draw(canvas, (FRAME_SIZE[0] / 2, FRAME_SIZE[1] / 2))
# define frame and register draw handler
frame = simplegui.create_frame("Card draw", FRAME_SIZE[0], FRAME_SIZE[1])
frame.set_draw_handler(draw)
# createa card
one_card = Card('S', '6')
frame.start()
########################
# Incomplete code from Pong
# Magic unnamed constants, repeated code, long expressions
width = 600
height = 400
def ball_init():
if random.randrange(0,2) == 0:
return [300,200], [3 + 3 * random.random(), 8 * (random.random() - 0.5)]
else:
return [300,200], [-(3 + 3 * random.random()), 8 * (random.random() - 0.5)]
########################
# Incomplete code from Pong
# Constants named and computed, repetition avoided, expressions broken into
# named pieces
width = 600
height = 400
def ball_init():
pos = [width/2, height/2]
vel_x = 3 + 3 * random.random()
vel_y = 8 * (random.random() - 0.5)
if random.randrange(0,2) == 1:
vel_x = -vel_x
return pos, [vel_x, vel_y]

Practice Exercises for Sprites and Sound (optional)10 min

Quiz: Quiz 7b9 questions

QUIZ
Quiz 7b
9 questions
To Pass70% or higher
Attempts3 every 8 hours
Deadline
December 3, 11:59 PM PST

1 point

  1. Question 1
    The class code provided for this week’s mini-project supports an ImageInfo class to organize the data associated with the image. Consider an ImageInfo object of the following form:
    1
    ImageInfo([45, 45], [90, 90], 35)

What is the radius of the shape associated with this ImageInfo object?



1 point 2. Question 2
Consider the provided ImageInfo and Sprite class code. Assume we want ten asteroids on the screen, each looking exactly alike and using the same image file. How many ImageInfo objects and how many Sprite objects should we create?


ten ImageInfo objects, ten Sprite objects


ten ImageInfo objects, one Sprite object


one ImageInfo object, ten Sprite objects


one ImageInfo object, one Sprite object


1 point 3. Question 3
The version of Rice Rocks that we will implement uses only a single asteroid image and spawns multiple instances of the provided Sprite class using this image. In the original Asteroids, a large asteroid split into two medium asteroids which themselves split into two small asteroids.

If we only had one image and wanted to implement asteroids of varying sizes in our version, how should we do this?


Store the size in a global variable. Use this variable when drawing a sprite.


Add a size attribute in the Sprite class and a size parameter to Sprite.init. Use the size attribute when drawing the sprite.


Add a size attribute in the ImageInfo class and a size parameter to ImageInfo.init. Use this attribute when drawing the sprite.


Store a list of sizes for each asteroid in a global variable. Use the corresponding size when drawing a sprite.


1 point 4. Question 4
What is the supported range of sound volumes in set_volume? You can find out in the CodeSkulptor documentation.


0 to 1


0 to 10


-1 to 1


1 to 100


1 point 5. Question 5
Assume you have code that loads and plays a sound. Unfortunately, you don’t hear anything. Which of the following could be a reason?


The given URL exists, but is inaccessible due to network problems.


A file found with the given URL isn’t a sound file recognized by your browser.


You have set the volume level to 0.


Your browser is loading a big sound file. Wait longer.


No file is found with the given URL.


1 point 6. Question 6
Which of the following are valid HTML representations of the color blue?

Refer to this page on HTML color values.


“#0000FF”


“rgb(0, 0, 255)”


“purple”


“#FFFF00”


“Blue”


1 point 7. Question 7
Imagine we are writing code for something like Rice Rocks, where things are moving in 2D toroidal space, i.e., the wrap around all four sides of the screen. How can we eliminate the duplicated code in the following function?

1
2
3
4
def move(position, vector):
"""Moves the position by the given vector in 2D toroidal space."""
position[0] = (position[0] + vector[0]) % SCREEN_SIZE[0]
position[1] = (position[1] + vector[1]) % SCREEN_SIZE[1]


1
2
3
4
5
NUM_DIMENSIONS = 2
def move(position, vector):
for d in range(NUM_DIMENSIONS):
return position[d] = (position[d] + vector[d]) %
SCREEN_SIZE[d]


1
2
3
def move(position, vector):
position = [(pos + vec) % size for pos in position for vec in
vector for size in SCREEN_SIZE]


1
2
3
def move(position, vector):
"""Moves the position by the given vector in 2D toroidal space."""
position = (position + vector) % SCREEN_SIZE


1
2
3
4
5
6
7
8
9
def move_dimension(dimension, position, vector):
"""Moves the position component by the given vector component in
1D toroidal space."""
position[dimension] = (position[dimension] + vector[dimension]) %
SCREEN_SIZE[dimension]
def move(position, vector):
"""Moves the position by the given vector in 2D toroidal space."""
move_dimension(0, position, vector)
move_dimension(1, position, vector)


1
2
3
4
5
NUM_DIMENSIONS = 2
def move(position, vector):
"""Moves the position by the given vector in 2D toroidal space."""
for d in range(NUM_DIMENSIONS):
position[d] = (position[d] + vector[d]) % SCREEN_SIZE[d]



1 point 8. Question 8
What is the primary reason for not duplicating code? It was the only reason mentioned in the Programming Tips #7 video.


It leads to faster code.


You only need to get the code correct once.


It takes less time to write the code.


1 point 9. Question 9
What is Mike Massimino’s greatest accomplishment?


Fixing the Hubble Space Telescope in space


Being the first person to use Twitter in space


Receiving his PhD from MIT


Appearing on The Big Bang Theory


Appearing on An Introduction to Interactive Programming in Python

Mini Project #7 - Spaceship

Mini-project Video13 min

http://www.codeskulptor.org/#examples-spaceship_template.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# program template for Spaceship
import simplegui
import math
import random
# globals for user interface
WIDTH = 800
HEIGHT = 600
score = 0
lives = 3
time = 0
class ImageInfo:
def __init__(self, center, size, radius = 0, lifespan = None, animated = False):
self.center = center
self.size = size
self.radius = radius
if lifespan:
self.lifespan = lifespan
else:
self.lifespan = float('inf')
self.animated = animated
def get_center(self):
return self.center
def get_size(self):
return self.size
def get_radius(self):
return self.radius
def get_lifespan(self):
return self.lifespan
def get_animated(self):
return self.animated
# art assets created by Kim Lathrop, may be freely re-used in non-commercial projects, please credit Kim
# debris images - debris1_brown.png, debris2_brown.png, debris3_brown.png, debris4_brown.png
# debris1_blue.png, debris2_blue.png, debris3_blue.png, debris4_blue.png, debris_blend.png
debris_info = ImageInfo([320, 240], [640, 480])
debris_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/debris2_blue.png")
# nebula images - nebula_brown.png, nebula_blue.png
nebula_info = ImageInfo([400, 300], [800, 600])
nebula_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/nebula_blue.f2014.png")
# splash image
splash_info = ImageInfo([200, 150], [400, 300])
splash_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/splash.png")
# ship image
ship_info = ImageInfo([45, 45], [90, 90], 35)
ship_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/double_ship.png")
# missile image - shot1.png, shot2.png, shot3.png
missile_info = ImageInfo([5,5], [10, 10], 3, 50)
missile_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/shot2.png")
# asteroid images - asteroid_blue.png, asteroid_brown.png, asteroid_blend.png
asteroid_info = ImageInfo([45, 45], [90, 90], 40)
asteroid_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blue.png")
# animated explosion - explosion_orange.png, explosion_blue.png, explosion_blue2.png, explosion_alpha.png
explosion_info = ImageInfo([64, 64], [128, 128], 17, 24, True)
explosion_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/explosion_alpha.png")
# sound assets purchased from sounddogs.com, please do not redistribute
soundtrack = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/soundtrack.mp3")
missile_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/missile.mp3")
missile_sound.set_volume(.5)
ship_thrust_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/thrust.mp3")
explosion_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/explosion.mp3")
# alternative upbeat soundtrack by composer and former IIPP student Emiel Stopler
# please do not redistribute without permission from Emiel at http://www.filmcomposer.nl
#soundtrack = simplegui.load_sound("https://storage.googleapis.com/codeskulptor-assets/ricerocks_theme.mp3")
# helper functions to handle transformations
def angle_to_vector(ang):
return [math.cos(ang), math.sin(ang)]
def dist(p,q):
return math.sqrt((p[0] - q[0]) ** 2+(p[1] - q[1]) ** 2)
# Ship class
class Ship:
def __init__(self, pos, vel, angle, image, info):
self.pos = [pos[0],pos[1]]
self.vel = [vel[0],vel[1]]
self.thrust = False
self.angle = angle
self.angle_vel = 0
self.image = image
self.image_center = info.get_center()
self.image_size = info.get_size()
self.radius = info.get_radius()
def draw(self,canvas):
canvas.draw_circle(self.pos, self.radius, 1, "White", "White")
def update(self):
pass
# Sprite class
class Sprite:
def __init__(self, pos, vel, ang, ang_vel, image, info, sound = None):
self.pos = [pos[0],pos[1]]
self.vel = [vel[0],vel[1]]
self.angle = ang
self.angle_vel = ang_vel
self.image = image
self.image_center = info.get_center()
self.image_size = info.get_size()
self.radius = info.get_radius()
self.lifespan = info.get_lifespan()
self.animated = info.get_animated()
self.age = 0
if sound:
sound.rewind()
sound.play()
def draw(self, canvas):
canvas.draw_circle(self.pos, self.radius, 1, "Red", "Red")
def update(self):
pass
def draw(canvas):
global time
# animiate background
time += 1
wtime = (time / 4) % WIDTH
center = debris_info.get_center()
size = debris_info.get_size()
canvas.draw_image(nebula_image, nebula_info.get_center(), nebula_info.get_size(), [WIDTH / 2, HEIGHT / 2], [WIDTH, HEIGHT])
canvas.draw_image(debris_image, center, size, (wtime - WIDTH / 2, HEIGHT / 2), (WIDTH, HEIGHT))
canvas.draw_image(debris_image, center, size, (wtime + WIDTH / 2, HEIGHT / 2), (WIDTH, HEIGHT))
# draw ship and sprites
my_ship.draw(canvas)
a_rock.draw(canvas)
a_missile.draw(canvas)
# update ship and sprites
my_ship.update()
a_rock.update()
a_missile.update()
# timer handler that spawns a rock
def rock_spawner():
pass
# initialize frame
frame = simplegui.create_frame("Asteroids", WIDTH, HEIGHT)
# initialize ship and two sprites
my_ship = Ship([WIDTH / 2, HEIGHT / 2], [0, 0], 0, ship_image, ship_info)
a_rock = Sprite([WIDTH / 3, HEIGHT / 3], [1, 1], 0, 0, asteroid_image, asteroid_info)
a_missile = Sprite([2 * WIDTH / 3, 2 * HEIGHT / 3], [-1,1], 0, 0, missile_image, missile_info, missile_sound)
# register handlers
frame.set_draw_handler(draw)
timer = simplegui.create_timer(1000.0, rock_spawner)
# get things rolling
timer.start()
frame.start()

Mini-project Description10 min

Code Clinic Tips10 min

Peer-graded Assignment: Spaceship2h

http://www.codeskulptor.org/#user43_5qF4DyjDNV_0.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# program template for Spaceship
import simplegui
import math
import random
# globals for user interface
WIDTH = 800
HEIGHT = 600
score = 0
lives = 3
time = 0
angular_velocity = 0.1
friction_factor = 0.1
class ImageInfo:
def __init__(self, center, size, radius = 0, lifespan = None, animated = False):
self.center = center
self.size = size
self.radius = radius
if lifespan:
self.lifespan = lifespan
else:
self.lifespan = float('inf')
self.animated = animated
def get_center(self):
return self.center
def get_size(self):
return self.size
def get_radius(self):
return self.radius
def get_lifespan(self):
return self.lifespan
def get_animated(self):
return self.animated
# art assets created by Kim Lathrop, may be freely re-used in non-commercial projects, please credit Kim
# debris images - debris1_brown.png, debris2_brown.png, debris3_brown.png, debris4_brown.png
# debris1_blue.png, debris2_blue.png, debris3_blue.png, debris4_blue.png, debris_blend.png
debris_info = ImageInfo([320, 240], [640, 480])
debris_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/debris2_blue.png")
# nebula images - nebula_brown.png, nebula_blue.png
nebula_info = ImageInfo([400, 300], [800, 600])
nebula_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/nebula_blue.f2014.png")
# splash image
splash_info = ImageInfo([200, 150], [400, 300])
splash_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/splash.png")
# ship image
ship_info = ImageInfo([45, 45], [90, 90], 35)
#thrust_ship_info = ImageInfo([135, 45], [90, 90], 35)
ship_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/double_ship.png")
# missile image - shot1.png, shot2.png, shot3.png
missile_info = ImageInfo([5,5], [10, 10], 3, 50)
missile_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/shot2.png")
# asteroid images - asteroid_blue.png, asteroid_brown.png, asteroid_blend.png
asteroid_info = ImageInfo([45, 45], [90, 90], 40)
asteroid_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blue.png")
# animated explosion - explosion_orange.png, explosion_blue.png, explosion_blue2.png, explosion_alpha.png
explosion_info = ImageInfo([64, 64], [128, 128], 17, 24, True)
explosion_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/explosion_alpha.png")
# sound assets purchased from sounddogs.com, please do not redistribute
soundtrack = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/soundtrack.mp3")
missile_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/missile.mp3")
missile_sound.set_volume(.5)
ship_thrust_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/thrust.mp3")
explosion_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/explosion.mp3")
# alternative upbeat soundtrack by composer and former IIPP student Emiel Stopler
# please do not redistribute without permission from Emiel at http://www.filmcomposer.nl
#soundtrack = simplegui.load_sound("https://storage.googleapis.com/codeskulptor-assets/ricerocks_theme.mp3")
# helper functions to handle transformations
def angle_to_vector(ang):
return [math.cos(ang), math.sin(ang)]
def dist(p,q):
return math.sqrt((p[0] - q[0]) ** 2+(p[1] - q[1]) ** 2)
# Ship class
class Ship:
def __init__(self, pos, vel, angle, image, info):
self.pos = [pos[0],pos[1]]
self.vel = [vel[0],vel[1]]
self.thrust = False
self.angle = angle
self.angle_vel = 0
self.image = image
self.image_center = info.get_center()
self.image_size = info.get_size()
self.radius = info.get_radius()
def draw(self,canvas):
if self.thrust:
self.image_center[0] = 135
canvas.draw_image(self.image, self.image_center, self.image_size, self.pos, self.image_size, self.angle)
self.image_center[0] = 45
else:
canvas.draw_image(self.image, self.image_center, self.image_size, self.pos, self.image_size, self.angle)
def keydown(self,key):
if key == simplegui.KEY_MAP["left"]:
self.angle_vel -= angular_velocity
if key == simplegui.KEY_MAP["right"]:
self.angle_vel += angular_velocity
if key == simplegui.KEY_MAP["left"] and key == simplegui.KEY_MAP["right"]:
pass
if key == simplegui.KEY_MAP["up"]:
self.thrust = True
ship_thrust_sound.play()
def keyup(self,key):
if key == simplegui.KEY_MAP["left"]:
self.angle_vel = 0
if key == simplegui.KEY_MAP["right"]:
self.angle_vel = 0
if key == simplegui.KEY_MAP["left"] and key == simplegui.KEY_MAP["right"]:
pass
if key == simplegui.KEY_MAP["up"]:
self.thrust = False
ship_thrust_sound.rewind()
def update(self):
self.pos[0] = (self.pos[0] + self.vel[0]) % WIDTH
self.pos[1] = (self.pos[1] + self.vel[1]) % HEIGHT
self.angle += self.angle_vel
self.vel[0] *= (1-friction_factor)
self.vel[1] *= (1-friction_factor)
forward = angle_to_vector(self.angle)
if self.thrust:
self.vel[0] += forward[0]
self.vel[1] += forward[1]
# Sprite class
class Sprite:
def __init__(self, pos, vel, ang, ang_vel, image, info, sound = None):
self.pos = [pos[0],pos[1]]
self.vel = [vel[0],vel[1]]
self.angle = ang
self.angle_vel = ang_vel
self.image = image
self.image_center = info.get_center()
self.image_size = info.get_size()
self.radius = info.get_radius()
self.lifespan = info.get_lifespan()
self.animated = info.get_animated()
self.age = 0
if sound:
sound.rewind()
sound.play()
def draw(self, canvas):
canvas.draw_circle(self.pos, self.radius, 1, "Red", "Red")
def update(self):
pass
def draw(canvas):
global time
# animiate background
time += 1
wtime = (time / 4) % WIDTH
center = debris_info.get_center()
size = debris_info.get_size()
canvas.draw_image(nebula_image, nebula_info.get_center(), nebula_info.get_size(), [WIDTH / 2, HEIGHT / 2], [WIDTH, HEIGHT])
canvas.draw_image(debris_image, center, size, (wtime - WIDTH / 2, HEIGHT / 2), (WIDTH, HEIGHT))
canvas.draw_image(debris_image, center, size, (wtime + WIDTH / 2, HEIGHT / 2), (WIDTH, HEIGHT))
# draw ship and sprites
my_ship.draw(canvas)
a_rock.draw(canvas)
a_missile.draw(canvas)
# update ship and sprites
my_ship.update()
a_rock.update()
a_missile.update()
# timer handler that spawns a rock
def rock_spawner():
pass
# initialize frame
frame = simplegui.create_frame("Asteroids", WIDTH, HEIGHT)
# initialize ship and two sprites
my_ship = Ship([WIDTH / 2, HEIGHT / 2], [0, 0], 0, ship_image, ship_info)
a_rock = Sprite([WIDTH / 3, HEIGHT / 3], [1, 1], 0, 0, asteroid_image, asteroid_info)
a_missile = Sprite([2 * WIDTH / 3, 2 * HEIGHT / 3], [-1,1], 0, 0, missile_image, missile_info, missile_sound)
# register handlers
frame.set_draw_handler(draw)
frame.set_keydown_handler(my_ship.keydown)
frame.set_keyup_handler(my_ship.keyup)
timer = simplegui.create_timer(1000.0, rock_spawner)
# get things rolling
timer.start()
frame.start()

http://www.codeskulptor.org/#user43_5qF4DyjDNV_1.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# program template for Spaceship
import simplegui
import math
import random
# globals for user interface
WIDTH = 800
HEIGHT = 600
score = 0
lives = 3
time = 0
angular_velocity = 0.1
friction_factor = 0.1
class ImageInfo:
def __init__(self, center, size, radius = 0, lifespan = None, animated = False):
self.center = center
self.size = size
self.radius = radius
if lifespan:
self.lifespan = lifespan
else:
self.lifespan = float('inf')
self.animated = animated
def get_center(self):
return self.center
def get_size(self):
return self.size
def get_radius(self):
return self.radius
def get_lifespan(self):
return self.lifespan
def get_animated(self):
return self.animated
# art assets created by Kim Lathrop, may be freely re-used in non-commercial projects, please credit Kim
# debris images - debris1_brown.png, debris2_brown.png, debris3_brown.png, debris4_brown.png
# debris1_blue.png, debris2_blue.png, debris3_blue.png, debris4_blue.png, debris_blend.png
debris_info = ImageInfo([320, 240], [640, 480])
debris_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/debris2_blue.png")
# nebula images - nebula_brown.png, nebula_blue.png
nebula_info = ImageInfo([400, 300], [800, 600])
nebula_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/nebula_blue.f2014.png")
# splash image
splash_info = ImageInfo([200, 150], [400, 300])
splash_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/splash.png")
# ship image
ship_info = ImageInfo([45, 45], [90, 90], 35)
#thrust_ship_info = ImageInfo([135, 45], [90, 90], 35)
ship_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/double_ship.png")
# missile image - shot1.png, shot2.png, shot3.png
missile_info = ImageInfo([5,5], [10, 10], 3, 50)
missile_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/shot2.png")
# asteroid images - asteroid_blue.png, asteroid_brown.png, asteroid_blend.png
asteroid_info = ImageInfo([45, 45], [90, 90], 40)
asteroid_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blue.png")
# animated explosion - explosion_orange.png, explosion_blue.png, explosion_blue2.png, explosion_alpha.png
explosion_info = ImageInfo([64, 64], [128, 128], 17, 24, True)
explosion_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/explosion_alpha.png")
# sound assets purchased from sounddogs.com, please do not redistribute
soundtrack = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/soundtrack.mp3")
missile_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/missile.mp3")
missile_sound.set_volume(.5)
ship_thrust_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/thrust.mp3")
explosion_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/explosion.mp3")
# alternative upbeat soundtrack by composer and former IIPP student Emiel Stopler
# please do not redistribute without permission from Emiel at http://www.filmcomposer.nl
#soundtrack = simplegui.load_sound("https://storage.googleapis.com/codeskulptor-assets/ricerocks_theme.mp3")
# helper functions to handle transformations
def angle_to_vector(ang):
return [math.cos(ang), math.sin(ang)]
def dist(p,q):
return math.sqrt((p[0] - q[0]) ** 2+(p[1] - q[1]) ** 2)
# Ship class
class Ship:
def __init__(self, pos, vel, angle, image, info):
self.pos = [pos[0],pos[1]]
self.vel = [vel[0],vel[1]]
self.thrust = False
self.angle = angle
self.angle_vel = 0
self.image = image
self.image_center = info.get_center()
self.image_size = info.get_size()
self.radius = info.get_radius()
def draw(self,canvas):
if self.thrust:
self.image_center[0] = 135
canvas.draw_image(self.image, self.image_center, self.image_size, self.pos, self.image_size, self.angle)
self.image_center[0] = 45
else:
canvas.draw_image(self.image, self.image_center, self.image_size, self.pos, self.image_size, self.angle)
def keydown(self,key):
if key == simplegui.KEY_MAP["left"]:
self.angle_vel -= angular_velocity
if key == simplegui.KEY_MAP["right"]:
self.angle_vel += angular_velocity
if key == simplegui.KEY_MAP["left"] and key == simplegui.KEY_MAP["right"]:
pass
if key == simplegui.KEY_MAP["up"]:
self.thrust = True
ship_thrust_sound.play()
if key == simplegui.KEY_MAP["space"]:
global my_ship
my_ship.shoot()
def keyup(self,key):
if key == simplegui.KEY_MAP["left"]:
self.angle_vel = 0
if key == simplegui.KEY_MAP["right"]:
self.angle_vel = 0
if key == simplegui.KEY_MAP["left"] and key == simplegui.KEY_MAP["right"]:
pass
if key == simplegui.KEY_MAP["up"]:
self.thrust = False
ship_thrust_sound.rewind()
def update(self):
self.pos[0] = (self.pos[0] + self.vel[0]) % WIDTH
self.pos[1] = (self.pos[1] + self.vel[1]) % HEIGHT
self.angle += self.angle_vel
self.vel[0] *= (1-friction_factor)
self.vel[1] *= (1-friction_factor)
forward = angle_to_vector(self.angle)
if self.thrust:
self.vel[0] += forward[0]
self.vel[1] += forward[1]
def shoot(self):
global a_missile
forward = angle_to_vector(self.angle)
a_missile = Sprite([self.pos[0] + forward[0]*self.image_size[0]/2, self.pos[1] + forward[1]*self.image_size[1]/2], [self.vel[0] + 10*forward[0],self.vel[1] + 10*forward[1]], self.angle, 0, missile_image, missile_info, missile_sound)
# Sprite class
class Sprite:
def __init__(self, pos, vel, ang, ang_vel, image, info, sound = None):
self.pos = [pos[0],pos[1]]
self.vel = [vel[0],vel[1]]
self.angle = ang
self.angle_vel = ang_vel
self.image = image
self.image_center = info.get_center()
self.image_size = info.get_size()
self.radius = info.get_radius()
self.lifespan = info.get_lifespan()
self.animated = info.get_animated()
self.age = 0
if sound:
sound.rewind()
sound.play()
def draw(self, canvas):
canvas.draw_image(self.image, self.image_center, self.image_size, self.pos, self.image_size, self.angle)
def update(self):
self.pos[0] += self.vel[0]
self.pos[1] += self.vel[1]
self.angle += self.angle_vel
def draw(canvas):
global time
# animiate background
time += 1
wtime = (time / 4) % WIDTH
center = debris_info.get_center()
size = debris_info.get_size()
canvas.draw_image(nebula_image, nebula_info.get_center(), nebula_info.get_size(), [WIDTH / 2, HEIGHT / 2], [WIDTH, HEIGHT])
canvas.draw_image(debris_image, center, size, (wtime - WIDTH / 2, HEIGHT / 2), (WIDTH, HEIGHT))
canvas.draw_image(debris_image, center, size, (wtime + WIDTH / 2, HEIGHT / 2), (WIDTH, HEIGHT))
# draw ship and sprites
my_ship.draw(canvas)
a_rock.draw(canvas)
a_missile.draw(canvas)
# update ship and sprites
my_ship.update()
a_rock.update()
a_missile.update()
global score
canvas.draw_text("Score: "+str(score), (WIDTH/10*6, HEIGHT/10), 48, 'Red')
global lives
canvas.draw_text("Lives: "+str(lives), (WIDTH/10, HEIGHT/10), 48, 'Red')
# timer handler that spawns a rock
def rock_spawner():
global a_rock
a_rock = Sprite([random.randint(0, WIDTH), random.randint(0, HEIGHT)], [random.randint(-5, 5), random.randint(-5, 5)], random.randint(-2, 2)*math.pi/60, random.randint(-1, 1), asteroid_image, asteroid_info)
# initialize frame
frame = simplegui.create_frame("Asteroids", WIDTH, HEIGHT)
# initialize ship and two sprites
my_ship = Ship([WIDTH / 2, HEIGHT / 2], [0, 0], 0, ship_image, ship_info)
a_rock = Sprite([WIDTH / 3, HEIGHT / 3], [1, 1], 0, 0.1, asteroid_image, asteroid_info)
a_missile = Sprite([2 * WIDTH / 3, 2 * HEIGHT / 3], [-1,1], 0, 0, missile_image, missile_info, missile_sound)
# register handlers
frame.set_draw_handler(draw)
frame.set_keydown_handler(my_ship.keydown)
frame.set_keyup_handler(my_ship.keyup)
timer = simplegui.create_timer(1000.0, rock_spawner)
# get things rolling
timer.start()
frame.start()

Review Your Peers: Spaceship

Week 8 - Sets and animation

Learn about sets in Python, compute collisions between sprites, animate sprites

Week 8a - Groups of Sprites

Sets11 min

http://www.codeskulptor.org/#examples-sets.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Examples of Sets
instructors = set(['Rixner', 'Warren', 'Greiner', 'Wong'])
print instructors
inst2 = set(['Rixner', 'Rixner', 'Warren', 'Warren', 'Greiner', 'Wong'])
print inst2
print instructors == inst2
for inst in instructors:
print inst
instructors.add('Colbert')
print instructors
instructors.add('Rixner')
print instructors
instructors.remove('Wong')
print instructors
#instructors.remove('Wong')
#print instructors
print 'Rixner' in instructors
print 'Wong' in instructors

http://www.codeskulptor.org/#examples-set_difference.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Examples of Sets 2
instructors = set(['Rixner', 'Warren', 'Greiner', 'Wong'])
print instructors
def get_rid_of(inst_set, starting_letter):
remove_set = set([])
for inst in inst_set:
if inst[0] == starting_letter:
remove_set.add(inst)
inst_set.difference_update(remove_set)
get_rid_of(instructors, 'W')
print instructors

Collisions for Sprites13 min

Practice Exercises for Sets and Collisions (optional)10 min

Week 8b - Animation

Sprite Animation12 min

http://www.codeskulptor.org/#examples-asteroid_animation.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# demo of animation using asteroid sprite sheet
import simplegui
# load 64 frame sprite sheer for asteroid - image source is opengameart, artist is warspawn
ROCK_CENTER = [64, 64]
ROCK_SIZE = [128, 128]
ROCK_DIM = 64
rock_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/asteroid1.opengameart.warspawn.png")
# global time for animation
time = 0
# draw handler
def draw(canvas):
global time
current_rock_index = (time % ROCK_DIM) // 1
current_rock_center = [ROCK_CENTER[0] + current_rock_index * ROCK_SIZE[0], ROCK_CENTER[1]]
canvas.draw_image(rock_image, current_rock_center, ROCK_SIZE, ROCK_CENTER, ROCK_SIZE)
time += 0.2
# create frame and size frame based on 128x128 pixel sprite
frame = simplegui.create_frame("Asteroid sprite", ROCK_SIZE[0], ROCK_SIZE[1])
# set draw handler and canvas background using custom HTML color
frame.set_draw_handler(draw)
frame.set_canvas_background("Blue")
# start animation
frame.start()

http://www.codeskulptor.org/#examples-explosion_animation.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# animation of explosion using 2D sprite sheet
import simplegui
# load 81 frame sprite sheer for explosion - image generated by phaedy explosion generator, source is hasgraphics.com
EXPLOSION_CENTER = [50, 50]
EXPLOSION_SIZE = [100, 100]
EXPLOSION_DIM = [9, 9]
explosion_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/explosion.hasgraphics.png")
# create timer that iterates current_sprite_center through sprite
time = 0
# define draw handler
def draw(canvas):
global time
explosion_index = [time % EXPLOSION_DIM[0], (time // EXPLOSION_DIM[0]) % EXPLOSION_DIM[1]]
canvas.draw_image(explosion_image,
[EXPLOSION_CENTER[0] + explosion_index[0] * EXPLOSION_SIZE[0],
EXPLOSION_CENTER[1] + explosion_index[1] * EXPLOSION_SIZE[1]],
EXPLOSION_SIZE, EXPLOSION_CENTER, EXPLOSION_SIZE)
time += 1
# create frame and size frame based on 100x100 pixel sprite
f = simplegui.create_frame("Asteroid sprite", EXPLOSION_SIZE[0], EXPLOSION_SIZE[1])
# set draw handler and canvas background using custom HTML color
f.set_draw_handler(draw)
f.set_canvas_background("Blue")
# start animation
f.start()

Programming Tips - 84 min

Quiz: Quiz 89 questions

QUIZ
Quiz 8
9 questions
To Pass70% or higher
Attempts3 every 8 hours
Deadline
December 10, 11:59 PM PST

Question 11 point
1.Question 1
Which of the following is valid notation for a set in CodeSkulptor?


{1,2,3}


set([1, 2, 3])


set([])


Question 21 point
2.Question 2
Which of the following operations can mutate set s? You may want to try some examples in CodeSkulptor and refer to the documentation.


s.intersection_update(s)


s.discard(x)


t.symmetric_difference(s)


s.update(t)


t.update(s)


s.difference(t)


Question 31 point
3.Question 3
Which of the following always give the same result as s.union(t)?

Refer to the CodeSkulptor documentation or try them on examples.


s.intersection(s.union(t))


s.union(s.symmetric_difference(t))


s.update(t)


s.union(t.difference(s))


Question 41 point
4.Question 4
A set is an unordered collection of distinct elements. Which of the following problem contexts represent instances of this idea?


Names for everyone taking this course


Group of distinct cities


Alphabetized names


1 point
5.Question 5
How many frames per second are typically projected in modern movies? How many times per second is the draw handler typically called in CodeSkulptor?

Enter two numbers representing these frame rates in frames per second. Use only spaces to separate the numbers.




Question 61 point
6.Question 6
For this week, the mini-project defines and uses a Sprite class to support animations. What attribute (also known as a field) can be used to help index the sub-images forming an animated sprite? (If you are stuck, review the bonus phase in the mini-project description.)


image_center


lifespan


animated


angle


pos


sound


age


image


image_size


radius


angle_vel


imagecenter imagesize pos


Question 71 point
7.Question 7
Consider a horizontally-tiled image where each sub-image has the same size. If each sub-image is of size 60×90 (in pixels), what is the horizontal distance (in pixels) between the centers of adjacent sub-images?


90


180


120


60


1 point
8.Question 8
How many distinct numbers are printed by the following code? Enter the count.

1
2
3
4
5
6
def next(x):
return (x ** 2 + 79) % 997
x = 1
for i in range(1000):
print x
x = next(x)

Hint: Consider how editing the code to use a set could help solve the question.




Question 91 point
9.Question 9
Which instructor exhibits the best coding style?


Scott


Joe


John


Stephen

Mini Project #8 - RiceRocks (Asteroids)

Mini-project Video8 min

http://www.codeskulptor.org/#examples-ricerocks_template.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# implementation of Spaceship - program template for RiceRocks
import simplegui
import math
import random
# globals for user interface
WIDTH = 800
HEIGHT = 600
score = 0
lives = 3
time = 0
started = False
class ImageInfo:
def __init__(self, center, size, radius = 0, lifespan = None, animated = False):
self.center = center
self.size = size
self.radius = radius
if lifespan:
self.lifespan = lifespan
else:
self.lifespan = float('inf')
self.animated = animated
def get_center(self):
return self.center
def get_size(self):
return self.size
def get_radius(self):
return self.radius
def get_lifespan(self):
return self.lifespan
def get_animated(self):
return self.animated
# art assets created by Kim Lathrop, may be freely re-used in non-commercial projects, please credit Kim
# debris images - debris1_brown.png, debris2_brown.png, debris3_brown.png, debris4_brown.png
# debris1_blue.png, debris2_blue.png, debris3_blue.png, debris4_blue.png, debris_blend.png
debris_info = ImageInfo([320, 240], [640, 480])
debris_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/debris2_blue.png")
# nebula images - nebula_brown.png, nebula_blue.png
nebula_info = ImageInfo([400, 300], [800, 600])
nebula_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/nebula_blue.f2014.png")
# splash image
splash_info = ImageInfo([200, 150], [400, 300])
splash_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/splash.png")
# ship image
ship_info = ImageInfo([45, 45], [90, 90], 35)
ship_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/double_ship.png")
# missile image - shot1.png, shot2.png, shot3.png
missile_info = ImageInfo([5,5], [10, 10], 3, 50)
missile_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/shot2.png")
# asteroid images - asteroid_blue.png, asteroid_brown.png, asteroid_blend.png
asteroid_info = ImageInfo([45, 45], [90, 90], 40)
asteroid_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blue.png")
# animated explosion - explosion_orange.png, explosion_blue.png, explosion_blue2.png, explosion_alpha.png
explosion_info = ImageInfo([64, 64], [128, 128], 17, 24, True)
explosion_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/explosion_alpha.png")
# sound assets purchased from sounddogs.com, please do not redistribute
# .ogg versions of sounds are also available, just replace .mp3 by .ogg
soundtrack = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/soundtrack.mp3")
missile_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/missile.mp3")
missile_sound.set_volume(.5)
ship_thrust_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/thrust.mp3")
explosion_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/explosion.mp3")
# alternative upbeat soundtrack by composer and former IIPP student Emiel Stopler
# please do not redistribute without permission from Emiel at http://www.filmcomposer.nl
#soundtrack = simplegui.load_sound("https://storage.googleapis.com/codeskulptor-assets/ricerocks_theme.mp3")
# helper functions to handle transformations
def angle_to_vector(ang):
return [math.cos(ang), math.sin(ang)]
def dist(p, q):
return math.sqrt((p[0] - q[0]) ** 2 + (p[1] - q[1]) ** 2)
# Ship class
class Ship:
def __init__(self, pos, vel, angle, image, info):
self.pos = [pos[0], pos[1]]
self.vel = [vel[0], vel[1]]
self.thrust = False
self.angle = angle
self.angle_vel = 0
self.image = image
self.image_center = info.get_center()
self.image_size = info.get_size()
self.radius = info.get_radius()
def draw(self,canvas):
if self.thrust:
canvas.draw_image(self.image, [self.image_center[0] + self.image_size[0], self.image_center[1]] , self.image_size,
self.pos, self.image_size, self.angle)
else:
canvas.draw_image(self.image, self.image_center, self.image_size,
self.pos, self.image_size, self.angle)
# canvas.draw_circle(self.pos, self.radius, 1, "White", "White")
def update(self):
# update angle
self.angle += self.angle_vel
# update position
self.pos[0] = (self.pos[0] + self.vel[0]) % WIDTH
self.pos[1] = (self.pos[1] + self.vel[1]) % HEIGHT
# update velocity
if self.thrust:
acc = angle_to_vector(self.angle)
self.vel[0] += acc[0] * .1
self.vel[1] += acc[1] * .1
self.vel[0] *= .99
self.vel[1] *= .99
def set_thrust(self, on):
self.thrust = on
if on:
ship_thrust_sound.rewind()
ship_thrust_sound.play()
else:
ship_thrust_sound.pause()
def increment_angle_vel(self):
self.angle_vel += .05
def decrement_angle_vel(self):
self.angle_vel -= .05
def shoot(self):
global a_missile
forward = angle_to_vector(self.angle)
missile_pos = [self.pos[0] + self.radius * forward[0], self.pos[1] + self.radius * forward[1]]
missile_vel = [self.vel[0] + 6 * forward[0], self.vel[1] + 6 * forward[1]]
a_missile = Sprite(missile_pos, missile_vel, self.angle, 0, missile_image, missile_info, missile_sound)
# Sprite class
class Sprite:
def __init__(self, pos, vel, ang, ang_vel, image, info, sound = None):
self.pos = [pos[0],pos[1]]
self.vel = [vel[0],vel[1]]
self.angle = ang
self.angle_vel = ang_vel
self.image = image
self.image_center = info.get_center()
self.image_size = info.get_size()
self.radius = info.get_radius()
self.lifespan = info.get_lifespan()
self.animated = info.get_animated()
self.age = 0
if sound:
sound.rewind()
sound.play()
def draw(self, canvas):
canvas.draw_image(self.image, self.image_center, self.image_size,
self.pos, self.image_size, self.angle)
def update(self):
# update angle
self.angle += self.angle_vel
# update position
self.pos[0] = (self.pos[0] + self.vel[0]) % WIDTH
self.pos[1] = (self.pos[1] + self.vel[1]) % HEIGHT
# key handlers to control ship
def keydown(key):
if key == simplegui.KEY_MAP['left']:
my_ship.decrement_angle_vel()
elif key == simplegui.KEY_MAP['right']:
my_ship.increment_angle_vel()
elif key == simplegui.KEY_MAP['up']:
my_ship.set_thrust(True)
elif key == simplegui.KEY_MAP['space']:
my_ship.shoot()
def keyup(key):
if key == simplegui.KEY_MAP['left']:
my_ship.increment_angle_vel()
elif key == simplegui.KEY_MAP['right']:
my_ship.decrement_angle_vel()
elif key == simplegui.KEY_MAP['up']:
my_ship.set_thrust(False)
# mouseclick handlers that reset UI and conditions whether splash image is drawn
def click(pos):
global started
center = [WIDTH / 2, HEIGHT / 2]
size = splash_info.get_size()
inwidth = (center[0] - size[0] / 2) < pos[0] < (center[0] + size[0] / 2)
inheight = (center[1] - size[1] / 2) < pos[1] < (center[1] + size[1] / 2)
if (not started) and inwidth and inheight:
started = True
def draw(canvas):
global time, started
# animiate background
time += 1
wtime = (time / 4) % WIDTH
center = debris_info.get_center()
size = debris_info.get_size()
canvas.draw_image(nebula_image, nebula_info.get_center(), nebula_info.get_size(), [WIDTH / 2, HEIGHT / 2], [WIDTH, HEIGHT])
canvas.draw_image(debris_image, center, size, (wtime - WIDTH / 2, HEIGHT / 2), (WIDTH, HEIGHT))
canvas.draw_image(debris_image, center, size, (wtime + WIDTH / 2, HEIGHT / 2), (WIDTH, HEIGHT))
# draw UI
canvas.draw_text("Lives", [50, 50], 22, "White")
canvas.draw_text("Score", [680, 50], 22, "White")
canvas.draw_text(str(lives), [50, 80], 22, "White")
canvas.draw_text(str(score), [680, 80], 22, "White")
# draw ship and sprites
my_ship.draw(canvas)
a_rock.draw(canvas)
a_missile.draw(canvas)
# update ship and sprites
my_ship.update()
a_rock.update()
a_missile.update()
# draw splash screen if not started
if not started:
canvas.draw_image(splash_image, splash_info.get_center(),
splash_info.get_size(), [WIDTH / 2, HEIGHT / 2],
splash_info.get_size())
# timer handler that spawns a rock
def rock_spawner():
global a_rock
rock_pos = [random.randrange(0, WIDTH), random.randrange(0, HEIGHT)]
rock_vel = [random.random() * .6 - .3, random.random() * .6 - .3]
rock_avel = random.random() * .2 - .1
a_rock = Sprite(rock_pos, rock_vel, 0, rock_avel, asteroid_image, asteroid_info)
# initialize stuff
frame = simplegui.create_frame("Asteroids", WIDTH, HEIGHT)
# initialize ship and two sprites
my_ship = Ship([WIDTH / 2, HEIGHT / 2], [0, 0], 0, ship_image, ship_info)
a_rock = Sprite([WIDTH / 3, HEIGHT / 3], [1, 1], 0, .1, asteroid_image, asteroid_info)
a_missile = Sprite([2 * WIDTH / 3, 2 * HEIGHT / 3], [-1,1], 0, 0, missile_image, missile_info, missile_sound)
# register handlers
frame.set_keyup_handler(keyup)
frame.set_keydown_handler(keydown)
frame.set_mouseclick_handler(click)
frame.set_draw_handler(draw)
timer = simplegui.create_timer(1000.0, rock_spawner)
# get things rolling
timer.start()
frame.start()

Mini-project Description10 min

Code Clinic Tips10 min

Peer-graded Assignment: RiceRocks2h

http://www.codeskulptor.org/#user43_QY7BxM32XH_0.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
# implementation of Spaceship - program template for RiceRocks
import simplegui
import math
import random
# globals for user interface
WIDTH = 800
HEIGHT = 600
score = 0
lives = 3
time = 0
started = False
ROCK_NUMBER = 12
class ImageInfo:
def __init__(self, center, size, radius = 0, lifespan = None, animated = False):
self.center = center
self.size = size
self.radius = radius
if lifespan:
self.lifespan = lifespan
else:
self.lifespan = float('inf')
self.animated = animated
def get_center(self):
return self.center
def get_size(self):
return self.size
def get_radius(self):
return self.radius
def get_lifespan(self):
return self.lifespan
def get_animated(self):
return self.animated
# art assets created by Kim Lathrop, may be freely re-used in non-commercial projects, please credit Kim
# debris images - debris1_brown.png, debris2_brown.png, debris3_brown.png, debris4_brown.png
# debris1_blue.png, debris2_blue.png, debris3_blue.png, debris4_blue.png, debris_blend.png
debris_info = ImageInfo([320, 240], [640, 480])
debris_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/debris2_blue.png")
# nebula images - nebula_brown.png, nebula_blue.png
nebula_info = ImageInfo([400, 300], [800, 600])
nebula_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/nebula_blue.f2014.png")
# splash image
splash_info = ImageInfo([200, 150], [400, 300])
splash_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/splash.png")
# ship image
ship_info = ImageInfo([45, 45], [90, 90], 35)
ship_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/double_ship.png")
# missile image - shot1.png, shot2.png, shot3.png
missile_info = ImageInfo([5,5], [10, 10], 3, 50)
missile_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/shot2.png")
# asteroid images - asteroid_blue.png, asteroid_brown.png, asteroid_blend.png
asteroid_info = ImageInfo([45, 45], [90, 90], 40)
asteroid_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blue.png")
# animated explosion - explosion_orange.png, explosion_blue.png, explosion_blue2.png, explosion_alpha.png
explosion_info = ImageInfo([64, 64], [128, 128], 17, 24, True)
explosion_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/explosion_alpha.png")
# sound assets purchased from sounddogs.com, please do not redistribute
# .ogg versions of sounds are also available, just replace .mp3 by .ogg
soundtrack = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/soundtrack.mp3")
missile_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/missile.mp3")
missile_sound.set_volume(.5)
ship_thrust_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/thrust.mp3")
explosion_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/explosion.mp3")
# alternative upbeat soundtrack by composer and former IIPP student Emiel Stopler
# please do not redistribute without permission from Emiel at http://www.filmcomposer.nl
#soundtrack = simplegui.load_sound("https://storage.googleapis.com/codeskulptor-assets/ricerocks_theme.mp3")
# helper functions to handle transformations
def angle_to_vector(ang):
return [math.cos(ang), math.sin(ang)]
def dist(p, q):
return math.sqrt((p[0] - q[0]) ** 2 + (p[1] - q[1]) ** 2)
def process_sprite_group(canvas, instance_set):
for instance in instance_set:
instance.draw(canvas)
instance.update()
# Ship class
class Ship:
def __init__(self, pos, vel, angle, image, info):
self.pos = [pos[0], pos[1]]
self.vel = [vel[0], vel[1]]
self.thrust = False
self.angle = angle
self.angle_vel = 0
self.image = image
self.image_center = info.get_center()
self.image_size = info.get_size()
self.radius = info.get_radius()
def draw(self,canvas):
if self.thrust:
canvas.draw_image(self.image, [self.image_center[0] + self.image_size[0], self.image_center[1]] , self.image_size,
self.pos, self.image_size, self.angle)
else:
canvas.draw_image(self.image, self.image_center, self.image_size,
self.pos, self.image_size, self.angle)
# canvas.draw_circle(self.pos, self.radius, 1, "White", "White")
def update(self):
# update angle
self.angle += self.angle_vel
# update position
self.pos[0] = (self.pos[0] + self.vel[0]) % WIDTH
self.pos[1] = (self.pos[1] + self.vel[1]) % HEIGHT
# update velocity
if self.thrust:
acc = angle_to_vector(self.angle)
self.vel[0] += acc[0] * .1
self.vel[1] += acc[1] * .1
self.vel[0] *= .99
self.vel[1] *= .99
def set_thrust(self, on):
self.thrust = on
if on:
ship_thrust_sound.rewind()
ship_thrust_sound.play()
else:
ship_thrust_sound.pause()
def increment_angle_vel(self):
self.angle_vel += .05
def decrement_angle_vel(self):
self.angle_vel -= .05
def shoot(self):
global a_missile
forward = angle_to_vector(self.angle)
missile_pos = [self.pos[0] + self.radius * forward[0], self.pos[1] + self.radius * forward[1]]
missile_vel = [self.vel[0] + 6 * forward[0], self.vel[1] + 6 * forward[1]]
a_missile = Sprite(missile_pos, missile_vel, self.angle, 0, missile_image, missile_info, missile_sound)
# Sprite class
class Sprite:
def __init__(self, pos, vel, ang, ang_vel, image, info, sound = None):
self.pos = [pos[0],pos[1]]
self.vel = [vel[0],vel[1]]
self.angle = ang
self.angle_vel = ang_vel
self.image = image
self.image_center = info.get_center()
self.image_size = info.get_size()
self.radius = info.get_radius()
self.lifespan = info.get_lifespan()
self.animated = info.get_animated()
self.age = 0
if sound:
sound.rewind()
sound.play()
def draw(self, canvas):
canvas.draw_image(self.image, self.image_center, self.image_size,
self.pos, self.image_size, self.angle)
def update(self):
# update angle
self.angle += self.angle_vel
# update position
self.pos[0] = (self.pos[0] + self.vel[0]) % WIDTH
self.pos[1] = (self.pos[1] + self.vel[1]) % HEIGHT
# key handlers to control ship
def keydown(key):
if key == simplegui.KEY_MAP['left']:
my_ship.decrement_angle_vel()
elif key == simplegui.KEY_MAP['right']:
my_ship.increment_angle_vel()
elif key == simplegui.KEY_MAP['up']:
my_ship.set_thrust(True)
elif key == simplegui.KEY_MAP['space']:
my_ship.shoot()
def keyup(key):
if key == simplegui.KEY_MAP['left']:
my_ship.increment_angle_vel()
elif key == simplegui.KEY_MAP['right']:
my_ship.decrement_angle_vel()
elif key == simplegui.KEY_MAP['up']:
my_ship.set_thrust(False)
# mouseclick handlers that reset UI and conditions whether splash image is drawn
def click(pos):
global started
center = [WIDTH / 2, HEIGHT / 2]
size = splash_info.get_size()
inwidth = (center[0] - size[0] / 2) < pos[0] < (center[0] + size[0] / 2)
inheight = (center[1] - size[1] / 2) < pos[1] < (center[1] + size[1] / 2)
if (not started) and inwidth and inheight:
started = True
def draw(canvas):
global time, started, rock_group
# animiate background
time += 1
wtime = (time / 4) % WIDTH
center = debris_info.get_center()
size = debris_info.get_size()
canvas.draw_image(nebula_image, nebula_info.get_center(), nebula_info.get_size(), [WIDTH / 2, HEIGHT / 2], [WIDTH, HEIGHT])
canvas.draw_image(debris_image, center, size, (wtime - WIDTH / 2, HEIGHT / 2), (WIDTH, HEIGHT))
canvas.draw_image(debris_image, center, size, (wtime + WIDTH / 2, HEIGHT / 2), (WIDTH, HEIGHT))
# draw UI
canvas.draw_text("Lives", [50, 50], 22, "White")
canvas.draw_text("Score", [680, 50], 22, "White")
canvas.draw_text(str(lives), [50, 80], 22, "White")
canvas.draw_text(str(score), [680, 80], 22, "White")
# draw ship and sprites
my_ship.draw(canvas)
a_missile.draw(canvas)
# update ship and sprites
my_ship.update()
a_missile.update()
# draw and update rocks in rock_group
process_sprite_group(canvas, rock_group)
# draw splash screen if not started
if not started:
canvas.draw_image(splash_image, splash_info.get_center(),
splash_info.get_size(), [WIDTH / 2, HEIGHT / 2],
splash_info.get_size())
# timer handler that spawns a rock
def rock_spawner():
global rock_group, ROCK_NUMBER
rock_pos = [random.randrange(0, WIDTH), random.randrange(0, HEIGHT)]
rock_vel = [random.random() * .6 - .3, random.random() * .6 - .3]
rock_avel = random.random() * .2 - .1
a_rock = Sprite(rock_pos, rock_vel, 0, rock_avel, asteroid_image, asteroid_info)
if len(rock_group) <= ROCK_NUMBER:
rock_group.add(a_rock)
# initialize stuff
rock_group = set()
frame = simplegui.create_frame("Asteroids", WIDTH, HEIGHT)
# initialize ship and two sprites
my_ship = Ship([WIDTH / 2, HEIGHT / 2], [0, 0], 0, ship_image, ship_info)
a_rock = Sprite([WIDTH / 3, HEIGHT / 3], [1, 1], 0, .1, asteroid_image, asteroid_info)
a_missile = Sprite([2 * WIDTH / 3, 2 * HEIGHT / 3], [-1,1], 0, 0, missile_image, missile_info, missile_sound)
# register handlers
frame.set_keyup_handler(keyup)
frame.set_keydown_handler(keydown)
frame.set_mouseclick_handler(click)
frame.set_draw_handler(draw)
timer = simplegui.create_timer(1000.0, rock_spawner)
# get things rolling
timer.start()
frame.start()

http://www.codeskulptor.org/#user43_QY7BxM32XH_1.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# implementation of Spaceship - program template for RiceRocks
import simplegui
import math
import random
# globals for user interface
WIDTH = 800
HEIGHT = 600
score = 0
lives = 3
time = 0
started = False
ROCK_NUMBER = 12
AGE_INCRE = 1
EXPLOSION_DIM = [9, 9]
explosion_group = set()
class ImageInfo:
def __init__(self, center, size, radius = 0, lifespan = None, animated = False):
self.center = center
self.size = size
self.radius = radius
if lifespan:
self.lifespan = lifespan
else:
self.lifespan = float('inf')
self.animated = animated
def get_center(self):
return self.center
def get_size(self):
return self.size
def get_radius(self):
return self.radius
def get_lifespan(self):
return self.lifespan
def get_animated(self):
return self.animated
# art assets created by Kim Lathrop, may be freely re-used in non-commercial projects, please credit Kim
# debris images - debris1_brown.png, debris2_brown.png, debris3_brown.png, debris4_brown.png
# debris1_blue.png, debris2_blue.png, debris3_blue.png, debris4_blue.png, debris_blend.png
debris_info = ImageInfo([320, 240], [640, 480])
debris_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/debris2_blue.png")
# nebula images - nebula_brown.png, nebula_blue.png
nebula_info = ImageInfo([400, 300], [800, 600])
nebula_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/nebula_blue.f2014.png")
# splash image
splash_info = ImageInfo([200, 150], [400, 300])
splash_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/splash.png")
# ship image
ship_info = ImageInfo([45, 45], [90, 90], 35)
ship_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/double_ship.png")
# missile image - shot1.png, shot2.png, shot3.png
missile_info = ImageInfo([5,5], [10, 10], 3, 50)
missile_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/shot2.png")
# asteroid images - asteroid_blue.png, asteroid_brown.png, asteroid_blend.png
asteroid_info = ImageInfo([45, 45], [90, 90], 40)
asteroid_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blue.png")
# animated explosion - explosion_orange.png, explosion_blue.png, explosion_blue2.png, explosion_alpha.png
explosion_info = ImageInfo([64, 64], [128, 128], 17, 24, True)
explosion_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/explosion_alpha.png")
# sound assets purchased from sounddogs.com, please do not redistribute
# .ogg versions of sounds are also available, just replace .mp3 by .ogg
soundtrack = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/soundtrack.mp3")
missile_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/missile.mp3")
missile_sound.set_volume(.5)
ship_thrust_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/thrust.mp3")
explosion_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/explosion.mp3")
# alternative upbeat soundtrack by composer and former IIPP student Emiel Stopler
# please do not redistribute without permission from Emiel at http://www.filmcomposer.nl
#soundtrack = simplegui.load_sound("https://storage.googleapis.com/codeskulptor-assets/ricerocks_theme.mp3")
# helper functions to handle transformations
def angle_to_vector(ang):
return [math.cos(ang), math.sin(ang)]
def dist(p, q):
return math.sqrt((p[0] - q[0]) ** 2 + (p[1] - q[1]) ** 2)
def process_sprite_group(canvas, instance_set):
removed = set()
for instance in instance_set:
if instance.update(): # True -- age >= lifespan
removed.add(instance)
else:
instance.draw(canvas)
instance_set.difference_update(removed)
def group_collide(group_set, other_object):
f = False
removed = set()
for sprite in group_set:
if sprite.collide(other_object):
removed.add(sprite)
f = True
group_set.difference_update(removed)
return f
def group_group_collide(group_missile, group_rock):
num = 0
for rock in group_rock:
if group_collide(group_missile, rock):
group_rock.discard(rock)
num += 1
return num
# Ship class
class Ship:
def __init__(self, pos, vel, angle, image, info):
self.pos = [pos[0], pos[1]]
self.vel = [vel[0], vel[1]]
self.thrust = False
self.angle = angle
self.angle_vel = 0
self.image = image
self.image_center = info.get_center()
self.image_size = info.get_size()
self.radius = info.get_radius()
def draw(self,canvas):
if self.thrust:
canvas.draw_image(self.image, [self.image_center[0] + self.image_size[0], self.image_center[1]] , self.image_size,
self.pos, self.image_size, self.angle)
else:
canvas.draw_image(self.image, self.image_center, self.image_size,
self.pos, self.image_size, self.angle)
# canvas.draw_circle(self.pos, self.radius, 1, "White", "White")
def update(self):
# update angle
self.angle += self.angle_vel
# update position
self.pos[0] = (self.pos[0] + self.vel[0]) % WIDTH
self.pos[1] = (self.pos[1] + self.vel[1]) % HEIGHT
# update velocity
if self.thrust:
acc = angle_to_vector(self.angle)
self.vel[0] += acc[0] * .1
self.vel[1] += acc[1] * .1
self.vel[0] *= .99
self.vel[1] *= .99
def set_thrust(self, on):
self.thrust = on
if on:
ship_thrust_sound.rewind()
ship_thrust_sound.play()
else:
ship_thrust_sound.pause()
def increment_angle_vel(self):
self.angle_vel += .05
def decrement_angle_vel(self):
self.angle_vel -= .05
def shoot(self):
global missile_group
forward = angle_to_vector(self.angle)
missile_pos = [self.pos[0] + self.radius * forward[0], self.pos[1] + self.radius * forward[1]]
missile_vel = [self.vel[0] + 6 * forward[0], self.vel[1] + 6 * forward[1]]
a_missile = Sprite(missile_pos, missile_vel, self.angle, 0, missile_image, missile_info, missile_sound)
missile_group.add(a_missile)
def get_position(self):
return self.pos
def get_radius(self):
return self.radius
# Sprite class
class Sprite:
def __init__(self, pos, vel, ang, ang_vel, image, info, sound = None):
self.pos = [pos[0],pos[1]]
self.vel = [vel[0],vel[1]]
self.angle = ang
self.angle_vel = ang_vel
self.image = image
self.image_center = info.get_center()
self.image_size = info.get_size()
self.radius = info.get_radius()
self.lifespan = info.get_lifespan()
self.animated = info.get_animated()
self.age = 0
if sound:
sound.rewind()
sound.play()
def draw(self, canvas):
global time
if self.animated:
time = 0
#explosion_index = [time % EXPLOSION_DIM[0], (time // EXPLOSION_DIM[0]) % EXPLOSION_DIM[1]]
explosion_index = time % 24
canvas.draw_image(explosion_image, [explosion_info.get_center()[0] + explosion_index * explosion_info.get_size()[0],
explosion_info.get_center()[1]],
explosion_info.get_size(), self.pos, explosion_info.get_size())
time += 1
else:
canvas.draw_image(self.image, self.image_center, self.image_size,
self.pos, self.image_size, self.angle)
def update(self):
# update angle
self.angle += self.angle_vel
# update position
self.pos[0] = (self.pos[0] + self.vel[0]) % WIDTH
self.pos[1] = (self.pos[1] + self.vel[1]) % HEIGHT
# update age
self.age += AGE_INCRE
return self.age >= self.lifespan
def collide(self, other_object):
dis = dist(self.pos, other_object.get_position())
if dis > (self.radius + other_object.get_radius()):
return False
else:
return True
def get_position(self):
return self.pos
def get_radius(self):
return self.radius
# key handlers to control ship
def keydown(key):
if key == simplegui.KEY_MAP['left']:
my_ship.decrement_angle_vel()
elif key == simplegui.KEY_MAP['right']:
my_ship.increment_angle_vel()
elif key == simplegui.KEY_MAP['up']:
my_ship.set_thrust(True)
elif key == simplegui.KEY_MAP['space']:
my_ship.shoot()
def keyup(key):
if key == simplegui.KEY_MAP['left']:
my_ship.increment_angle_vel()
elif key == simplegui.KEY_MAP['right']:
my_ship.decrement_angle_vel()
elif key == simplegui.KEY_MAP['up']:
my_ship.set_thrust(False)
# mouseclick handlers that reset UI and conditions whether splash image is drawn
def click(pos):
global started, time, score, lives
center = [WIDTH / 2, HEIGHT / 2]
size = splash_info.get_size()
inwidth = (center[0] - size[0] / 2) < pos[0] < (center[0] + size[0] / 2)
inheight = (center[1] - size[1] / 2) < pos[1] < (center[1] + size[1] / 2)
if (not started) and inwidth and inheight:
started = True
time = 0
score = 0
lives = 3
soundtrack.rewind()
soundtrack.play()
def draw(canvas):
global time, started, rock_group, missile_group, lives, score
# animiate background
time += 1
wtime = (time / 4) % WIDTH
center = debris_info.get_center()
size = debris_info.get_size()
canvas.draw_image(nebula_image, nebula_info.get_center(), nebula_info.get_size(), [WIDTH / 2, HEIGHT / 2], [WIDTH, HEIGHT])
canvas.draw_image(debris_image, center, size, (wtime - WIDTH / 2, HEIGHT / 2), (WIDTH, HEIGHT))
canvas.draw_image(debris_image, center, size, (wtime + WIDTH / 2, HEIGHT / 2), (WIDTH, HEIGHT))
# draw UI
canvas.draw_text("Lives", [50, 50], 22, "White")
canvas.draw_text("Score", [680, 50], 22, "White")
canvas.draw_text(str(lives), [50, 80], 22, "White")
canvas.draw_text(str(score), [680, 80], 22, "White")
# draw ship and sprites
my_ship.draw(canvas)
# update ship and sprites
my_ship.update()
# collision between rocks and ship
if group_collide(rock_group, my_ship):
lives -= 1
if lives <= 0:
started = False
rock_group = set()
# collision between missile and rock
score += group_group_collide(missile_group, rock_group)
# draw and update rocks and missile in group
process_sprite_group(canvas, rock_group)
process_sprite_group(canvas, missile_group)
# draw splash screen if not started
if not started:
canvas.draw_image(splash_image, splash_info.get_center(),
splash_info.get_size(), [WIDTH / 2, HEIGHT / 2],
splash_info.get_size())
# timer handler that spawns a rock
def rock_spawner():
global rock_group, ROCK_NUMBER, started, score
rock_pos = [random.randrange(0, WIDTH), random.randrange(0, HEIGHT)]
rock_vel = [random.random() * .6 - .3+score, random.random() * .6 - .3+score]
rock_avel = random.random() * .2 - .1
a_rock = Sprite(rock_pos, rock_vel, 0, rock_avel, asteroid_image, asteroid_info)
dis = dist(my_ship.get_position(), a_rock.get_position())
far_to_ship = dis > 2 * (my_ship.get_radius() + a_rock.get_radius())
if len(rock_group) <= ROCK_NUMBER and started and far_to_ship:
rock_group.add(a_rock)
# initialize stuff
rock_group = set()
missile_group = set()
frame = simplegui.create_frame("Asteroids", WIDTH, HEIGHT)
# initialize ship and two sprites
my_ship = Ship([WIDTH / 2, HEIGHT / 2], [0, 0], 0, ship_image, ship_info)
a_rock = Sprite([WIDTH / 3, HEIGHT / 3], [1, 1], 0, .1, asteroid_image, asteroid_info)
a_missile = Sprite([2 * WIDTH / 3, 2 * HEIGHT / 3], [-1,1], 0, 0, missile_image, missile_info, missile_sound)
# register handlers
frame.set_keyup_handler(keyup)
frame.set_keydown_handler(keydown)
frame.set_mouseclick_handler(click)
frame.set_draw_handler(draw)
timer = simplegui.create_timer(1000.0, rock_spawner)
# get things rolling
timer.start()
frame.start()

http://www.codeskulptor.org/#user43_QY7BxM32XH_2.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
# implementation of Spaceship - program template for RiceRocks
import simplegui
import math
import random
# globals for user interface
WIDTH = 800
HEIGHT = 600
score = 0
lives = 3
time = 0
started = False
ROCK_NUMBER = 12
AGE_INCRE = 1
EXPLOSION_DIM = [9, 9]
explosion_group = set()
class ImageInfo:
def __init__(self, center, size, radius = 0, lifespan = None, animated = False):
self.center = center
self.size = size
self.radius = radius
if lifespan:
self.lifespan = lifespan
else:
self.lifespan = float('inf')
self.animated = animated
def get_center(self):
return self.center
def get_size(self):
return self.size
def get_radius(self):
return self.radius
def get_lifespan(self):
return self.lifespan
def get_animated(self):
return self.animated
# art assets created by Kim Lathrop, may be freely re-used in non-commercial projects, please credit Kim
# debris images - debris1_brown.png, debris2_brown.png, debris3_brown.png, debris4_brown.png
# debris1_blue.png, debris2_blue.png, debris3_blue.png, debris4_blue.png, debris_blend.png
debris_info = ImageInfo([320, 240], [640, 480])
debris_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/debris2_blue.png")
# nebula images - nebula_brown.png, nebula_blue.png
nebula_info = ImageInfo([400, 300], [800, 600])
nebula_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/nebula_blue.f2014.png")
# splash image
splash_info = ImageInfo([200, 150], [400, 300])
splash_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/splash.png")
# ship image
ship_info = ImageInfo([45, 45], [90, 90], 35)
ship_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/double_ship.png")
# missile image - shot1.png, shot2.png, shot3.png
missile_info = ImageInfo([5,5], [10, 10], 3, 50)
missile_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/shot2.png")
# asteroid images - asteroid_blue.png, asteroid_brown.png, asteroid_blend.png
asteroid_info = ImageInfo([45, 45], [90, 90], 40)
asteroid_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blue.png")
# animated explosion - explosion_orange.png, explosion_blue.png, explosion_blue2.png, explosion_alpha.png
explosion_info = ImageInfo([64, 64], [128, 128], 17, 24, True)
explosion_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/explosion_alpha.png")
# sound assets purchased from sounddogs.com, please do not redistribute
# .ogg versions of sounds are also available, just replace .mp3 by .ogg
soundtrack = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/soundtrack.mp3")
missile_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/missile.mp3")
missile_sound.set_volume(.5)
ship_thrust_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/thrust.mp3")
explosion_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/explosion.mp3")
# alternative upbeat soundtrack by composer and former IIPP student Emiel Stopler
# please do not redistribute without permission from Emiel at http://www.filmcomposer.nl
#soundtrack = simplegui.load_sound("https://storage.googleapis.com/codeskulptor-assets/ricerocks_theme.mp3")
# helper functions to handle transformations
def angle_to_vector(ang):
return [math.cos(ang), math.sin(ang)]
def dist(p, q):
return math.sqrt((p[0] - q[0]) ** 2 + (p[1] - q[1]) ** 2)
def process_sprite_group(canvas, instance_set):
removed = set()
for instance in instance_set:
if instance.update(): # True -- age >= lifespan
removed.add(instance)
else:
instance.draw(canvas)
instance_set.difference_update(removed)
def group_collide(group_set, other_object):
global explosion_group
f = False
removed = set()
for sprite in group_set:
if sprite.collide(other_object):
explosion = Sprite(other_object.get_position(), [0,0], 0, 0, explosion_image, explosion_info, sound = explosion_sound)
explosion_group.add(explosion)
removed.add(sprite)
f = True
group_set.difference_update(removed)
return f
def group_group_collide(group_missile, group_rock):
num = 0
for rock in group_rock:
if group_collide(group_missile, rock):
group_rock.discard(rock)
num += 1
return num
# Ship class
class Ship:
def __init__(self, pos, vel, angle, image, info):
self.pos = [pos[0], pos[1]]
self.vel = [vel[0], vel[1]]
self.thrust = False
self.angle = angle
self.angle_vel = 0
self.image = image
self.image_center = info.get_center()
self.image_size = info.get_size()
self.radius = info.get_radius()
def draw(self,canvas):
if self.thrust:
canvas.draw_image(self.image, [self.image_center[0] + self.image_size[0], self.image_center[1]] , self.image_size,
self.pos, self.image_size, self.angle)
else:
canvas.draw_image(self.image, self.image_center, self.image_size,
self.pos, self.image_size, self.angle)
# canvas.draw_circle(self.pos, self.radius, 1, "White", "White")
def update(self):
# update angle
self.angle += self.angle_vel
# update position
self.pos[0] = (self.pos[0] + self.vel[0]) % WIDTH
self.pos[1] = (self.pos[1] + self.vel[1]) % HEIGHT
# update velocity
if self.thrust:
acc = angle_to_vector(self.angle)
self.vel[0] += acc[0] * .1
self.vel[1] += acc[1] * .1
self.vel[0] *= .99
self.vel[1] *= .99
def set_thrust(self, on):
self.thrust = on
if on:
ship_thrust_sound.rewind()
ship_thrust_sound.play()
else:
ship_thrust_sound.pause()
def increment_angle_vel(self):
self.angle_vel += .05
def decrement_angle_vel(self):
self.angle_vel -= .05
def shoot(self):
global missile_group
forward = angle_to_vector(self.angle)
missile_pos = [self.pos[0] + self.radius * forward[0], self.pos[1] + self.radius * forward[1]]
missile_vel = [self.vel[0] + 6 * forward[0], self.vel[1] + 6 * forward[1]]
a_missile = Sprite(missile_pos, missile_vel, self.angle, 0, missile_image, missile_info, missile_sound)
missile_group.add(a_missile)
def get_position(self):
return self.pos
def get_radius(self):
return self.radius
# Sprite class
class Sprite:
def __init__(self, pos, vel, ang, ang_vel, image, info, sound = None):
self.pos = [pos[0],pos[1]]
self.vel = [vel[0],vel[1]]
self.angle = ang
self.angle_vel = ang_vel
self.image = image
self.image_center = info.get_center()
self.image_size = info.get_size()
self.radius = info.get_radius()
self.lifespan = info.get_lifespan()
self.animated = info.get_animated()
self.age = 0
if sound:
sound.rewind()
sound.play()
def draw(self, canvas):
global time
if self.animated:
explosion_index = time % 24
canvas.draw_image(explosion_image, [explosion_info.get_center()[0] + explosion_index * explosion_info.get_size()[0],
explosion_info.get_center()[1]],
explosion_info.get_size(), self.pos, explosion_info.get_size())
else:
canvas.draw_image(self.image, self.image_center, self.image_size,
self.pos, self.image_size, self.angle)
def update(self):
# update angle
self.angle += self.angle_vel
# update position
self.pos[0] = (self.pos[0] + self.vel[0]) % WIDTH
self.pos[1] = (self.pos[1] + self.vel[1]) % HEIGHT
# update age
self.age += AGE_INCRE
return self.age >= self.lifespan
def collide(self, other_object):
dis = dist(self.pos, other_object.get_position())
if dis > (self.radius + other_object.get_radius()):
return False
else:
return True
def get_position(self):
return self.pos
def get_radius(self):
return self.radius
# key handlers to control ship
def keydown(key):
if key == simplegui.KEY_MAP['left']:
my_ship.decrement_angle_vel()
elif key == simplegui.KEY_MAP['right']:
my_ship.increment_angle_vel()
elif key == simplegui.KEY_MAP['up']:
my_ship.set_thrust(True)
elif key == simplegui.KEY_MAP['space']:
my_ship.shoot()
def keyup(key):
if key == simplegui.KEY_MAP['left']:
my_ship.increment_angle_vel()
elif key == simplegui.KEY_MAP['right']:
my_ship.decrement_angle_vel()
elif key == simplegui.KEY_MAP['up']:
my_ship.set_thrust(False)
# mouseclick handlers that reset UI and conditions whether splash image is drawn
def click(pos):
global started, time, score, lives
center = [WIDTH / 2, HEIGHT / 2]
size = splash_info.get_size()
inwidth = (center[0] - size[0] / 2) < pos[0] < (center[0] + size[0] / 2)
inheight = (center[1] - size[1] / 2) < pos[1] < (center[1] + size[1] / 2)
if (not started) and inwidth and inheight:
started = True
time = 0
score = 0
lives = 3
soundtrack.rewind()
soundtrack.play()
def draw(canvas):
global time, started, rock_group, missile_group, lives, score, explosion_group
# animiate background
time += 1
wtime = (time / 4) % WIDTH
center = debris_info.get_center()
size = debris_info.get_size()
canvas.draw_image(nebula_image, nebula_info.get_center(), nebula_info.get_size(), [WIDTH / 2, HEIGHT / 2], [WIDTH, HEIGHT])
canvas.draw_image(debris_image, center, size, (wtime - WIDTH / 2, HEIGHT / 2), (WIDTH, HEIGHT))
canvas.draw_image(debris_image, center, size, (wtime + WIDTH / 2, HEIGHT / 2), (WIDTH, HEIGHT))
# draw UI
canvas.draw_text("Lives", [50, 50], 22, "White")
canvas.draw_text("Score", [680, 50], 22, "White")
canvas.draw_text(str(lives), [50, 80], 22, "White")
canvas.draw_text(str(score), [680, 80], 22, "White")
# draw ship and sprites
my_ship.draw(canvas)
# update ship and sprites
my_ship.update()
# collision between rocks and ship
if group_collide(rock_group, my_ship):
lives -= 1
if lives <= 0:
started = False
rock_group = set()
# collision between missile and rock
score += group_group_collide(missile_group, rock_group)
# draw and update rocks and missile in group
process_sprite_group(canvas, rock_group)
process_sprite_group(canvas, missile_group)
process_sprite_group(canvas, explosion_group)
# draw splash screen if not started
if not started:
canvas.draw_image(splash_image, splash_info.get_center(),
splash_info.get_size(), [WIDTH / 2, HEIGHT / 2],
splash_info.get_size())
# timer handler that spawns a rock
def rock_spawner():
global rock_group, ROCK_NUMBER, started, score
rock_pos = [random.randrange(0, WIDTH), random.randrange(0, HEIGHT)]
rock_vel = [(random.random() * .6 - .3)*score, (random.random() * .6 - .3)*score]
rock_avel = random.random() * .2 - .1
a_rock = Sprite(rock_pos, rock_vel, 0, rock_avel, asteroid_image, asteroid_info)
dis = dist(my_ship.get_position(), a_rock.get_position())
far_to_ship = dis > 2 * (my_ship.get_radius() + a_rock.get_radius())
if len(rock_group) <= ROCK_NUMBER and started and far_to_ship:
rock_group.add(a_rock)
# initialize stuff
rock_group = set()
missile_group = set()
frame = simplegui.create_frame("Asteroids", WIDTH, HEIGHT)
# initialize ship and two sprites
my_ship = Ship([WIDTH / 2, HEIGHT / 2], [0, 0], 0, ship_image, ship_info)
a_rock = Sprite([WIDTH / 3, HEIGHT / 3], [1, 1], 0, .1, asteroid_image, asteroid_info)
a_missile = Sprite([2 * WIDTH / 3, 2 * HEIGHT / 3], [-1,1], 0, 0, missile_image, missile_info, missile_sound)
# register handlers
frame.set_keyup_handler(keyup)
frame.set_keydown_handler(keydown)
frame.set_mouseclick_handler(click)
frame.set_draw_handler(draw)
timer = simplegui.create_timer(1000.0, rock_spawner)
# get things rolling
timer.start()
frame.start()

Review Your Peers: RiceRocks

Post-class

Beyond CodeSkulptor15 min

https://www.python.org/

http://wiki.python.org/moin/UsefulModules#GUI
http://wiki.python.org/moin/PythonGameLibraries

Class Wrap-up4 min

https://www.coursetalk.com/providers/coursera/courses/an-introduction-to-interactive-programming-in-python/write-review

https://www.class-central.com/review/new/408

##

Learn the basics of object-oriented programming in Python using classes, work with tiled images

Principles of Computing (Part 1)

Lecture slides can be found [here]
Coursera can be found here

About this course: This two-part course builds upon the programming skills that you learned in our Introduction to Interactive Programming in Python course. We will augment those skills with both important programming practices and critical mathematical problem solving skills. These skills underlie larger scale computational problem solving and programming. The main focus of the class will be programming weekly mini-projects in Python that build upon the mathematical and programming principles that are taught in the class. To keep the class fun and engaging, many of the projects will involve working with strategy-based games.

In part 1 of this course, the programming aspect of the class will focus on coding standards and testing. The mathematical portion of the class will focus on probability, combinatorics, and counting with an eye towards practical applications of these concepts in Computer Science.

Recommended Background - Students should be comfortable writing small (100+ line) programs in Python using constructs such as lists, dictionaries and classes and also have a high-school math background that includes algebra and pre-calculus.

#

Lecture slides can be found [here]
Coursera can be found here


primary

#

Lecture slides can be found [here]
Coursera can be found here


primary

#

Lecture slides can be found [here]
Coursera can be found here


primary