Homework 6
Last updated: Tue, 15 Oct 2024 15:03:32 -0400
Out: Mon Oct 07, 2024, 12pm (noon) EST
Due: Mon Oct 21, 2024, 12pm (noon) EST
Overview
This assignment continues to explore programming according to the The Design Recipe, in particular with lists and list functions.
This hw will be graded accordingly:
correctness (9 pts)
design recipe (16 pts)
style (9 pts)
README (1 pt)
Setup
Create a new repository for this assignment by going to the CS450 Fall 2024 GitHub Organization and clicking "New".
Note: The CS450 Fall 2024 GitHub Organization must be the owner of the repository. Do not create the repository in your own account.
Name the repository hw<X>-<LASTNAME>-<FIRSTNAME> where <X> is the current homework number.
For example, I would name my hw6 repository hw6-Chang-Stephen.
Mark the repository as Private.
Check "Add a README file".
Select the Racket template for the .gitignore.
Choose whatever you wish for the license.
When done click "Create repository".
Tasks
Reading
Read Chapter 16-17 of the Textbook (where reading means working through the examples and exercises interactively).
Review the The Design Recipe section of the course website (topics that will be covered in future lectures are marked as such).
Notes and Reminders
All code you write must now follow the The Design Recipe. (Just submitting code is no longer sufficient.)
Signatures should use define/contract and the predicates defined in the Data Design Recipe step. UPDATE: You may need the listof contract constructor for this assignment.
For Examples and Tests, do not use check-expect from the Beginning Student Language (even though the textbook says to). Instead, use check-equal? or other testing forms from rackunit.
Examples for a function definition should come right after the define. But Tests should be put into the test-suite in tests.rkt. Try to think about corner cases and code coverage.
Also, remember that Racket Style and The Design Recipe reserves certain language features only for specific scenarios. For example, set! and other "imperative" features are not allowed ever. Conditionals such as cond should only be used with enumeration or itemization Data Definitions.
The submitted program must be only a series of defines (both constants and function definitions are allowed) and tests/examples. Do not run any other code, i.e., do not automatically start big-bang! Not following this this will result in GradeScope errors and point deductions.
You may look at prior code and examples to help you but BE CAREFUL. A "COPY-AND-MODIFY" PROGRAMMING STRATEGY WILL NOT WORK IN THIS COURSE (nor in the real world). Your program will be wrong (partially because most of the design recipe steps will be wrong) and will receive a low score. Instead, you should write the code for this homework from scratch using The Design Recipe.
Programming
In this assignment you will combine the functions you wrote in Homework 4 and Homework 5 into a playable "Guitar Hero"-like big-bang interactive program, which includes keyboard interaction and scoring.
Here is an online demo that approximates what the program might look like.
The main code should go in a file named hw6.rkt and tests should go in a tests.rkt file of the appropriate format.
In this assignment, each function should have at minimum of one (meaningful) Example and two Tests (that are not the same as the example).
As with any big-bang program, you will first need to design a WorldState data definition whose instances represents a snapshot of the current game state. It should contain the current visible Notes (which includes their positions and NoteState) and the current "Score", which is the number of "misses" allowed before the game ends. As described below, the game should end when the player has 10 misses.
- You will also need to design and implement the following big-bang functions:
render : used with big-bang to-draw clause.
Takes an instance of WorldState and draws the current Notes into the scene. An empty scene (represented with an EMPTY-SCENE constant) should:be 400 pixels wide and 400 pixels tall,
have a vertical gray line in the middle
have a horizontal gray line at y coordinate TARGET-Y
have a "target" that is a black outline circle the same size as a Note (you may find it useful to define a constant called TARGET-NOTE that is a Note to represent the target), and is centered at where the two lines meet.
The Note images should be drawn according to make-Note-image from Homework 4 centered on the middle line at their respective y-coordinates.
NOTE: This function (like all functions) must only process one kind of data (e.g., a KeyEvent, or a WorldState, or a Note, etc). See the lecture notes or textbook for many examples. Functions that try to process multiple kinds of data at once will not be accepted.
You might find the functions you defined in Homework 4 and Homework 5 useful here, e.g., place-Notes-in-scene and place-Note-in-scene.
key-handler : used with big-bang on-key clause. This function should only react to a space press. When this happens, any Notes overlapping with the target should have their NoteState updated to HIT. On any other key, nothing should happen.
NOTE: This function (like all functions) must only process one kind of data (e.g., a KeyEvent, or a WorldState, or a Note, etc). So you will likely need to define one or more helper functions. See the lecture notes or textbook for many examples. Functions that try to process multiple kinds of data at once will not be accepted.
next-WorldState : used with big-bang on-tick clause.
This function should:- update the position of each Note according to its velocity, and update its NoteState if necessary. In Homework 4 you started to write a function that does this, but you will need to change it to modify the NoteState, which should be updated as follows:
Notes that go out of the scene become OUTOFSCENE (with exceptions below)
Notes that are still in scene but past the target become MISSED (with exceptions below)
Notes that are HIT cannot become MISSED but can go OUTOFSCENE
Notes that are MISSED should not go OUTOFSCENE (because we need them to know when the game ends)
remove Notes that are OUTOFSCENE from the WorldState (do you already have a function that does this?)
insert a new PENDING Note at NOTE-INIT-Y with velocity NOTE-VELOCITY with 1-in-100 probability,
somehow keep track of the "Score", which is the number of misses remaining (maximum 10). A misses-remaining function should take a WorldState and return the number of misses remaining before the game ends (see below for how to end the game)
To help with testing, your should also write a num-Notes function that computes the number of Notes in the WorldState. Again, keep in mind that this (and every) function should only process one kind of data. So you will likely need to define multiple helper functions. Do not try to do everything with one function.- functions to be used with big-bang stop-when clause. This will detect and stop the game when appropriate.
game-over? : consumes a WorldState and returns true if there are ten or more MISSED Notes in the world.
render-last : consumes a WorldState and calls render and adds the text "Game Over" on top of that result.
If you follow the design recipe and have properly structured code—
one function does one task with only one kind of data— then this assignment will be easy. If you try to just "get the code working" or employ other unprincipled programming habits, then it will be more difficult to complete the assignment. As a reminder, here are some of the constants you should define and provide the following:
Constants
SCENE-HEIGHT = 400
SCENE-WIDTH = 400
SCENE-CENTER-X = 200
NOTE-RADIUS = 20
NOTE-INIT-Y = 0
NOTE-VELOCITY = 4
TARGET-Y = 320
INIT-WORLDSTATE
EMPTY-SCENE
PENDING
HIT
MISSED
OUTOFSCENE
Before Submitting
Testing
Do not submit until all code has been thoroughly tested (by you).
Assignments may or may not use a GradeScope Autograder, but either way, an Autograder is not a software development tool so do not use it as one. Code must be tested independent of any Autograder.
If you submit and get an Autograder error, this means the code you wrote is not complete and/or not correct and it’s up to you to figure out why.
Of course, the course staff is here and eager to help, but cannot do so if a student does not explain what they’ve tried first (e.g., "why is the Autograder giving an error?" is not something we can help with). At the very least you should report what error you are seeing and which part of the error message you do not understand.
The Autograder test suite is subject to change. This means that the visible grade seen during submission is not the final grade.
Style
All code should follow proper Racket Style.
Also, the repository itself must follow proper style. Specifically, it must have appropriate commit messages. See How to Write a Git Commit Message if you are unsure how to write a commit message.
Files
A submission must have the following files in the repository root:
hw6.rkt: Contains the hw solution code.
All defines should use the name specified in the exercise (ask if you are unsure) and should be provided.
The easiest (but not always the most readable) way to ensure all necessary definitions are provided is to (initially) put as the second line in the file:
This automatically provides all definitions in the file. (The first line should be #lang racket)
tests.rkt: This file should require hw6.rkt and define tests for it.
Specifically, it should define a rackunit test-suite which contains sufficient rackunit test cases (e.g., check-equal?, etc.) for each defined function.
README.md: Contains the required README information, including the GitHub repo url.
Submitting
When you are done, submit your work to Gradescope hw6. You must use the "GitHub" Submission Method and select your hw<X>-<LASTNAME>-<FIRSTNAME> repository.
Note that this is the only acceptable way to submit homework in this course. (Do not manually upload files and do not email files to the course staff. Homework submitted via any unapproved methods will not be graded.)