RU beehive logo ITEC dept promo banner
ITEC 380
2020spring
ibarland

structs
hw04

Due:
Feb.21 23:59, or (for 10% bonus) Feb.20 (Thu) at the start of class, D2L and hardcopy.
Your submitted file should be named “hw04.rkt”, plus any .java files.

Standard instructions for all homeworks:


Consider the following information, which might be part of a sports-simulation:

A team is:

  1. (5pts) Give a data definition (including examples of the data, and the template for any function which processes a team), as per steps 1-3 of the design recipe. Give at least three examples of a team.

  2. (5pts) We’ll say one team is “greater” than another if its offense is higher than the other’s defense, and its defense is higher than the other’s offense. Write the function team>? to implement this. Follow all the steps of the design recipe1. As always, be sure to think about enough test-cases to cover the interesting situations (half of the pts). (In this case, six or seven should suffice, if they each cover a different situation.)


Familiarize yourself with the arcade game Pac-Man, such as this example. We will write a simplified version which only needs to deal with: the pacman, eating dots, ghosts, and walls. It does not need to deal with: score, having more than one level, number-of-lives, fruit, or ghosts becoming temporarily vulnerable.

For this Homework, you'll submit two files: a .java and .rkt program file.

We start by representing the pacman, and writing a method involving them.
  1. (3pts) In both Java and Racket, develop a data-definition for a pacman. For each field, give a short (two-to-three word) comment describing what it stands for, and its units. Natural units for screen-based games are pixels, and ticks (where a "tick" is an abstract amount of time, but it's conveninent to declare it as the amount of time between two frames).
    hint: To represent directions (or keypresses, or both), use the strings "left", "down", etc.; rather than symbols, and rather than "west", "south", etc. . This will play nicely with the keypress events of the 2htdp/universe library. This will be a union type.
    pro tip: Rather than keep track of both how wide-open the mouth currently is and whether it's opening or closing, I recommend being a little sneaky and just keep the pacman's age. Then if you later need to know how wide the mouth should be, you can take the cosine of the age (or, call any other function2 which maps numbers to [0,1]).3

    Remember to include both field-names and their types, in racket as well as Java.

  2. (3pts) Make at least two different examples of the data; do this both in Java and in racket. (In Java, where all code must be inside a method, put these inside a static method void tests().)
  3. (3pts) Write the template for a pacman-processing function, in both racket and Java.
    (In Java, you'll have to comment out the template, since the ... won't compile.)
  4. (5pts) In both racket and in Java: Write a function that converts a pacman's direction to an x-displacement (dx), and another to compute the y-displacement (dy).4 That is, heading left corresponds to an dx of +1 and a dy of 0, while heading north corresponds to a dx of 0 and a dy of -1. The function should take in just the direction, not an entire pacman.

    (You might have functions direction->dx and direction->dy, or you might have one function that returns both values wrapped in a posn structure / java.awt.Point, or a list-of-length-exactly-two (or array/vector of length 2). Whichever you choose should correspond to how you're representing the pacman's position — as two numbers, or a posn/Point, or a list-of-length-exactly-two.)

  5. (3pts) Create (in both racket and Java), a function glide-pacman which takes in a pacman, and returns a pacman one "tick" of time later, ignoring any exterior factors like walls or ghosts or wrapping around the screen5. The Java and racket versions should work in the same way: returning a new object, rather than mutating any fields (Cf. enbiggen in the lecture notes).

The following problems only need be done in racket.

  1. Give a data-definition for an ghost, a dot, and a wall.
  2. Give a data-definitions for an ghost, a dot, and a wall, each with two examples of the data. Include a template for ghost (but not dot or wall, since we won't actually write functions that deal primarily with lazy, unchanging dots and walls.)
  3. Write glide-ghost similarly to glide-pacman.
  4. (5pts) Drawing functions:
    1. Write the function draw-dot : dot, image -> image, which takes a dotbrick and a “background” image, and returns that background image with the dotbrick 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 a dot that is: (a) near the center 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.
    2. Write draw-ghost, similarly.
    3. Write draw-pacman, similarly. I suggest writing a helper that just generates a pacman-image, ready to be placed on the background. Since we don't need an anatomically-correct pac-man, it's fine if you draw a square for the pac-man, with a small circle inside (growing and shrinking), to represent the mouth. Alternately, you can use the provided arc.rkt:
    4. Write draw-wall and draw-dot similarly.

    I suggest using simple shapes (like mere rectangles) for all your drawing-functions for the game. You are welcome to be much fancier, though it won’t earn you additional credit. You are welcome to use jpg/png/bitmaps, but make sure you have the legal right to copy them — e.g. from sites like classroomclipart.com or libraries like planetcute . Please cite your source, of course!

  5. (5pts) In racket (only), write the function pacman-handle-key, which takes a pacman and a keypress (e.g. "z" or "right"), and returns a new pacman which has responded to that keypress.

    (For now, you can have the keypress take effect immediately, although in our final version we may store the keystroke until the next time the pacman can reaches an intersection.)

  6. (3pts) (racket-only) Write a function draw-world which takes in a pacman and one ghost, and returns an image: that pacman and ghost placed onto a(n otherwise blank) board. Only one test-case is required. (In the future, this function will get upgraded place all game-objects onto a background board.
  7. Finally, write pacman-collide-ghost?. You may download and (require "overlap.rkt") (but you shouldn't need to modify that file).
    Remember, don't copy/paste a .rkt file; right-click to download, and then you can open it in DrRacket if you like.

All the above should have their tests, as well as signatures and (brief) purpose statements. Only after all tests pass, the following should work (in racket):

(require 2htdp/universe)

(big-bang some-initial-pacman
    [on-key  pacman-handle-key]
    [on-tick glide-pacman]
    [to-draw draw-world])


1 Note that the stub-function, step 5e, gets replaced with the real body (step 7), so it won’t be visible in what you submit. Also, you don’t need to include the names of constructors/selectors; that was part of quiz03 but not part of the design recipe.      
2
; sawtooth : integer?, (and/c integer? positive?) -> real?
; Return a number between 0 and 1.
; As x increases, it's a rising-then-falling pattern: /\/\/\/\...
;    with a period of 2 * `period/2`.
;    (bug: this should allow real inputs, not just integer.)
;
(define (sawtooth x period/2)
(/ (abs (- (modulo (- x period/2) (* 2 period/2)) period/2))
period/2))

(check-expect (sawtooth   0 100)   0/100)
(check-expect (sawtooth   1 100)   1/100)
(check-expect (sawtooth   2 100)   2/100)
(check-expect (sawtooth  99 100)  99/100)
(check-expect (sawtooth 100 100) 100/100)
(check-expect (sawtooth 101 100)  99/100)
(check-expect (sawtooth 102 100)  98/100)
(check-expect (sawtooth 199 100)   1/100)
(check-expect (sawtooth 200 100)   0/100)
(check-expect (sawtooth 201 100)   1/100)
(check-expect (sawtooth 300 100) 100/100)
(check-expect (sawtooth 301 100)  99/100)
(check-expect (sawtooth 400 100)   0/100)
(check-expect (sawtooth 401 100)   1/100)
You're welcome. (If you use this code, cite the source URL, of course.)      
3 Keeping track of age is definitely a hack, so that we can collapse two fields to one, but it feels relatively natural. It also suggests that we can use a pacman's age later on (for calculating score, or having the pacman evolve, or …). Hopefully we won't want to, in the future, need to know whether the mouth is waxing or waning; if so we'll end up with uglier and less understandable code than the natural, straightforward two-field represention.      
4 If you are already representing the direction via x- and y-offsets, then instead have a function that translates keypresses into the direction(s).      
5 You are encouraged to allow and test for pacman wrapping around the screen, but it won't be required; we can choose to later create walls which won't allow wrapping around. … On the other hand, it's only a few extra function calls and tests to support this feature.      

logo for creative commons by-attribution license
This page licensed CC-BY 4.0 Ian Barland
Page last generated
Please mail any suggestions
(incl. typos, broken links)
to ibarlandradford.edu
Rendered by Racket.