

The graphics can be inspected directly in the DrRacket REPL, by running (block->pict T-Block) to display a single block, or building a list of these pictures using (map block->pict all-blocks):īlocks can be rotated clockwise and counter clockwise during the game, in 90 degree increments, so we need to implement a mechanism to rotate the blocks.
#ALL TETRIS BLOCKS CODE#
In addition to tests, contracts are useful in ensuring that defects in the code are detected and reported as early as possible. a valid tetris block for the block->pict function) and they return the expected value, a pict in our case. This ensures that they will check that their arguments are what we expect them to be (e.g. ( define/contract ( block->pict block ) ( -> valid-block? pict? ) ( apply vc-append ( map row->squares block ))) ( define/contract ( row->squares row ) ( -> string? pict? ) ( define items ( for/list () ( define color ( hash-ref colors char #f )) ( if color ( filled-rectangle square-size square-size #:color color ) ( rectangle square-size square-size )))) ( apply hc-append items ))īoth functions are protected by contracts, as indicated by the define/contract form. We will also define a mapping from the characters used in block strings to actual colors: The square-size defines the size of each square, it is useful to define it separately, so blocks can be easily made bigger or smaller. We will use the pict package for the graphics and have them displayed directly in the DrRacket REPL.īlocks can be constructed out of squares, an empty one for the spaces in the 4x4 grid and a color square for the filled in squares. If you have some experience with GUI applications, you would think that we need to construct a frame and a canvas before we can draw the tetris blocks, but in Racket all this can be left until later. ( module+ test ( check-false ( valid-block-row? 1 )) not a string ( check-false ( valid-block-row? "." )) more than 4 characters ( check-false ( valid-block-row? "X." )) containing invalid characters ( check-false ( valid-block? "hello" )) not a list ( check-false ( valid-block? ( append L-Block T-Block ))) more than 4 items ( check-false ( valid-block? ( list "." "." "." 1 ))) not a list of strings ( check-false ( valid-block? ( list "X." "." "." "." ))) contains invalid characters Verify that all our blocks are correctly defined ( for () ( check-pred valid-block? block ))) Before we start writing functions which manipulate these blocks, it is useful to define two validation functions, valid-block-row? will check if a single string is valid for a block definition, while valid-block? will verify that a tetris block definition actually conforms to our conventions: Using lists of strings for our blocks has some disadvantages, since Racket cannot validate a correct block definition. Racket will also display strings directly, so the results of various functions can be inspected directly into the REPL, without the need to define separate functions to display the data structures. Using a string representation means that there is a visual cue about the shape of the blocks right in the program source.
