home—lectures—recipe—hws—exams—D2L—zoom (snow day)
list processing
Pac-Man cont.
Part A: Problems 1–6 due
Oct.03 (Thu) at start of class,
on D2L (no hardcopy).
Part B: The remainder due
Oct.08 (Tue)
at start of class; submit all problems (incl. part A)
on D2L, and hardcopy.
Reading: §6.6, and §10.1–10.3.1.
(Additional recommended, but not required, background reading: all of Chpt.6, and §10.3.
Additional, non-required, challenge-reading: § 10.5.)
All problems are to be written in Racket.
Do not call any of the following functions:
- list (except when making test-cases)
- append (unless you write it yourself)
- remove/remove* (unless you write it yourself)
- place-images (plural) (unless you write it yourself); calling place-image (singular) is fine/intended.
- any functions with a “!”, such as set! and set-rest!.
If you want to use let* (as mentioned in class), you certainly may.
Your name and the assignment-number
must be in a comment at the start of the file
All functions/data must include the appropriate steps of the-design-recipe.html.
In particular, test cases alone might be worth 40-50% of the credit for a function.
Have enough test cases to cover different corner cases; often 2–3 can suffice.
- Write the function count-bigs : (-> real? (listof real?) natnum?,
which takes in a threshold and a list of numbers, and returns
how many of them
are larger than the threshold.
To help you out, here are some test cases; no further ones are required.
(The data-definition for list-of-number has already been given in lecture,
so you don't need to repeat steps 1-3 of the design recipe for list-of-number.)
Remember: We can't re-assign to variables, in functional programming.
So we won't have a counter which we increment, like you might in your imperative-programming class.
Instead, be sure to follow the design recipe, and after copying the template,
think about the inventory-with-values
(assuming we call our parameters “thresh” and “nums”):
if we call count-bigs with the particular inputs
(count-bigs 3 (cons 10 (cons 2 (cons 5 empty)))), what is…
- thresh =
- nums =
- (first nums) =
- (rest nums) =
- (count-bigs threshold (rest nums)) =
Fill in each blank with a particular number, or list-of-numbers.
Then, ask yourself: Starting with those pieces of info,
how do I assemble them to get my desired result of 2?
You don't need to include the above in your answer —
it's just to remind you of what you do,
for the “inventory-with-values” step of the design-recipe, #6.
If you get stuck on any of the problems below, make sure you didn't skip this step;
it's the one that can really make things click!
- Write the racket function map-sqr : (-> (listof number?) (listof number?)),
which squares each number in a list;
do not call map .
To help you out, here are some test cases; no further ones are required.
(check-expect (map-sqr empty) empty)
(check-expect (map-sqr (cons 7 empty)) (cons 49 empty))
(check-expect (map-sqr (cons 9 (cons 7 empty))) (cons 81 (cons 49 empty))) |
Copy your hw04(structs) racket file to one that we'll use for this one.
Add a very noticeable dividing-line (say, 80 ;s)
between old code and the new.
You will not need to turn in hardcopy of things before the dividing-line
if they were in your hw04 solution or in the posted hw04-soln.
Please include part A (problems 1–6) in your part B hardcopy.
- For List-of-ghosts,
- Give at least 4 example values of this type.
Your last example should contain at least four ghosts; you may use this as the ghosts
in your game's initial world.
- Write the template for a list-of-ghost processing function.
- Write pacman-collide-ghosts?, which determines whether a single pacman overlaps with any ghost
in a list-of-ghosts.
(Of course, you should call hw04's pacman-collide-ghost? as a helper.)
name-change: In hw04 we actually called it pacman-overlap-ghost?
,
but I decided I prefer collide
.
You can use either collide
or overlap
, as you prefer.
- Write
ghosts-remaining : (-> pacman? (listof ghost?) (listof ghost?)),
which returns all ghosts in the given list which are not
colliding with the pacman.
(Since you are (presumably) not implementing a pacman being powered up,
then you won't actually call this function in your final game, but I am still requiring it.
If you are implementing that feature, then the function should only remove ghosts if the pacman is currently powered-up.)
Remember, do not call built-in functions like remove. Use the list template.
- Drawing:
Write
draw-ghosts,
which takes a list-of-ghosts and a background-image,
and returns the background image with the ghosts overlaid on it.
When creating the expected-output for your test cases, feel
free to include the calls to draw-ghost (singular), etc..
Creating the expected-result for a test for a list-of-length-2 will help you
understand what your code needs to do.
- Similarly, give examples of List-of-walls.
You don't need to give a data-def'n or template (since they are so similar to those for List-of-ghosts), though.
One list should be what you'll use in the game,
and to be interesting should have at least six walls:
Four for the outer-boundary, and at least two interior ones.
That lets us do something at least as interesting as, say:

- Similarly, write
pacman-collide-walls?
and
ghost-collide-walls?.
- Write draw-walls, similar to draw-ghosts.
- Write
move-ghost : (-> ghost? (listof wall?) ghost?),
which is like
glide-ghost
but accounting for walls:
If gliding one step would end up colliding with a wall,
then instead just
ghost-spin (from hw04).
(In this case the ghost need not actually end up moving.).
- Similarly, write
move-pacman : (-> pacman? (listof wall?) pacman?).
- Option 1:
If your pacman struct includes both a current-direction and
a cached direction-keypress,
then:
You should test if moving in the direction of the cached direction will avoid walls;
if so then that will become the new direction.
Otherwise, see if moving in the current direction will avoid walls;
if so it continues moving in that direction.
Otherwise, the pacman should … stop? Move in a random/next direction? It's up to you.
- Option 2:
If your earlier pacman-handle-key had a keypress take effect immediately,
you can still do so.
(This is harder for the player, since there is only a limited time for
them to hit the direction key — as little as one frame, if two
walls are exactly the width of a pacman|!)
In this case, if gliding the pacman would result in colliding with a wall,
the pacman should probably stop (which is different from the original game).
- Worlds:
Define a “world” structure which contains
one pacman, a list of ghosts,
and a list of walls.
As usual for our data-definitions,
make examples of the data (at least two).
- Give a template for world-processing functions.
- Write the function move-world : (-> world? world?)
which returns a new world one tick later, where the pacman and all ghosts have moved.
- Write the function world-handle-key : (-> world? key-event? world?)
which returns a new world updated to handle the keypress.
Will be easy — mostly defers to pacman-handle-key,
and your test cases will largely crib from that.
- Write the function draw-world : (-> world? image?),
which draws the world onto a blank background.
- Optionally: If implementing dots, give functions similar to the above for them.
- Finally, write a function game-over? : (-> world? boolean?),
which returns whether the game is over
(that is, if the pacman is colliding with a ghost, or (optionally) there are no more dots).
All the above should have their tests, as well
as signatures and (brief) purpose statements.
Only after all tests pass,
add
(require 2htdp/universe)
(big-bang some-initial-world
[on-key world-handle-key]
[on-tick update-world]
[to-draw draw-world]
[stop-when game-over?]) |
and you can play your game.
home—lectures—recipe—hws—exams—D2L—zoom (snow day)
 This page licensed CC-BY 4.0 Ian Barland Page last generated | Please mail any suggestions (incl. typos, broken links) to ibarland radford.edu |
 |