Problem Set 05
Last updated: Thu, 12 Feb 2015 10:52:49 -0500
OUT: Monday 2/9/2015, 9pm EST
DUE: Monday 2/16/2015, 9pm EST
You must use the Intermediate Student with lambda language to complete this assignment. Select it via the Choose Language... menu located at the bottom-left of the DrRacket window.
Put all your solution files in a directory named set05 in your repository.
Download extras.rkt to this directory (right-click and choose "Save As"; don’t copy and paste) and commit it as well.
Use begin-for-test and rackunit to define your examples and tests.
Don’t forget to tell us how many hours you spent working on the assignment. This should be a global variable called TIME-ON-TASK in each file. For example:
(define TIME-ON-TASK 10.5) ; hours
So each solution file must have at least the following at the top:
|(define TIME-ON-TASK <number-of-hours-you-spent>)|
After you’ve submitted your solution, use a web browser to go to https://github.ccs.neu.edu/
and check that your repository contains the following files:
Alternate Data Definitions: For each problem, describe in prose two alternative data definitions. For each of these alternatives, list pros and cons of how the changes would affect your code. For example, some data definition changes may simplify parts of your program and make other parts more complex. You should also consider how the alternatives affect your program in terms of readability and maintainability. Sometimes a little additional complexity may be worthwhile if makes your code more understandable. These are the tradeoffs you should constantly be considering.
Put these alternative data definitions and writeups at the end of your solution file(s).
Git Commit Requirement: For this assignment, you must have at least three well-labeled git commits (including the final commit). A well-labeled git commit accurately and succinctly describes the changes since the previous commit. Something like "commit2", or "home work 3" is not an acceptable git commit label. Failure to meet this requirement will result in loss of points.
For this assignment, you may use ListOf<X> instead of defining
your own list data definitions.
In this assignment, map, filter, foldr are
your best friends. If you do not understand when and how to use them
properly, you may have a difficult time completing the assignment.
In this assignment, you should also look for opportunities to abstract
similar parts of your program. You may be asked to describe some of your
ideas during your code walk.
1 Balls and Walls
1.1 Additional Preliminaries
Save your solutions for this problem to a file named walls.rkt.
Run the following expression (you must have required extras.rkt
) to check that your file is properly named and is in the proper directory:
(check-location "05" "walls.rkt")
Add these additional provides at the top of your file (below the requires), so that we can test your solution:
1.2 Problem Description
UPDATE 2015-02-12: The names of some requested functions have changed.
Please check that your provides match the current
Implement a game similar to the classic JezzBall
to get an approximate
idea of the
Implement your game using 2htdp/image
. As usual, you must implement the standard
functions required by big-bang, including a World
and an INITIAL-WORLD
constant. Use the following run
function to initiate your game (though you don’t need to
The game consists of some number of balls bouncing around a
400 x 400 canvas. The balls have a constant horizontal and
vertical velocity between 1 pixel/tick and 10 pixels/tick
(inclusive), except when close to a wall.
If a tick would put any part of a ball past a canvas wall, then instead
the ball moves just enough to be flush against that wall,
like in previous assignments and examples. That axis
of the ball’s velocity then changes direction to the opposite direction.
A ball does not lose velocity when bouncing, so the magnitude
of a ball’s velocity never changes, only the direction.
Balls do not interact with each other, so it’s possible for balls to
A ball has a radius of 20 pixels and is rendered as a solid blue
Implement and provide the following functions:
|; get-balls : World -> ListOf<Ball>|
|; Returns all the balls in the given world.|
|; mk-ball : Coordinate Coordinate Real Real -> Ball|
|; Returns a Ball with center at (x,y), with the given velocities.|
|; A positive x velocity is in the x-increasing direction and vice versa.|
|; The y velocity is similar.|
|(define (mk-ball x y vx vy) ...)|
|; replace-balls : World ListOf<Ball> -> World|
|; Replaces the Balls in the given World with the given Balls.|
|; get-ball-x : Ball -> Coordinate|
|; Returns the x position of the Ball's center.|
|; get-ball-y : Ball -> Coordiate|
|; Returns the y position of the Ball's center.|
The game player may insert new walls into the canvas by left-clicking
the mouse (i.e., "button-down").
All walls have a major and minor axis.
For a vertical wall, the y-axis is the major axis
and the x-axis is the minor axis.
For a horizontal wall, the major and minor axes are
the opposite that of a vertical wall.
A wall starts with a length of 2 pixels along its major axis.
A wall typically grows by 16 pixels/tick along its major axis. If
either end of the wall’s major axis hits the canvas edge or another
perpendicular wall, it should stop growing. However, if one end hits a
wall, but the other does not, then the unobstructed end should continue
to grow, at 8 pixels/tick. On a tick, if any end of a wall’s
major axis would exceed a perpendicular wall or canvas edge,
then that end grows by just enough to be flush against the closest
wall or edge.
When both ends of a wall’s major axis hit other walls, that wall is
no longer active (i.e., it stops growing). There may be
at most one active wall on the canvas at any time.
If a ball hits an active wall, the game is over. Otherwise, a ball
should bounce off inserted walls the same way it bounces off the
To simplify your computations:
However, render a wall as solid brown rectangle,
with a minor axis width of 4 pixels.
A wall may only be inserted into a section of the canvas where balls can
reach. When a section of the canvas becomes unreachable, it should be
colored yellow. (You may leave the walls rendered in the unreachable
parts of the canvas. Don’t worry about connecting unreachable
sections of the canvas into one contiguous yellow polygon, as in the
sample game linked above.
When the game begins, a click inserts a vertical wall. Pressing the
space bar switches to inserting horizontal walls. The game should
display text to indicate which orientation wall would be inserted on
the next click.
1.2.3 Scoring and Leveling
A game’s score is determined by the percentage area of the
blocked off sections of the canvas, in other words,
the percentage of the canvas unreachable by any ball.
The areas is are pixels.
To compute the score, first compute this percentage,
multiply by 100, and the use round
to get an integer score.
|; score : World -> Natural|
|; Returns the current score.|
|; level : World -> Natural|
|; Returns the current level.|
A game begins with no walls and one ball at level 1. The ball should
have a randomly generated position completely within the canvas
(flush against a canvas edge is considered completely within the canvas)
x and y velocities between 1 and
10 pixels/tick (inclusive). Since the ball can reach
all parts of the canvas, the initial score is 0.
A player then tries
to insert walls to increase the score. If the score reaches or exceeds the
goal score for the level, the game advances to the next level.
Each new level should start with no walls and a number of randomly
generated balls equal to the level number.
A goal score is computed as 50 plus five times the level number. The goal score
should not exceed 90.
The game should display the current level, score, and goal score at all times.
As mentioned previously, the game ends when a ball collides with an
active wall. The game should display GAME OVER when the game is over.
Here are some gameplay scenes.