Homework 7
Last updated: Tue, 25 Mar 2025 09:06:16 -0400
Out: Tue Mar 25 2025, 11am EST
Due: Tue Apr 01 2025, 11am EST
Overview
This assignment focuses on a very common kind of data definition, an itemization of compound data.
This hw will be graded accordingly:
correctness (autograder) (10 pts)
design recipe (24 pts)
testing (20 pts)
style (8 pts)
README (2 pt)
Setup
Create a new repository for this assignment by going to the CS450 Spring 2025 GitHub Organization and clicking "New".
Note: The CS450 Spring 2025 GitHub Organization must be the owner of the repository. Do not create the repository in your own account.
On the "Create a new repository" screen:
Name the repository hw<X>-<LASTNAME>-<FIRSTNAME> where <X> is the current homework number.
For example, I would name my hw7 repository hw7-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
This assignment focuses on writing programs that deal with a very
common kind of data definition, an itemization of
compound data. (All object-oriented languages and
object-oriented programming deal exclusively with this kind of
data. But we will not restrict ourselves to only objects—
Since these data definitions are more complicated, coming up with and using the template will be critical in this assignment!
The context of this assignment will continue to be the game that we have been developing, and we will now begin to add other types of blocks.
(Note that no solutions to previous hws are needed to complete this assignment. In fact, since this assignment requires new data definitions, it is recommended that all students start from scratch, even those who completed previous ones. Trying to "adapt" a previous solution will likely be the more error-prone path, so do so at your own risk.)
You will not need big-bang in this assignment, though we may post an online demo that uses some of the functions from this assignment (maybe coming soon!)
Reading
(Re)read Chapters 6 and 10 of the Textbook, and also review the chapters about lists (8-17).
Review the The Design Recipe section of the course website for new elements of the design recipe that we have learned.
Pre-programming Notes
- All code must be written following the The Design Recipe. (Just submitting code is not sufficient.) In additional to the required receipe steps, some language features may only be used in the certain scenarios, as called for by The Design Recipe.
For example, set! and other "imperative" features are not allowed ever.
NEW: Each function is allowed one if expression, to "process" a piece of Boolean data, in addition to another kind of data, in functions that need to do so, e.g., filter. (Conditionals such as cond remain restricted to Data Definitions.)
Signatures should use define/contract and the predicates defined in the Data Design Recipe step. NEW: The listof contract constructor may be useful to use with functions that process list inputs. If a function is defined with define/contract and it’s clear which data definitions its contract refers to, then there’s no need to also include comment signatures.
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 be 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. Each function should have at minimum one Example, and "sufficient" Tests.
Tests should go in a tests.rkt file, as described in lecture, and the rest of the code should go in a file named hw7.rkt.
The submitted program must be only a series of defines (both constants and function definitions are allowed). It should not run any code (e.g., it should not start the big-bang loop automatically!). Not following this will result in GradeScope errors and/or timeouts.
You may look at lecture code to help you but DO NOT SUBMIT ANY OF THIS CODE (even if you change the variable names, etc). You won’t receive any credit. Instead, you should write code for this homework from scratch using The Design Recipe.
NEW: One-line helper functions—
if the name and description clearly describe what it does (the course staff is the final arbiter of this)— do not need to be submitted with Examples and Tests, if they are covered by other tests. NOTE: This does not change the Design Recipe. It is only changing submission requirements. As usual, however, it will be difficult to offer help with code that does not follow the design recipe, so omit these steps at your own risk. struct instances, e.g., for WorldState data, must be comparable with equal? and check-equal?, which means that they should be declared with the #:transparent keyword.
Important: Each submission must be organized so that each function only processes one kind of data. Submissions consisting of only a few large, unreadable functions that try to do everything will not receive any credit.
Programming
- In this assignment:
a UNIT is 40 pixels,
the WIDTH of a row is 10 UNITs.
the HEIGHT of all possible rows is 20 UNITs
- This assignment uses the following Data Definitions:
- A RotationState that is an enumeration of four values, representing each of the possible rotation states of a block. See below for what the rotation states of each block are. Formally,
;; A RotationState is one of: ;; - ROTATION1 ;; - ROTATION2 ;; - ROTATION3 ;; - ROTATION4 The above data definition uses constants which you should define. You may choose whatever values you want to actually represent each state, though some choices will make writing the code easier than others. (Note: choosing RotationState = 1, etc might not be the best choice)
- A Block is one of:
(mk-IBlock [x : XCoord] [y : YCoord] [r : RotationState])
(mk-JBlock [x : XCoord] [y : YCoord] [r : RotationState])
(mk-LBlock [x : XCoord] [y : YCoord] [r : RotationState])
An I-Block (cyan) and J-Block (blue) are as previously described, and an L-Block (orange) is the "mirror" of a J-Block (we’ll only use 3 blocks for now, to keep the assignment small). The x and y components represent the rotation point of the blocks. The following image shows the rotation points, along with the RotationStates of each of the blocks (the left image is ROTATION1) A 1Block is the same as in the previous assignment
- To be properly tested, your program should complete the data definitions above, and also define and provide the following:
- the following Block constructors:
mk-IBlock
mk-JBlock
mk-LBlock
Note: You might find the "super struct" feature useful. Block->Image : takes a Block input and produces a (properly rotated) image of that block.
get-Block-bottom : takes a Block input and produces the bottommost y-coordinate of the block
at-bottom? : takes a Block input and evaluates to true if the bottom of the block is at y coordinate UNIT * HEIGHT
block-adjacent-to-1blocks? : same as Homework 6
cant-move-down? : takes a Block and a Listof<1Block> and evaluates to true if the block is either "at bottom" or its bottom is "adjacent" to the top of the given 1Blocks. You should use the two functions above in this function.
Block-down : takes a Block and adds UNIT to its y component
maybe-Block-down : takes a Block and a Listof<1Block> and moves it "down" if it’s not "at the bottom" or "adjacent" to the 1Blocks. This function should use some of the functions above. Also, since the function name clearly indicates that this function needs to consider a predicate, it is allowed to use one if expression.
rotate-Block : takes a Block and updates its RotationState using next-RotationState. Note: this function does not need to reposition the Block, as described in Homework 4.
- Block->1Blocks : converts a Block into an equivalent Listof<1Block>. It should define and use the following functions:
IBlock->1Blocks
JBlock->1Blocks
LBlock->1Blocks
same-pos? : Takes two 1Blocks and evaluates to true if they both have the same center x and ycoordinates. This function should use a Multi-argument Templates
overlap? : Takes two Listof<1Block> and evaluates to true if there is at least one pair of 1Blocks, one from each list, that have the same position.
Before Submitting
Testing (and Autograders)
Before submitting, note:
Do not submit until all code has been thoroughly tested (by you), which means writing a "sufficient" number of Test cases.
A GradeScope "Autograder" may or may not be released before the due date but either way, an Autograder is not a software development/testing tool, so do not use it as one. Code must be tested independent of any Autograder and questions about Autograders will be ignored (e.g., posts asking "why is the Autograder giving an error?" are not allowed)
If you do submit before the deadline and get an Autograder error, this is bonus information that indicates the submitted code is not complete and/or not correct. But it’s up to you to figure out what "correct" means and how to fix to the program.
Of course, the course staff is here and eager to help, but cannot do so without context information. The best way to supply this information is to INCLUDE EXAMPLES WITH ALL QUESTIONS, along with what the "expected" result should be! The posted examples should be the minimal amount of code needed to communicate the problem. This will receive the clearest possible answer.
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:
hw7.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 hw7.rkt and define tests for it.
Specifically, it should define a rackunit test-suite named TESTS 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 hw7. 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.)