CodeSkulptor

The following demos illustrate some of the features of CodeSkulptor, emphasizing the interactive aspects provided by its SimpleGUI module.

Draggable map magnifier
Uses mouse control.
Craps dice game
Uses simple control elements. Prints output to console.
Sprite sheet animation
Tetris prototype
Use left & right arrows to move sideways, up & down arrows to rotate.
Simple music player
Uses buttons and sounds. Note: The sample .ogg sounds are not supported in Safari.
Doodle Jump prototype
Use arrows to move.

These are some exceptional programs made by our students.

Bunny's Big Adventure
Jenna Netland, Rice, Fall 2012
The Adventure of Tom
Derek Peirce, Rice, Fall 2012
Pyman
Lawrence Strickland, Coursera, Fall 2012
Rice Racer
Steve Knock, Coursera, Fall 2012
Star Wars
Steve Knock, Coursera, Fall 2012
Elemental Tower Defence
Scott Reynolds, Coursera, Fall 2012
Psychedelic 1D Cellular Automata
Scott Reynolds, Coursera, Fall 2012
Tile Flood
Sergey Efimov, Coursera, Spring 2013
Game of Life
Jonathon Nixon, Coursera, Spring 2013
Py*bert
Jeff Botts, Coursera, Spring 2013
DDR clone
Emily Wachtel, Coursera, Spring 2013
The Descent
Jiaqi Liu, Rice, Fall 2013
Analog Clock
Kostya Shkryob, Coursera, Fall 2013
Rubik's Cube
Karen Ward & Dennis della Corte, Coursera, Fall 2013
Galaxy Invaders
Igor Petetskih, Coursera, Fall 2013
Pang
Ender Kasim, Coursera, Fall 2013

CodeSkulptor provides the SimpleGUI module for interactive programs. However, SimpleGUI is available only inside CodeSkulptor. Pygame is a commonly-used (but significantly more complex) module for interactive programs in Python. The following resources describe how to port programs from SimpleGUI to Pygame.


From SimpleGUI to Pygame — Kevin Byiers, Coursera, Fall 2012

From SimpleGUI to Pygame (videos) — Julie Stoltz and Andrew Sadavoy, Spring 2013

CodeSkulptor provides the SimpleGUI module for interactive programs. However, SimpleGUI is available only inside CodeSkulptor. tkinter is a commonly-used (but significantly more complex) module for interactive programs in Python. The following resources describe how to port programs from SimpleGUI to tkinter.

Examples of converting SimpleGUI code into tkinter, Bill, Fall 2012 & Spring 2013

Here are some examples of converting code from using SimpleGUI to Python's default GUI, tkinter. I'm not a programmer so don't expect any coding wizardry, but I think these examples will help people looking for a different GUI they can use outside this class. To use these you'll need to go to the CodeSkulptor link and copy the code into a new window in IDLE or another Python environment. I suggest naming them like I did, but that's up to you. These were coded in Python 3.2.3. Python 3 uses the module name tkinter, whereas Python 2 uses the module name Tkinter. Thus, you'll need to edit the module name to run in Python 2. In later examples, I'll show you how to write your code to run in both versions without an edit.

Remember that while the example programs are provided as CodeSkulptor links, they will not run in CodeSkulptor since they use tkinter, not SimpleGUI.

  1. sg_tick_tkinter.py — Converts Scott Rixner's SimpleGUI tick function to use tkinter. More details
  2. sg_tick_tkinter_add_tb.py — Introduces two new tkinter widgets: Frame and Text. More details
  3. sg_calculator_tkinter.py — Demonstrates tkinter widgets Frame, Button, Label, Entry, Text and Scrollbar by converting Joe Warren's calculator example to tkinter. More details
  4. sg_calculator_tkinter_error_check.py — Adds Python error checking for divide-by-zero and for non-numerical input. Student project: Extend the error-checking messages. More details
  5. sg_calculator_tkinter_fonts.py — Adds font support for Buttons and shows Scrollbar layout error. More details
  6. sg_calculator_tkinter_fonts_layout.py — Uses multiple frames to fix the scrollbar problem. More details
  7. sg_welcome.py — Converts the Codeskulptor “Welcome!” home page to tkinter. Introduces the Canvas widget and writing text to the canvas. More details
  8. import_example.py — Explains import library vs. import library as x vs. from library import * and shows a sample error. More details
    1. z_flag_norway_sudan.py — Draws line and polygon shapes to make flags on two Canvas widgets. Runs in both Python 2 and Python 3 without edits. More details
    2. z_flag_maldives.py — Adds more shapes on the Canvas. Introduces drawing arcs, ovals, and circles and getting a closer color match. More details
  9. tk_radiobutton_example.py — Introduces the Radiobutton widget, shown in two modes. This is a very important widget for many forms. More details
  10. tk_graphical_rpsls.py — Converts “Rock-Paper-Scissors-Lizard-Spock” (RPSLS) project to tkinter, with basic graphics. Includes a Scott Rixner mode. More details
  11. tk_gtn.py — Graphical version of “Guess the Number” project. Much better layout of Canvas and Frame (Figured THAT out, finally.) More details
  12. tk_scale_0.py — Per a request from a student, I made a demo of the Scale widget. You can use this in “Guess the Number” to avoid input errors, plus learn another cool graphical interface. More details
  13. tk_list_selection_example_0.py — Demonstrates capturing mouse clicks, per a student request. More details

Understanding basic Python using Pystep

One surprising fact about interactive programming in Python is that moderately sophisticated interactive programs can be constructed using only a very small subset of Python. Before tackling interactive programming, we will focus on learning a small, but useful, subset of Python 2. Our approach to learning Python will be to break this subset of Python into five levels with each level containing some new basic functionality of Python.

To support this learning process, we have created a tutorial program called

Pystep — http://www.codeskulptor.org/#demos-pystep.py.

Pystep supports the five language levels shown below that correspond to increasingly larger subsets of Python. For each language level, Pystep contains multiple examples that illustrate the structure and behavior of the particular language features associated with that level. You will continue to use CodeSkulptor for the development and testing of your Python code. We suggest that you start by reviewing the short summary of the basic features of Pystep and then experiment with the examples below.

Each of these five levels of Python correspond to a half-week of material. In particular, the first 2.5 weeks of An Introduction to Interactive Programming in Python focuses on the following features of Python.

Summary of Pystep features

Selecting the language level and example

Users can select the language level and various examples from that level using the two buttons in the control area on the upper right-hand side. The name of the example is echoed in the message pane above the main coding pane in the middle of the frame. Pystep supports two methods for exploring the structure and behavior of basic Python programs at a particular language level.

Visualizing the structure of the example

Learning to write valid Python programs requires us to understand the structure of Python programs. In particular, Python programs consist of a collection of components such as statements and expressions. To visualize the structure of these components, users can navigate the example programs using the arrow keys. Using the up or down arrow keys selects the preceding or following line, respectively, of the Python program. Using the left or right arrow key selects various components that comprise a particular line of Python code. The selection pane in the lower right-hand portion of the frame contains information about the current selection and other kinds of Python statements or expressions that could be used in place of the current selection.

Evaluating the example program

Pystep includes three buttons on the left-hand side control area that enable the user to evaluate the example Python program in a controlled manner. The “Step” button takes the current Python programs and reduces it to simpler Python program that produces an equivalent result. Although modern implementations of Python (such as CodeSkulptor) do not evaluate programs in this manner due to efficiency considerations, this idea of repeatedly reducing a program to a simpler program has the advantage that it makes understanding the behavior of simple Python programs much easier for novice programmers. The “Unstep” button allows the previous “Step” to be undone, while the third button allows reloading of the current example.

Level 0 — Expressions (Week 0a)

Example: “hello_world”

In Python, a program consists of a sequence of statements. When executing a program, Python executes each statement in the program one after the other (sequentially). Executing different kinds of Python statement causes Python to perform different actions. For language level zero, we only consider one kind of Python statement, the print statement. To begin, load the first example at language level zero, “hello_world”, into Pystep.

print "Hello world"

For level zero, most of our example programs will consist of a single print statement. At this point, we suggest that you experiment with the left and right arrow keys for a moment. Note that when the entire statement is selected (the entire line is red), the selection pane shows that the selected component is a statement whose particular instance is print. Now, pressing the right arrow key selects the expression "Hello world". The selection pane notes that this expression is a “string_value” with a particular instance of "Hello world".

To evaluate this Python statement, next press the “Step” button in the left-hand control area. When evaluating a print statement, Python repeatedly reduces the expression associated with the print to a increasingly simple equivalent expressions until no further simplification is possible. At this point, the expression is a value. In this example, "Hello world" is already a value so pressing the "Step" button causes Python to execute the print statement and print the value "Hello world" in the console of the underlying CodeSkulptor window, just as executing this Python program in CodeSkulptor would. In this example, "Hello world" is a particular type of value known as string. We will return to strings later.

Example: “print_numbers”

As part of this level, we will focus on understanding the most common kind of expressions in Python, arithmetic values or numbers, and the arithmetic expressions built from numbers. In Python, there are two types of numbers, int — corresponding to integers, and float — corresponding to real numbers. The second example “print_nunbers” has expressions of both types.

print 42
print 3.14

Stepping through this example prints out the numbers 4 and 3.14 in the console.

Examples: “print_exp1”, “print_exp2”

As in a calculator, we can construct more interesting arithmetic expressions in Python using arithmetic operators. Pystep includes several examples that illustrate the basic strategy for creating arithmetic expressions in Python. A arithmetic expression is either a number or a binary arithmetic operator applied to two arithmetic sub-expressions. We suggest that you use the left and right arrow keys to select the various arithmetic expressions (and sub-expressions) in these examples and note some of the possible operators in basic Python. These basic arithmetic operations include plus +, minus -, times *, division /, power **, integer division // and remainder %. The minus operator - can also be unary (i.e., take one argument), but we'll just represent that operation in binary form as multiplication by -1 for now. The functions int and float convert other kinds of data (such as strings) into ints and floats.

Python computes the value of arithmetic expression by repeatedly reducing the expression to a simpler expression until the expression is number. Python selects an arithmetic operator whose associated arithmetic expressions are numbers and then applies the operator to the numbers to compute the numerical value of the expression. When choosing between several options for which expression to evaluate, Python typically choose the leftmost unevaluated expression. We suggest that you experiment with “Step” and “Unstep” on these examples to better understand this process of evaluation for arithmetic examples.

Examples: “my_name_is”, “convert_to_numbers”, “my_number_is”, “print_winner”

To conclude, we return to examples with strings. The string "hello_world" is a value since Python cannot simplify this expression further. However, we can also construct string expressions using string operations in manners similar to that for arithmetic expressions. For example, string concatenation + takes two strings and joins them to form a single string. The example “my_name_is” illustrates this concept. The operator str converts other types of data such a number into a string in the example “convert_to_numbers”. The example “my_number_is” combines this concept with string concatenation to do some simple string processing. The final example “print_winner” uses multiple print statements to generate several lines of output to the console.

Level 1 — Variables and assignments (Week 0b)

Example: “my_name_is_variable”

Using only print statements, we can't form interesting computations. In Python, the assignment statement allows us to attach the value of an expression to a variable for later use in subsequent expressions. This statement will expand the range of possible Python programs to a much more interesting set of programs. To begin, consider the example “my_name_is_variable” at language level one.

# An assignment statement using a string
name = "Joe"
print "My name is", name

You can use the left and right arrows key to explore the structure of the assignment statement. Executing the assignment statement via “Step” causes the variable name to take on the value "Joe". Pystep visualizes this definition in the variable pane where the variable namecode> is shown as having the value "Joe" of type string. Now, when an expression using a variable is encountered during subsequent evaluation, Python looks up the value of the variable and substitutes that value in place of the variable. The expression is then evaluated as usual. In the example, the instance of name in the print statement is replaced by its value "Joe" during one step of evaluation.

Examples: “fahrenheit_to_celsius”, “circle_area”, “triangle_area”

More generally, the right-hand side of an assignment statement can be an expression. Python evaluates the assignment statement by first evaluating its associated right-hand-side expression and then storing its value in the variable on the left-hand side. The third line in the next example “fahrenheit_to_celsius” illustrates this case when the right-hand side of an assignment statement contains a complex expression. Note that Pystep repeatedly reduces this expression to a simpler equivalent expression before assigning the resulting value to the variable celsius. The remaining examples include multiple variables and multiple assignments used to specify more complicated computations.

As a note, Python variable names consist of alphanumeric character and the underscore "_" character. Variable names must begin with an alphanumeric character. Also, observe that, for statements, the selection pane now has three instances, print, comment and assignment. Technically, comments are not statements in Python. (During stepping, Pystepem> ignores comments.) However, we have included them here for convenience to better illustrate the structure of a Python program.

Level 2 — Functions (Week 1a)

Example: “double”

In several of the previous examples such as “fahrenheit_to_celsius”, we constructed a chunk of Python code that performed some useful computation that we might wish to carry out multiple times. Instead of copying the code, the standard solution in modern computing is to define a function that carries out the action of the code. For the “fahrenheit_to_celsius” example, this function would take fahrenheit as input and then compute and return the corresponding Celsius temperature. Here is a simple example of a function double defined via a function definition statement of the form

def double(x):
    return 2 * x

The indented statement in this example is the body of the function. (In general, the body of a Python function is a sequence of indented statements.) The return statement instructs Python that 2 * x is the value returned by the function double. Given this definition, we can call the function double later in the program via an expression of the form double(2). The example "double" illustrates this process.

# A function that doubles a number
def double(x):
    return 2 * x
print double(1 + 1)

The process by which Python evaluates a function call is fairly straightforward, but has multiple steps. We will use Pystep to illustrate this process visually. In particular, let's step through the program above. The first step of execution defines the function double. Note that the variable pane now has a definition for double of type <funct>. The next step evaluates the right-hand side of the print statement, double(1 + 1). To evaluate the expression double(1 + 1), Python first evaluates its argument 1 + 1 and reduces the expression to double(2).

Next, Python evaluates the function call double(2). This evaluation is by far the most complex process that we have studied up to now. To make this process more transparent, we will explain this process as a transformation into an equivalent Python program involving the body of the function and some extra assignement statements. It is important to note that, in reality, Python does not evaluate a function in this manner. Instead, the following explanation is designed to provide a simple equivlaent mental model for the novice seeking to understand function evaluation.

To visualize the first step of evaluation of the function call double(2), Pystep applies the following transformations to the program:

  • Replace the function call double(2) by a new variable double0,
  • Prepend the body of double to the top of the current program,
  • Create an assignment of the parameter x to the corresponding value 2 from the function call,
  • Prepend this assignment to the top of the current program,
  • Replace the return 2 * x statement by a pair of statements, double0 = 2 * x and return double0.

The resulting program has the following form:

x1 = 2
double0 = 2 * x1
return double0
print double0

You should use “Step” and “Unstep” to move back and forth between the program before the body of double is inserted and after the body of is inserted. Walk through the items above to make sure that you understand the transformation entailed in this single step.

Before proceeding with the evaluation of this program, we note that the subscripted variables introduced into the program are new variables created to store values generated and used in evaluating double. The subscript indicates the call level associated with the variable (the number of function calls pending when the variable was created). Observe that the variable x1 is local to the definition of double since x1 is used purely inside the definition of double. double0 is a temporary variable that stores the value returned by function evaluation for later use at the function call location. This temporary variable has subscript zero to indicate that it exists outside the body of the function call. (Note that double0 is an artifact of our visualization of function evaluation. In actual Python function evaluation, the return value is directly substituted for the function call.)

At this point, evaluation of the program via stepping proceeds as usual. Observe that Pystep has inserted a blue line to separate the code add to the front of the program in response to the function call from the remainder of the code. When Pystep executes a return statement, this statement alerts Python that evaluation of the function is completed and Python then deletes all code up to the blue line. At this point, the variable double0 contains the value returned by the function call and the print statement then prints 4 in the console.

Examples: “fahrenheit_to_kelvin”, “triangle_area_function”

Functions in Python may call other functions leading to a sequence of pending function calls as illustrated during the evaluation of the “fahrenheit_to_kelvin” example. In that example, we have defined two functions: one function f2c that converts temperatures from degrees Fahrenheit to degrees Celsius and a second function f2k that converts from degrees Fahrenheit to Kelvin with the help of f2c. Note that functions may also have more than one parameter such as illustrated in the “triangle_area_function” example.

Example: “print_name”

Besides returning a value, Python functions may also have side effects like printing out a message. In the example, “print_name”, we provide a function that take the string name and prints the string expression "My name is " + name to the console. In this example, the call to the function print_name is both an expression and a statement. Since function calls need not return a value, we use the return statement without a return expression to return from the function call. In this case, Python returns the special value None by default to indicate that no value was returned.

Level 3 — Logic and conditionals (Week 1b)

Example: “True_False”

The programs that we are capable of constructing in our subset of Python are still fairly uninteresting. In particular, the sequence of statements executed by Python does not depend on the actual values used in the computation. In language level three, we will extend the types of data that we consider to include a new binary data type called Booleans. (The corresponding type in Python is bool.) The two Boolean values are True and False. We begin by noting that Python programs can print and assign Boolean values in the same manner as numbers and strings. For example,

print True, False

prints out the Boolean values True and False as expected.

Examples: “boolean_expressions”, “is_positive”

Boolean values can combined using the three Boolean operators and, or and not. The example “boolean_expressions” contains several examples of Boolean expressions. Boolean values can also be created by comparing other types of data. In particular, we will often compare numbers using relational comparisons such as ==, !=, < and >. These operators take two numbers and return a Boolean value. (Relation comparisons also work on strings.) The example “is_positive” defines a simple function that returns True if an input number is positive and False otherwise.

Example: “absolute_value”

The main use of Boolean values is to control the sequence in which Python executes statements. For now, we will focus on three related types of conditional statements: if statements, else statements and elif statements. A sequence of these statements forms a compound statement consisting of an if statement followed by zero or more elif statements followed by an optional else statement. In Python, if statements have the form

if condition:
    body

Note that body of the if statement corresponds to a sequence of indented Python statements (similar to the body of a function definition). You may use the left and right arrow keys to explore the structure of the if statement. To execute an if statement, Python first evaluates the Boolean expression that forms the condition. If the condition evaluates to True, Python executes the body of the if statement. If the condition evaluates to False, the body is ignored. An else statement has the form:

else:
    body

else statements (when needed) always follow either an if statement (or an elif statement). The body of the else statement also consists of a sequence of indented Python statements. The body of the else statement is executed its preceding if statement's condition evaluates to False. The example “absolute_value” illustrates the use of an if and else statement. Note that Pystep first evaluates the condition for the if statements and then replaces the if and else statements by the appropriate body.

Examples: “sign”, “military_time”

In many situations, we wish to select among more than two choices. For this situation, we suggest using one or more elif statements in conjunction with if and else statements. An elif statement has the form:

elif condition:
    body

elif statements always follow either an if statements or another elif statement. If the conditions for the preceding sequence of if/elif statements all evaluate to False, the condition for the elif is evaluated. If the condition evaluates to True, the body of the statement is executed. Otherwise, any following elif and else statements are then executed. The example “sign” uses an if-elif-else sequence to return -1 when an input number is negative, 0 when the number is zero and 1 when the number is positive. The example “military_time” illustrates the use of a longer chain of conditionals to convert military time to twelve-hour time.

Example: “factorial”

The final “factorial” example demonstrates that the combination of functions and conditionals is surprisingly powerful. The factorial function in this example calls itself conditionally based on the value of its input. This idea of a function calling itself is known as recursion. While we won't leverage the power of recursion in this course, recursion is a critical tool in many more advanced computer applications.

Level 4 — Local and global variables (Week 2a)

Example: “circle_area_function”

For language level four, we will broaden the capabilities of Python slightly and consider the kinds of variables that we can use in creating programs. At level one, assignments to variables outside functions generated global variables whose values can be referenced anywhere inside the program, even inside the body of a function. In the example “circle_area_function”, the variable PI references the global version of the variable. (Note the absence of a subscript in Pystep.) Global variables can be referenced before, during and after a functional call.

Example: “cylinder_volume”

At language level two, we observed that the parameters of the function have the property that they are local to the body of the function and can only be accessed/updated inside the function body. In many case, we would like to create other variables that are local to the function to temporarily hold value that are useful in the function. In Python, assignment to a variable inside a Python function creates a local version of the variable. In the example “cylinder_volume”, we observe that the assignment to area creates a new variable with subscript one to indicate that this variable is local to the function. Observe that, as we step through this example, once evaluation of the function is completed, the local definition disappears.

Example: “fahrenheit_to_kelvin2”

One obvious question at this point is: What happens if we try to assign to an existing global variable inside the body of a function? In Python, this assignment creates a new local copy of the variable even if a global version of the variable already exists. In the example “fahrenheit_to_kelvin2”, assignment to the variable c inside the function f2k creates a new local copy of c inside f2k. (Note that this local version has subscript one). The global version of c persists through evaluation of the call to f2k and is referenced later in the final print.

Example: “player_is_ready”

However, in some cases, we would like to modify the value of a global variable inside a Python function. Since, by default, an assignment creates a local variable in a function, placing a global statement in that function instructs Python to treat any assignments to the specified variable(s) in the function as assignments to the global version of the variable. In the example “player_is_ready”, assignment to the variable message inside the function ready does not create a new local variable due to the global statement inside the function. We will make use of global variables inside functions substantially in this class since, early in the class, our primary mechanism for communicating information between the various event handlers controlling interactive program will be global variables. Later in the class, we will introduce object-oriented methods for reducing our reliance on global variables.