home—lectures—recipe—exams—hws—D2L—breeze (snow day)
Galaxians II: list-processing
Part A: Problems 1,2 due Nov.02 (Fri) noon, on D2L.
Part B: The remainder due Nov.05 23:59 on D2L, and hardcopy of both Parts.
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.)
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.
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&ndash3; suffice.
Unless otherwise indicated, 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 (unless you write it yourself)
- Functions with a “!”, such as set! and set-rest!.
- (5pts)
Write the function count-bigs : real, list-of-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.)
hint: 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 “threshold” and “nums”):
if we call count-bigs with the particular inputs
(count-bigs 3 (cons 10 (cons 2 (cons 5 empty)))), what is…
- threshold =
- 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!
- (5pts)
Write the racket function map-sqr : list-of-number → list-of-number,
which squares each number in a list;
do not call map (or, my-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 solution.
Any changes you make (e.g. updating the world examples to have a list-of-aliens)
will be moved below the dividing line.
Please include part A (problems 1,2) in your part B hardcopy.
Right now, you can go ahead and move
all the world definitions,
examples, and functions below the dividing-line,
since we'll be updating world to include a list-of-aliens.
- Worlds:
(2pts)
Define a “world” structure which contains
a cannonplayer, one bulletmissile, and (for now)
exactly one alien.
As usual for our data-definitions,
make examples of the data (at least two), and a template.
- Give a template for a world-processing functions.
- (3pts)
Write the function update-world : world → world
which returns a new world one “tick” later.
For the time being, you can have update-world simply move
the world's alien to the right.
Ultimately, this function will decide whether the alien(s) should
be moving to the left or to the right (or, down) --
and to do that, we'll need to keep some further info (where?) which
tracks which direction they're currently moving in.
(And if you want to start implementing this now, that's totally fine —
it'll save you time on the next homework, where we finish the game.)
For now, you don't need test cases that involve the bulletmissile colliding
with anything — you can just have the bulletmissile far away from
any aliens or cannonplayers.
- (2pts)
Write the function world-handle-key : world, keypress → world
which returns a new world updated to handle the keypress.
(Should be easy -- mostly defers to
cannonplayer-handle-key,
and your test cases will largely crib from that.)
- Drawing functions:
- (2pts)
Write the function draw-alien : alien, image -> image,
which takes an alien and a background image,
and returns that background image with an alien drawn on top of it.
hint: place-image is a handy function;
it is similar to overlay/xy
except that it crops the result to the background.
hint: For test-cases, include drawing an alien that is:
(a) in the middle of a small image;
and
(b) one that is mostly off the left-edge but has just a few pixels showing.
Note: Here's an image you can (modify to) use in your test-cases,
in addition to a solid rectangle or whatever else you might choose:
house-with-flowers.rkt.
If you place this file in the same directory as other functions,
you can just (require "house-with-flowers.rkt"),
and then use its exported id (house-with-flowers, coincidentally).
You don't need to print this file, but do submit it on D2L so that I can run your program.
- (2pts)
Write the similar function
draw-player : player, image → image
- (0pts)
Write the function draw-world : world -> image,
which (for the moment) draws the alien and player (only) onto a blank background.
You may not call list, nor place-images.
hint: Call
draw-alien
with an empty-scene for the background;
call draw-player passing it the result of draw-alien
as the second argument.
- (1pt)
Write the function draw-
bulletmissile : bulletmissile, image -> image.
- (3pts)
Change your draw-world so that it incorporates drawing the
bulletmissile as well.
(You don't need to include your previous part (c);
you can update the code and test-cases directly.
Part (c.) was just so that you'd understand how to combine the drawing of two things,
before you try drawing three.)
- (5pts)
List-of-aliens:
- Give the data-definition for list-of-alien.
- Give at least 4 example values of this type.
Your last example should contain at least six aliens (not all in the same row,
nor all in the same column);
you may use this as the aliens in your game's initial world.
- Write the template for any alien-processing function.
- (5pts)
Write draw-aliens : list-of-alien, image → image,
similar to the draw-* functions from ../hw05/hw05.html.
(One test case will suffice; write it before you write the code, to make your life easier.)
hint: When creating the expected-output for you test case, feel free to call draw-alien.
This will help remind you how we drew multiple items onto a single image,
back in hw05 #4c and #4e.
(5pts)
Modify your world struct so that it includes two more fields:
a list of aliens, rather than just a single alien;
and: is the alien fleet currently marching to the left, or to the right?
(A boolean could capture this, but I recommend using a number — perhaps +1 or -1.
This way, it can immediately generalize to be the fleet's x-velocity.)
You'll need to
make updates to your examples of world-structs,
along with
draw-world,
world-handle-key,
and update-world.
(For now, update-world need only move all the aliens in the fleet's direction;
below we'll overhaul it further to handle the fleet reaching the edge of the screen.)
Verify that all updated test cases still pass, of course.
- (5pts)
Write alien-collide-missile?, which determines whether a alien overlaps with a missile.
It's okay to approximate overlap by only looking at the missile's “bounding box”,
and calling the provided overlap?
see instructions at top of that file; you might just copy that code into your own file..
Have two test cases (this is reasonable, given that you already have overlap? fully tested).
- (5pts)
Write aliens-remaining : list-of-alien, missile → list-of-alien
which returns all aliens in the given list which are not colliding with the given missile.
restriction: Do not use the built-in function remove;
the goal of this assignment is to be able to process the list yourself.
hint: We previously saw that when
an if expression was either adding 1 or not, to some value,
we could reduce it to add-1-or-0, and then factor out
the “some value” from the if.
However, cons doesn't have the equivalent to zero that + has:
there is no way
to say “cons nothingness onto a list, returning the same list”.
So we can't use that same trick.
Add the player firing:
If the player presses the "fire" button,
the world's missile is replaced with a new one
just above the player.
Design discussion:
When playing the game, after a missile hits an alien, there is no missile left in the world.
But our world structure always has a missile field!
How to fix this?
- (The correct solution:)
Make the field be not be a missile, but a union-type: missile-or-false.
Then, all our world-missile-handling function would handle that union type.
(This means making a new data-definition, perhaps updating the functions
which took missiles to handle the new type.
Happily, it's an easy upgrade.)
- (A generalization, also correct:)
allow for a list of missiles (including empty).
Especially if using higher-order functions map and filter,
this ends up being the easiest, shortest, and most powerful solution —
that's how you can tell it's good code!
- (Hack, but acceptable):
Start your initial world with a missile that is already above the screen,
and heading upward.
It will never get drawn, and will happen to not intersect with any aliens.
When the missile intersects with something, the next world's missile is again above the screen.
Similarly, if the missile hits an alien, it should disappear.
(This isn't part of handling a keypress.
Which function should check for this?)
This may involve a helper function,
or you can look up ormap
and use a lambda-expression.
- Write leftmost : list-of-alien → real which returns the leftmost coordinate of
any alien in the list.
If the list is empty, you can return any real.
Similarly, write rightmost
and bottommost.
challenge: Instead of the above twothree functions, write a single one which will handle all cases.
For example, you might have
most : list-of-alien, (alien→real), (real,real→real) → real.
(The third input will either be max or min;
it's up to you to figure out what you might use as the second input.)
Alternately, you can use calls to map and sort.
Now, upgrade your update-world
so that it moves the alien fleet down and reverses direction,
when
the left- or right-most alien is near/at/beyond the edge of the screen.
Use map, and a function like
(λ (a) (move-alien a +1 0)).
language-level: In order to pass a function to map,
you'll need change:
Language » Choose Language… » Intermediate Student.
remember: Feel free to use let*, if you like.
Extra credit:
Add alien-missiles to the world.
I'll leave it to you do decide how to best do this.
Helper functions might include missile-overlaps-aliens?
and missiles-remaining.
Alternately, using
filter and higher-order functions
(and, andmap/ormap)
can significantly simplify this.
But if you have any problems, I recommend
making the functions and their test-cases,
so you can quickly find where the error is.
All the above should have their tests, as well
as signatures and (brief) purpose statements.
Only after all tests pass,
you can check that the following works:
(require 2htdp/universe)
(big-bang some-initial-world
[on-key world-handle-key]
[on-tick update-world]
[stop-when (λ (w) … (bottommost …) …)]
[to-draw draw-world]) |
home—lectures—recipe—exams—hws—D2L—breeze (snow day)
This page licensed CC-BY 4.0 Ian Barland Page last generated | Please mail any suggestions (incl. typos, broken links) to ibarlandradford.edu |
|