Tuesday, 10 July 2012

Exercise 175: Design the program tetris-render...


Design the program tetris-render, which turns a given instance of Tetris into an Image.

You can download the code for this question from here.

This is a straight forward question. We have a data structure containing a collection of tetris blocks, which we need to turn into a world (game) scene.

We can do this by  recursing through our data structure until we have a complete scene.

I chose to split the tetris-render function into two functions - a main function and a helper function. This because the main render-tetris function only takes a single argument (a Tetris) and if I wanted to recurse into this I would need to continually be created a a new Tetris from the component parts I had (the head and the tail)

   
; Tetris is (make-tetris Block Landscape)
; Landscape is one of:
;  empty
;  (cons Block Landscape)
; Block is (make-block N N)
; interpretation: given (make-tetris (make-block x y) (list b1 b2 ...))
;   (x,y) is the logical position of the dropping block, while
;   b1b2, etc are the positions of the resting blocks
; a logical position (x,y) determines how many SIZEs the block is
;   from the leftxand from the topx.
   

Code

(define-struct block (x y))
(define-struct tetris (block landscape))

; physical constants
(define WIDTH 10) ; the maximal number of blocks horizontally


; graphical constants
(define SIZE 10) ; blocks are square
(define BLOCK ; they are rendered as red squares with black rims
  (overlay (rectangle (- SIZE 1) (- SIZE 1) "solid" "red")
           (rectangle SIZE SIZE "outline" "black")))


; this is just an example/test Tetris scene.
(define TETRIS  (make-tetris (make-block 10 60)
                             (list (make-block 20 40) )))


(define SCENE-SIZE (* WIDTH SIZE))




; This tetris-render function is a wrapper around the main function.
; This just splits the tetris into the initial block/landscape tuple and
; calls the main tetris-render-helper function.
(define (tetris-render tetris)
  (tetris-render-helper (tetris-block tetris)
                        (tetris-landscape tetris)))




; draw a tetris scene. This is the function that does the guts of the work.
; If our landscape is empty, just draw the block onto an empty scene
; otherwise recurse, and draw draw the current block on the result of drawing 
; the rest of the blocks.
(define (tetris-render-helper block landscape)
  (draw-block block
              (cond ((empty? landscape )    
                     (empty-scene SCENE-SIZE SCENE-SIZE))
                    (else (tetris-render-helper  (first landscape)
                                                 (rest landscape))))))


; draw our block on supplied background. 
(define (draw-block block background)
 (place-image BLOCK
                (block-x block) (block-y block)
                background))


(tetris-render  TETRIS)


; ## TESTS ##


; simple example - a single block in an empty landscape
(check-expect (tetris-render (make-tetris (make-block 20 40) empty))
              (place-image BLOCK 20 40 (empty-scene SCENE-SIZE SCENE-SIZE)))


; a slightly more complex test - drawing two blocks
(check-expect (tetris-render (make-tetris (make-block 10 60)
                              (list (make-block 20 40) )))
              (place-image BLOCK 10 60 (place-image BLOCK 20 40 
                              (empty-scene SCENE-SIZE SCENE-SIZE))))

No comments:

Post a Comment