home—lectures—recipe—exams—hws—D2L—breeze (snow day)
hw04
continuing pacman
Due Oct.18 (Fri) in class: 1-4, and #10.
Due Oct.21 (Mon) in class: the remainder.
Implement the functions below.
All functions are to be in racket (no Java required).
All steps of the-design-recipe—the design recipe: final version are required:
For each thing you need to represent:
-
a data-definition,
-
examples of the data (at least two, presumably ones that can be used for future tests)
-
a template, for any function which process this type of data.
For each function:
-
tests (at least two for most functions, and at least one for drawing functions),
-
signature and purpose.
-
code (which will naturally include the header, and any necessary data-handling).
The required behaviors of the pacman game are minimal:
We'll require a pacman, 4 ghosts (of different colors),
and ≥4 walls.
Ghosts1
will never collide with walls
(but can end up moving in any of the four directions).
The pacman will move in response to keystrokes, and its mouth
will open and close.
The game ends if the pacman collides with any ghost
or with any wall (if that's even possible in your version).
You do not need to implement:
dots;
powerups;
pacman never colliding with walls and delayed direction-changes.
You don't need 3-way (or more) intersections
(e.g. you might have just one long tunnel that circles
around on itself).
Ghosts can move randomly at intersections, or deterministically.
Of course, you are encouraged to do any of these things;
there will be a small amount of extra credit for doing so.
-
Later problems will have you do the same sort of thing repeatedly:
For a particular type T,
- (2-4pts) Develop a data-representation for a T,
including some examples of the data, and a template for any
function dealing with a ghost.
For fields of a define-struct, be sure to include the type, as well
as a quick description and its units (if applicable).
- (3pts) Develop the function move-T,
which (similar to move-pacman)
takes in a T,
and returns a (new) representation of
that T one tick later.
- (3pts)
Develop the function pacman-collide-T?
which takes in one pacman and one T, and determines if
they overlap.
- (3pts)
Write draw-T, which takes in
a T and an image,
and returns an image of
the T overlayed onto the original image.
- Do Problem#0, with T=ghost.
-
Do Problem#0, with T=wall.
Omit move-wall, of course.
I recommend that your data-representation mesh with
the way rectangles were represented, to make
it convenient to call overlap?.
Walls are lightweight enough that you might
just want to use a fixed list-of-length-four
to represent a wall; that's acceptable.
If you do so:
Suppose the third number in the list-of-length-four represents
the wall's width,
in your representation.
In that case you could certainly use the built-in function
third to
extract the width.
But even better, you can name your own getter:
(define wall-width third).
(You can explain to yourself exactly how this works
in terms of the semantics of define
as discussed in class.)
-
Do Problem#1, but with T=ghosts (that is, a list-of-ghosts).
We say a pacman collides with a (list-of-)ghosts if
if collides with any ghost within the list.
For move-ghosts, do not use the list-of-ghost template:
Instead, use the function map, as discussed in class.
-
Do Problem#0
with T=walls (that is, a list-of-walls).
Omit move-walls, of course.
-
We realize that our move-ghost function is too simplistic:
it doen't account for avoiding walls.
We want not only the function as written, but also a smarter function,
“dance2-ghost”, which moves the ghost while also avoiding walls.
(This will be the function which the final game uses to update a ghost each time-step.)
What inputs does dance-ghost need, to do its job?
I suggest that dance-ghost might work by
calling move-ghost, and then seeing whether
that move was “legal”, by checking for any collisions.
If not, it just returns the ghost unmoved, but with a new direction3.
You are encouraged to use let*.
- [Optional] (4pts)
Write dance-pacman,
which is like move-pacman except that
if the pacman can change direction to the its "next direction",
it will do that.
Optional:
This problem only applies if you have decided to
have pacman-handle-key update
the pacman's "next direction requested"
but not change the current direction.
However, making that change and
it's not that difficult a function to write,
and it turns a game that doesn't feel like pacman into one that does.
We might realize that it'd be nice to have, in addition to move-pacman,
a function move-pacman-in-dir : (which uses the given direction,
ignoring the pacman's current-direction).
This is practically what we already have,
and then move-pacman refactors into a one-line call
to that more-primitive function.
In this homework, we'll say that a “world”
is the representation for an entire game:
— a pacman, all the ghosts, and all the walls.
Including some examples of the data (at least two),
and a template for any function dealing with a world.
(If you want to call it a “game” instead of a “world”,
that's fine too.)
Complete #1 with T=world,
Except that :
-
Let's call it dance-world instead of move-world,
to be consistent with the move/dance terminology.
(This function does not process any user-input.)
- No collision function.
Instead, write world-done?,
which returns whether or not the pacman is colliding with
a ghost or wall4,
or there are no more dots (if implementing dots).
- draw-world
won't take in a pre-existing image;
instead it should just take in a world, and return an image.
It is responsible for creating the initial background and then
overlaying items on top of it.
- Write the function world-handle-key,
which takes a world and a keypress,
and returns a new world.
(This function does not reflect any time-passing though,
so presumably nothing moves.)
- (1pt)
Have your code call big-bang (after your
(require 2htdp/universe)),
providing it
on-tick,
on-draw,
on-key,
and
stop-when
handlers.
-
[Optional...though I am thinking requiring this required.]
Implement dots.
Instead of (or perhaps in addition to) pacman-collide-dots?,
you might want all-uncollided-dots : pacman, dots → dots
which returns all dots which aren't overlapping with the pacman.
(This is a filter function.)
- (3pts) Problem Set #11 (8ed: ??) [which strings are derived from a grammar].
For the strings that are derivable, give a left-most derivation (using “⇒” as in the book).
- baab
- bbbab
- bbaaaaa
- bbaab
Features, Requirements, and Extras
We're looking for a pacman-like game,
but we don't need to implement every feature of the original.
In particular, it's acceptable to punt on the following issues.
-
Your game can behave differently than the game proper,
as long as it's reasonable.
-
Objects can be drawn quite differently from the original.
(Keep it simple at first; you can always make it look fancier later.)
-
No sounds required
(though you are certainly welcome to
call play-sound if you like).
Please, no copyrighted sounds.
If you know of a website that has some free-to-use sounds
(e.g. under a creative commons license),
please post on the discussion boards.
Or, record your own!
-
We don't need to keep track of a score.
Post/ask on discussion boards if you have other questions/suggestions.
The ultimate point of the exercise is to:
- be proficient at list-processing functions
(including maps, filters, and folds, which we'll talk about later);
-
have a solid understanding of how one can write a program functionally,
without ever assigning to a variable;
-
better understand model-view-controller;
-
avoid ghosts.
Opportunities are rife for extra-credit, by adding additional features.
Don't do this until you get the above functionality working, though!
Note that the amount of extra-credit offered will not be too much:
it's more important to complete the regular classwork,
than to skip/not-learn some of the regular topics but do more
pacman-programming.
-
Please put a clear dividing point between code for requirements from previous homeworks,
and any changed/updated code that is required for this assignment.
-
For hardcopy, I prefer if you don't to provide any of the code for previous homeworks.
-
You may use code from the posted solutions,
but (as with all code5 you don't write)
you should cite your source.
1
It perhaps goes without saying:
Ghosts will always be moving
(and will only change directions at intersections/corners).
It should be possible for ghosts and pacman to collide.
↩
2
In retrospect, I realize that instead of calling my original function
“move-ghost”, maybe
“step-ghost” or “advance-ghost”
would have been a better name.
But rather than having people go back and do a change-all on the name,
making it confusing to talk to each other about the project,
we'll just adopt the “dance” naming-scheme.
↩
3
Having dance-ghost sometimes return an unmoved-but-perhaps-turned
ghost is a bit clever.
And cleverness can be something to avoid; it can lead to
misunderstandings/confusions/bugs in the future.
(This particular example isn't too clever
The “right” thing to do might be:
If the ghost can't move in the current direction,
calculate a list of all the directions it can legally move in,
and move in one of those directions.
See the note for dance-pacman, for an easy way to implement this
(especially when combined with filter,
and a list of the-four-possible-directions).
↩4If you know, from the way you
have written your move methods, that a pacman can never ever
collide with a wall, then you don't need to do further computation
to check for check wall-collision.
↩
5Or at the least,
all code except for possibly one-to-two line snippets
that are straightforward. ↩
home—lectures—recipe—exams—hws—D2L—breeze (snow day)