Question: Needs to be in Dr.Racket. The provided code needed to make the tetris game shown is below the problems. Enhancements 1. In your game, the






Needs to be in Dr.Racket. The provided code needed to make the tetris game shown is below the problems.
Enhancements 1. In your game, the player can press the 'u' key to make the piece that is falling rotate 180 degrees. (Note it is normal for this to make some pieces appear to move slightly.) 2. In your game, instead of the pieces being randomly (and uniformly) chosen from the 7 classic pieces, the pieces are randomly (and uniformly) chosen from 10 pieces. They are the classic 7 and these 3: The initial rotation for each piece is also chosen randomly. 3. In your game, the player can press the 'c' key to cheat: If the score is less than 100, nothing happens. Else the player loses 100 points (cheating costs you) and the next piece that appears will be: The piece after is again chosen randomly from the 10 above (unless, of course, the player hits 'c' while the "cheat piece" is falling and still has a large enough score). Hitting 'c' multiple times while a single piece is falling should behave no differently than hitting it once. 1 Requirements For our testing scripts to work, you must follow these guidelines. Your game should have all the features of the original Tetris game, as well as the enhancements. The subclasses you create must start with my-followed by the name of the original class. For example, your Tetris class should be called my-tetris%. We have provided empty class definitions for you to complete. You do not need any other classes. . All your new pieces, including your cheat piece, must use the same format as the provided pieces. . Do not use the Racket graphics library directly in any way. The only use of racket/gui should occur indirectly by using instances of classes defined in hu7graphics.rkt as needed (only a little is needed). Do not have (require racket/gui) in your hw7assignment.rkt file. ulang racket (require racket/random) for randon-ref (require "hw7graphics.rkt") (provide all-shapes rotations) (provide tetrisx board) (define all-colors (list "dark green" "dark blue" "dark red" "gold" "dark violet" "orange red" "gray")) ; module-exported function to compute all four rotations of a shape with no symmetries. (define (rotations vector-of-points) (define (rotate9e point) (cons (- (cdr point)) (car point))) (define rotate180 (compose rotatese rotate98)) (define rotate270 (compose rotate188 rotate98)) (for/vector ([f (in-list (list identity rotate98 rotate189 rotate270))]) (vector-napf vector-of-points))) ; A "shape" is a vector of vectors of points, representing all possible rotations of the shape. A point is a pair of the Ints. Here is a list of all the classic tetris shapes (including their rotations as needed). (define all-shapes (vector (vector (vector (@.0) (1.0) (0.1) (1.1))) square (only needs one) (rotations (vector (@.0) (-1.0) (1.0) (0.-1))) T (vector (vector (0.8) (-1.0) (1.0) '(2.0)) : Long (only needs two) (vector (@.) (@.-1) '(@. 1) '(@. 2))) (rotations (vector (@.0) (@.-1) (0.1) (1.1))) (rotations (vector (@.0) (0-1) (9.1) (1.1))) Inverted 2 (rotations (vector (2.0) '(-1.0) (@.-1) '(1.-1))) is (rotations (vector (@.0) (1.0) (0-1) (-1.-1))))); Z (define translate-point dx dy) (match-lambda (cons x y) (cons (+ x dx) + y dy))))) (define (translate-points dx dy) (curry vector-nap (translate-point dx dy))) ; Represents the current piece, including its shape, position, notation, and color. (define pieces (class object (super-new) (init-field all-rotations board) Envariant: in range (@..n), where n is (vector-Length all-rotations) (define rotation-index (random (vector-length all-rotations))) (field [color (randon-ref all-colors)]) (field [(base-position position) (5.)]); (column. row) aka (y) (define (to-grid-space points) ((translate-points (car base-position) (cdr base-position)) points)) (define (current-rotation) (vector-ref all-rotations rotation-index)) (define/public (get-points) (to-grid-space (current-rotation) takes the intended movement in x, y and rotation and checks to see if the movement is possible. If it is, makes this movement and returns true. Otherwise returns false. (define/public (move dx dy [drot )) (define new-rotation-index (modulo (+ rotation-index drot) (vector-length all-rotations))) (define candidate-rotation (translate-points dx dy) (to-grid-space (vector-ref all-rotations new-rotation-index)))) for each individual block in the piece, checks if the intended move will put this blocke in an occupied space. note fancy use of and: Ef sequence-andmap returns false, return false, } else, continue and do the rest of the "conjuncts". taking advantage, of the fact that set! returns (void), which is truthy. (only #f is not truthy!) (and (sequence-andmap (a (point) (send board empty-at? point)) candidate-rotation) (set! rotation-index new-rotation-index) (set! base-position (translate-point dx dy) base-position)) #t)) (define/public (drop-by-one) (move @ 1)))) Class responsible for the interaction between the pieces and the game itself define board (class object (super-new) (init-field game) (field (current-piece uf]) (next-piece) (field (score ] current score (delay 580] ; current delay (num-columns 10) [num-rows 27]) (field (grid (build-vector nun-rows (A) (make-vector nun-columns #f))))) the game is over when there is a piece extending into the second row from the top (define/public (game-over?) (sequence ormap identity (vector-ref grid 1))) ; moves the current piece down by one and returns t), or, if that is not possible, stores the current piece in the grid, generates a new plece, and returns if. (define/public (step) (define stepped (send current-piece drop-by-one)) (unless stepped (store-current) (unless (game-over?) (next-piece))) stepped) > Moves the current piece in the given direction/rotation, if possible. Return boolean indicating whether move succeeded. (define (move dx dy [drote]) (and (not (gante-over?)) (send gane running?) (begine (send current-piece move dx dy drot) (send game refresh)>>> (define/public (move-left) (nove -1 8)) (define/public (move-right) (move 1 )) (define/public (rotate-clockwise) (move 1)) (define/public (rotate-counter-clockwise) (move @ @ -1)) drops the piece to the Lowest Location in the currently occupied colums. Then replaces it with a new piece Change the score to reflect the distance dropped. (define/public (drop-all-the-way) (when (send game running?) Luv too Lop (do) ((not (step))) (set! score (+ score 1))) (send gane refresh))) (define/public (select-shape) (randon-ref all-shapes)) (define/public (next-piece) (set! current-piece (new piece% [ all-rotations (select-shape) [board this]>> Gets the information from the current piece about where it is and uses this is to store the piece on the board itself. Then calls remove_filled. (define/public (store-current) (define points (send current-piece get-points)) (for ([idx (in-range 4)]) ; teehee, I hope all the pieces have 4 blocks (match-define (cons x y) (vector-ref points idx)) (when (>= y B) (vector-set! (vector-ref grid y) x (get-field color current-piece)>>> (remove-filled) (set! delay (max (- delay 2) se))) Takes a point and checks to see if it is in the bounds of the board and currently empty. (define/public (empty-at? point) (match point [(cons xy) (and (>= x ) (] [parent global-pane])) (new tetris-buttons[label "new game"] [parent top-pane) [callback ( (be) (new-game))]) (new tetris-button (label "pause") [parent top-pane] [callback (a (be) (toggle-pause))]) (new tetris-button% [label "quit" ] [parent top-pane] [callback ((be) (on-close) (exit))]) (define score-pane (new tetris-horizontal-panes [alignment center center)] [parent global-pane])) (new tetris-messagex (label "Current Score:"] [parent score-pane]) (field (score (new tetris-messagex [label "-"] [parent score-pane] [auto-resize #t]}]) (set-board) The canvas is the general-purposes drawing widget that will let us draw rectangles so that we can visualize the board. See the paint method below. (field (canvas (new tetris-canvasx [game this) [parent global-pane] (stretchable-width #f) (stretchable-height #f] (min-width (* block-size (get-field num-columns board))] (min-height (* block-size (get-field nun-rows board))]))) (send canvas set-canvas-background (make-color "light blue")) (new tetris-button (label "O"] [parent global-pane] [callback ( (be) (send board rotate-clockwise))]) (define arrow-pane (new tetris-horizontal-panes [alignment center center)] [parent global-pane])) (new tetris-button (label "left"] [parent arrow-pane] [callback ( (be) (send board move-left))]) (new tetris-buttons[label "drop"] [parent arrow-pane] [callback (a (be) (send board drop-all-the-way))]) (new tetris-buttons (label "right") [parent arrow-pane] [callback ((be) (send board move-right))]) (new tetris-button' [label "O") (parent global-pane] [callback (A (be) (send board rotate-counter-clockwise)))) Handle keypresses. Can be "augmented" by subclasses to handle further keys. (define/pubment (on-char event) (define keycode (send event get-key-code)) (match keycode [# (new-gane)] ["\p (toggle-pause)] ["\q (exit)] [(or a 'left) (send board move-left)] [(or !\d 'right) (send board move-right)] [(or \s 'down) (send board rotate-counter-clockwise)] [(or !\'up) (send board rotate-clockwise)] ["\space (send board drop-all-the-way)] L (inner of on-char event)])) (update-score) (send root show at) (run-game) (define/public (set-board) (set! board (new boardx [gane this]))) Repeatedly calls itself (through timer-callback) so that the process is fully automated. Checks if the game is over and if it isn't, resets the timer. (define/public (run-game) (when (and (not (send board gane-over?)) running) (send timer stop) (send timer start (get-field delay board) #t))) (define/public (refresh) (update-score) (send canvas refresh-now)) Starts the gawe over, replacing the old board and score (define/public (new-game) (set-board) (set! running #t) (refresh) (run-game)) Uses racket/drow's drawing context to draw a block. (define/public (draw-block dc row-idx column-idx color) (send dc set-brush color 'solid) (send dc draw-rectangle (* block-size colunn-idx) (block-size row-idx) block-size block-size)) Iterates over the board's grid plus the current piece, and draws all the blocks with the right colors. ;; Called by tetris-canvas (see on-point in graphics.rkt), which is called indirectly through the refresh-now method COLL above. dc is a rocket/drow "drawing context" (see docs) (define/public (paint dc) (for ([row (in-vector (get-field grid board))] [row-idx in-naturals)]) (for (maybe-color (in-vector row)] [column-idx (in-naturals)] when maybe-color) (draw-block dc row-idx column-idx maybe-color))) (define current-piece (get-field curre -piece boar (define current-color (get-field color current-piece)) (for ([point (send current-piece get-points)]) (match-let ([(cons x y) point]) (draw-block de y x current-color)))) pouses the gawe or resumes it (define/public (toggle-pause) (cond (running (send timer stop) (set! running #f)] (else (set! running wt) (run-game)])) (define/public (running?) running) ; the application will not exit cleanly if the timer is Left running (define/public (on-close) (send timer stop)) ; alters the displayed score to reflect what is currently stored in the board (define/public (update-score) (send score set-label (number-string (get-field score board)))))) Enhancements 1. In your game, the player can press the 'u' key to make the piece that is falling rotate 180 degrees. (Note it is normal for this to make some pieces appear to move slightly.) 2. In your game, instead of the pieces being randomly (and uniformly) chosen from the 7 classic pieces, the pieces are randomly (and uniformly) chosen from 10 pieces. They are the classic 7 and these 3: The initial rotation for each piece is also chosen randomly. 3. In your game, the player can press the 'c' key to cheat: If the score is less than 100, nothing happens. Else the player loses 100 points (cheating costs you) and the next piece that appears will be: The piece after is again chosen randomly from the 10 above (unless, of course, the player hits 'c' while the "cheat piece" is falling and still has a large enough score). Hitting 'c' multiple times while a single piece is falling should behave no differently than hitting it once. 1 Requirements For our testing scripts to work, you must follow these guidelines. Your game should have all the features of the original Tetris game, as well as the enhancements. The subclasses you create must start with my-followed by the name of the original class. For example, your Tetris class should be called my-tetris%. We have provided empty class definitions for you to complete. You do not need any other classes. . All your new pieces, including your cheat piece, must use the same format as the provided pieces. . Do not use the Racket graphics library directly in any way. The only use of racket/gui should occur indirectly by using instances of classes defined in hu7graphics.rkt as needed (only a little is needed). Do not have (require racket/gui) in your hw7assignment.rkt file. ulang racket (require racket/random) for randon-ref (require "hw7graphics.rkt") (provide all-shapes rotations) (provide tetrisx board) (define all-colors (list "dark green" "dark blue" "dark red" "gold" "dark violet" "orange red" "gray")) ; module-exported function to compute all four rotations of a shape with no symmetries. (define (rotations vector-of-points) (define (rotate9e point) (cons (- (cdr point)) (car point))) (define rotate180 (compose rotatese rotate98)) (define rotate270 (compose rotate188 rotate98)) (for/vector ([f (in-list (list identity rotate98 rotate189 rotate270))]) (vector-napf vector-of-points))) ; A "shape" is a vector of vectors of points, representing all possible rotations of the shape. A point is a pair of the Ints. Here is a list of all the classic tetris shapes (including their rotations as needed). (define all-shapes (vector (vector (vector (@.0) (1.0) (0.1) (1.1))) square (only needs one) (rotations (vector (@.0) (-1.0) (1.0) (0.-1))) T (vector (vector (0.8) (-1.0) (1.0) '(2.0)) : Long (only needs two) (vector (@.) (@.-1) '(@. 1) '(@. 2))) (rotations (vector (@.0) (@.-1) (0.1) (1.1))) (rotations (vector (@.0) (0-1) (9.1) (1.1))) Inverted 2 (rotations (vector (2.0) '(-1.0) (@.-1) '(1.-1))) is (rotations (vector (@.0) (1.0) (0-1) (-1.-1))))); Z (define translate-point dx dy) (match-lambda (cons x y) (cons (+ x dx) + y dy))))) (define (translate-points dx dy) (curry vector-nap (translate-point dx dy))) ; Represents the current piece, including its shape, position, notation, and color. (define pieces (class object (super-new) (init-field all-rotations board) Envariant: in range (@..n), where n is (vector-Length all-rotations) (define rotation-index (random (vector-length all-rotations))) (field [color (randon-ref all-colors)]) (field [(base-position position) (5.)]); (column. row) aka (y) (define (to-grid-space points) ((translate-points (car base-position) (cdr base-position)) points)) (define (current-rotation) (vector-ref all-rotations rotation-index)) (define/public (get-points) (to-grid-space (current-rotation) takes the intended movement in x, y and rotation and checks to see if the movement is possible. If it is, makes this movement and returns true. Otherwise returns false. (define/public (move dx dy [drot )) (define new-rotation-index (modulo (+ rotation-index drot) (vector-length all-rotations))) (define candidate-rotation (translate-points dx dy) (to-grid-space (vector-ref all-rotations new-rotation-index)))) for each individual block in the piece, checks if the intended move will put this blocke in an occupied space. note fancy use of and: Ef sequence-andmap returns false, return false, } else, continue and do the rest of the "conjuncts". taking advantage, of the fact that set! returns (void), which is truthy. (only #f is not truthy!) (and (sequence-andmap (a (point) (send board empty-at? point)) candidate-rotation) (set! rotation-index new-rotation-index) (set! base-position (translate-point dx dy) base-position)) #t)) (define/public (drop-by-one) (move @ 1)))) Class responsible for the interaction between the pieces and the game itself define board (class object (super-new) (init-field game) (field (current-piece uf]) (next-piece) (field (score ] current score (delay 580] ; current delay (num-columns 10) [num-rows 27]) (field (grid (build-vector nun-rows (A) (make-vector nun-columns #f))))) the game is over when there is a piece extending into the second row from the top (define/public (game-over?) (sequence ormap identity (vector-ref grid 1))) ; moves the current piece down by one and returns t), or, if that is not possible, stores the current piece in the grid, generates a new plece, and returns if. (define/public (step) (define stepped (send current-piece drop-by-one)) (unless stepped (store-current) (unless (game-over?) (next-piece))) stepped) > Moves the current piece in the given direction/rotation, if possible. Return boolean indicating whether move succeeded. (define (move dx dy [drote]) (and (not (gante-over?)) (send gane running?) (begine (send current-piece move dx dy drot) (send game refresh)>>> (define/public (move-left) (nove -1 8)) (define/public (move-right) (move 1 )) (define/public (rotate-clockwise) (move 1)) (define/public (rotate-counter-clockwise) (move @ @ -1)) drops the piece to the Lowest Location in the currently occupied colums. Then replaces it with a new piece Change the score to reflect the distance dropped. (define/public (drop-all-the-way) (when (send game running?) Luv too Lop (do) ((not (step))) (set! score (+ score 1))) (send gane refresh))) (define/public (select-shape) (randon-ref all-shapes)) (define/public (next-piece) (set! current-piece (new piece% [ all-rotations (select-shape) [board this]>> Gets the information from the current piece about where it is and uses this is to store the piece on the board itself. Then calls remove_filled. (define/public (store-current) (define points (send current-piece get-points)) (for ([idx (in-range 4)]) ; teehee, I hope all the pieces have 4 blocks (match-define (cons x y) (vector-ref points idx)) (when (>= y B) (vector-set! (vector-ref grid y) x (get-field color current-piece)>>> (remove-filled) (set! delay (max (- delay 2) se))) Takes a point and checks to see if it is in the bounds of the board and currently empty. (define/public (empty-at? point) (match point [(cons xy) (and (>= x ) (] [parent global-pane])) (new tetris-buttons[label "new game"] [parent top-pane) [callback ( (be) (new-game))]) (new tetris-button (label "pause") [parent top-pane] [callback (a (be) (toggle-pause))]) (new tetris-button% [label "quit" ] [parent top-pane] [callback ((be) (on-close) (exit))]) (define score-pane (new tetris-horizontal-panes [alignment center center)] [parent global-pane])) (new tetris-messagex (label "Current Score:"] [parent score-pane]) (field (score (new tetris-messagex [label "-"] [parent score-pane] [auto-resize #t]}]) (set-board) The canvas is the general-purposes drawing widget that will let us draw rectangles so that we can visualize the board. See the paint method below. (field (canvas (new tetris-canvasx [game this) [parent global-pane] (stretchable-width #f) (stretchable-height #f] (min-width (* block-size (get-field num-columns board))] (min-height (* block-size (get-field nun-rows board))]))) (send canvas set-canvas-background (make-color "light blue")) (new tetris-button (label "O"] [parent global-pane] [callback ( (be) (send board rotate-clockwise))]) (define arrow-pane (new tetris-horizontal-panes [alignment center center)] [parent global-pane])) (new tetris-button (label "left"] [parent arrow-pane] [callback ( (be) (send board move-left))]) (new tetris-buttons[label "drop"] [parent arrow-pane] [callback (a (be) (send board drop-all-the-way))]) (new tetris-buttons (label "right") [parent arrow-pane] [callback ((be) (send board move-right))]) (new tetris-button' [label "O") (parent global-pane] [callback (A (be) (send board rotate-counter-clockwise)))) Handle keypresses. Can be "augmented" by subclasses to handle further keys. (define/pubment (on-char event) (define keycode (send event get-key-code)) (match keycode [# (new-gane)] ["\p (toggle-pause)] ["\q (exit)] [(or a 'left) (send board move-left)] [(or !\d 'right) (send board move-right)] [(or \s 'down) (send board rotate-counter-clockwise)] [(or !\'up) (send board rotate-clockwise)] ["\space (send board drop-all-the-way)] L (inner of on-char event)])) (update-score) (send root show at) (run-game) (define/public (set-board) (set! board (new boardx [gane this]))) Repeatedly calls itself (through timer-callback) so that the process is fully automated. Checks if the game is over and if it isn't, resets the timer. (define/public (run-game) (when (and (not (send board gane-over?)) running) (send timer stop) (send timer start (get-field delay board) #t))) (define/public (refresh) (update-score) (send canvas refresh-now)) Starts the gawe over, replacing the old board and score (define/public (new-game) (set-board) (set! running #t) (refresh) (run-game)) Uses racket/drow's drawing context to draw a block. (define/public (draw-block dc row-idx column-idx color) (send dc set-brush color 'solid) (send dc draw-rectangle (* block-size colunn-idx) (block-size row-idx) block-size block-size)) Iterates over the board's grid plus the current piece, and draws all the blocks with the right colors. ;; Called by tetris-canvas (see on-point in graphics.rkt), which is called indirectly through the refresh-now method COLL above. dc is a rocket/drow "drawing context" (see docs) (define/public (paint dc) (for ([row (in-vector (get-field grid board))] [row-idx in-naturals)]) (for (maybe-color (in-vector row)] [column-idx (in-naturals)] when maybe-color) (draw-block dc row-idx column-idx maybe-color))) (define current-piece (get-field curre -piece boar (define current-color (get-field color current-piece)) (for ([point (send current-piece get-points)]) (match-let ([(cons x y) point]) (draw-block de y x current-color)))) pouses the gawe or resumes it (define/public (toggle-pause) (cond (running (send timer stop) (set! running #f)] (else (set! running wt) (run-game)])) (define/public (running?) running) ; the application will not exit cleanly if the timer is Left running (define/public (on-close) (send timer stop)) ; alters the displayed score to reflect what is currently stored in the board (define/public (update-score) (send score set-label (number-string (get-field score board))))))
Step by Step Solution
There are 3 Steps involved in it
Get step-by-step solutions from verified subject matter experts
