Lab 3 Structured Data
Purpose: The purpose of this lab is to practice designing and programming with custom structures.
Textbook references: Chapter 3: How to Design Programs Chapter 5: Adding Structure
Custom Structures
Consider the following data definitions:
(define-struct address [num st city us-state zip]) ; An Address is a (make-address Nat String String String Nat) ; - where num is the number of the building on the street ; - st is the name of the street ; - city is the city the building is in ; - us-state is the state the city is in ; - and zip is the zipcode of the building (define-struct student [first last nuid local perm]) ; An NEUStudent is a ; (make-student String String PositiveNumber Address Address) ; - where first is the student's first name ; - last is the student's last name ; - nuid is the student's NUID # ; - local is the student's local address ; - and perm is the student's permanent address
Exercise 1 Complete the data design recipe for the above data definitions.
Exercise 2 Design the function student-email which takes an NEUStudent and produces a string representing that student’s email address. For simplicity we will say that a student’s email address is always their last name (all lowercase), followed by a period, followed by the first initial of their first name (also lowercase), and finished with "@husky.neu.edu".
Exercise 3 Design the function update-zipcode which takes an NEUStudent and a number, representing the new zip code of the person and updates their permanent address to have that zip code. Be sure to follow the template!
The Apocalypse
In today’s lab we will work on designing a little game where you are being attacked by a zombie. The program takes as input the initial position of the player (and no other information). It displays the player at that location, the zombie at a random location on the screen, and the score in the top left corner (initially zero). Then, every time the clock ticks the zombie will move towards the player and the score will increase by 1. The player can try to escape the zombie by moving using the arrow keys on the keyboard. The game ends when the player is eaten by the zombie and the program displays the player’s final score in the center of the screen so they know how they did.
As usual we will follow the steps for designing a world program. Recall that these steps break with our usual convention of top down programming because the larger program is at the bottom instead of at the top. However, you should continue to design your individual functions using top down programming as much as possible.
Step 1: What stays the same?
Exercise 4 Define some constants to describe what stays the same throughout the game. What images might you need to draw? Keep in mind that this is not an art class so you can just use circles to represent the player and the zombie, or copy pictures from the internet. What other information is always the same (e.g. the speed of the zombie)?
Step 2: What changes?
Exercise 5 Design a data definition for the world state. Remember that you need to be able to display the player, the zombie, and the score. Since you are keeping track of a location for both the player and the zombie it would be a good idea to use the same kind of data for both. Which type of data have we used to represent positions? Remember to follow all the steps of the data design recipe.
Step 3: Which handlers do we need?
Exercise 6 Write the signature and purpose statements for the handler functions you will need. Recall that big-bang always requires a to-draw clause. Which other clauses will you need based on the program description? If you are having trouble take a look at the documentation, and if you are still confused, ask a tutor or TA for assistance.
Step 4: Design your handlers
Exercise 7 Design the function for your to-draw clause. Recall that you need to draw the player, the zombie, and the score in the top left corner. The function overlay/align will be helpful to you here.
Exercise 8 Design the function that changes the world over time. There are two things that change over time: the position of the zombie and the score of the player. To help you design this function we have included below some code that moves one position towards another position at a given speed:
; move-towards : Posn Posn Number -> Posn ; Move position 1 towards position 2 at speed (check-expect (move-towards (make-posn 0 0) (make-posn 8 6) 5) (make-posn 4 3)) (check-expect (move-towards (make-posn 1 2) (make-posn 1 2) 1) (make-posn 1 2)) (define (move-towards p1 p2 speed) (if (< (distance p1 p2) speed) p2 (make-posn (+ (posn-x p1) (/ (* (- (posn-x p2) (posn-x p1)) speed) (distance p1 p2))) (+ (posn-y p1) (/ (* (- (posn-y p2) (posn-y p1)) speed) (distance p1 p2)))))) ; distance : Posn Posn -> Number ; Produces the distance between the two positions (check-expect (distance (make-posn 0 0) (make-posn 8 6)) 10) (check-expect (distance (make-posn 1 2) (make-posn 1 2)) 0) (define (distance p1 p2) (inexact->exact (sqrt (+ (sqr (- (posn-x p1) (posn-x p2))) (sqr (- (posn-y p1) (posn-y p2)))))))
Exercise 9 Design the function that changes the world when a key is pressed. When the player presses an arrow key you want to shift their position a bit in that direction. You can decide how fast the player is. The faster they are, the easier the game will be. Remember that if the player presses a non-arrow key, you don’t want to change the world, but you don’t want your program to break either!
Exercise 10 Design the function that checks whether the game is over. The game is over when the player has been eaten by the zombie. That is, when the position of the player and the position of the zombie are the same.
Exercise 11 Design the function that displays the losing screen and the player’s score when the game is over. Check the documentation for stop-when to see how you can use this function in big-bang
Step 5: Put it all together!
Exercise 12 Design the function zombie-game which takes as input the initial position of the player and runs your program. Give it a try! What’s your high score?
Before You Go...
If you had trouble finishing any of the exercises in the lab or homework, or just feel like you’re struggling with any of the class material, please feel free to come to office hours and talk to a TA or tutor for additional assistance.
Stretch Goals: Fighting Back
Update your world program so that you can fight back against the zombie. You can shoot a single bullet at the zombie but only if you don’t already have a bullet flying around. If you successfully shoot the zombie you win the game but if it eats you first, you lose.
Exercise 13 Update your data definitions to account for this new information. What sorts of things do we need to keep track of now that we didn’t before? How can we represent these things? Be sure to update all the steps of the data design recipe.
Exercise 14 Update any functions that take in this new data. This is called re-factoring your code. Note that you don’t have to update any functions that are still taking in the same data definition. This is a very important thing to remember about re-factoring. Don’t throw away code if you can re-use it!