;===== ; CS 111 - Week 6 Lecture 2 - 2025-10-02 (require 2htdp/image) (require 2htdp/universe) ;===== ; DATA DEFINITION ; an Anything is an expression of any type ;===== ; DATA DEFINITION ; a list is one of: ; * empty ; * (cons Anything list) ; cons for CONStruct a list ;===== ; COMPLETED template for a function that "walks through" a list ; ; * "walks through"? Might need to do something involving or ; to *each* element in a list of unknown size ; ; * AFTER writing your tests for such a function, ; (being SURE to include at least one test ; with an empty list AND at least one with ; a NON-empty list, and MORE if there are additional ; cases), ; * PASTE this into your function body to help ; in COMPLETING that function body: ; ; (define (a-list-funct ... a-list ...) ; (cond ; [(empty? a-list) ...] ; [else (... ; ... (first a-list) ... ; (a-list-funct ... (rest a-list) ...) ...) ; ] ; ) ; ) ;===== ; NOTE: when a function CALLS itself -- ; as len does, as add1-list does, ; and as the a-list-funct in the template above does -- ; that function is called a RECURSIVE function. ; ; * It is VITAL that, in a recursive function: ; * it includes at least ONE branch that does NOT ; call itself! (called a BASE case) ; * its recursive calls to itself are always on a ; "SMALLER" version of the original parameter, ; (such that, eventually, your repeated calls ; WILL eventually reach one of the base cases!) ;==== ; writing to a file? ; 2htdp/batch-io module includes ONE write function: (require 2htdp/batch-io) ;----- ; signature: write-file: string string -> string ; purpose: expects the name of a file written as a string -- ; either its full/"absolute" name OR its name in the current ; working directory -- ; AND the string to write to that file, ; has the SIDE-EFFECT of trying to write that string ; to that file, creating the file if necessary, ; (and OVERWRITING its current contents if it exists), ; and returns the name of the file ;===== ; FUN FACT: you can indicate a newline within a string ; using the \n character ; (the default display of these in DrRacket's Interactions ; window is as \n, BUT they WILL appear as newlines when ; written to a file!) "(don't worry, when written to a file the \n characters below" " are treated as newlines)" "1\n2\n3" "after running this, view the contents of the file sample.txt" (write-file "sample.txt" "hello\n32") ;===== ; what if I want a big-bang expression whose ; world is a list of IMAGES? ; ; and here, I want to make use of a function ; that takes a list of images and adds them ; randomly to a scene ;----- ; first: some useful named constants (define SC-WIDTH 300) (define SC-HEIGHT 200) (define BACKDROP (empty-scene SC-WIDTH SC-HEIGHT)) ;===== ; for this big-bang's on-tick clause -- well, we ; don't want the world to change, in this case! ; so how about a function that just returns the ; current world unchanged? ;===== ; signature: return-current: Anything -> Anything ; purpose: expects any value, and returns it unchanged (check-expect (return-current 3) 3) (check-expect (return-current empty) empty) (define (return-current any-value) any-value ) ;===== ; signature: draw-images-randomly: list -> scene ; purpose: expects a list of images, and returns a scene ; of those images centered at random locations ;----- ; need at least two tests, and for a function expecting ; a list of uncertain size, ; one of those tests needs to be for an empty list (check-random (draw-images-randomly empty) BACKDROP) ;----- ; for more-convenient testing... (define SHAPE-TRIO (cons (circle 30 "solid" "purple") (cons (triangle 35 "outline" "darkgreen") (cons (square 50 "solid" "pink") empty)))) (check-random (draw-images-randomly SHAPE-TRIO) (place-image (first SHAPE-TRIO) (random SC-WIDTH) (random SC-HEIGHT) (draw-images-randomly (rest SHAPE-TRIO)))) (define (draw-images-randomly image-list) (cond [(empty? image-list) BACKDROP] [else (place-image (first image-list) (random SC-WIDTH) (random SC-HEIGHT) (draw-images-randomly (rest image-list))) ] ) ) (draw-images-randomly SHAPE-TRIO) "=====" "non-interactive version -- " " CLOSE the big-bang World window to continue!" "=====" (big-bang SHAPE-TRIO (on-tick return-current 0.5) (to-draw draw-images-randomly)) ;===== ; what if: certain keystrokes could add shapes to this world? ;----- ; say: a "c" to add a circle, say with a 20-pixel radius? ; a "t" to add a triangle, say with 25-pixel sides? ; a "s" to add a star, say with 25 pixels between its points? ; say, randomly-colored? ;===== ; signature: add-shape: list string -> list ; purpose: expects a list of images and a shape key, ; one of "c" or "t" or "s", and returns a new list ; with a new first randomly-colored ; shape added to the given list as follows: ; * for "c", it adds a 20-pixel-radius circle ; * for "t", it adds a 25-pixel-sided triangle ; * for "s", it adds a 25-pixels-between-its-points star ; * for any other key, it returns the given list unchanged ;----- ; since the newly-added shapes' sizes are constant... (define CIRC-SIZE 20) (define TRI-SIZE 25) (define STAR-SIZE 25) ;===== ; have lists AND enumeration data here, but which are ; "driving" this function's action? ; really, it is the enumeration data -- the shape key string; ; SO: need at least 4 tests here, ; one for each of the 3 values in the enumeration, ; and, because the function specifies what is desired for ; a "bad" shape key value, need a test for that, also. (check-random (add-shape empty "c") (cons (circle CIRC-SIZE "solid" (make-color (random 256) (random 256) (random 256))) empty)) (check-random (add-shape SHAPE-TRIO "t") (cons (triangle TRI-SIZE "solid" (make-color (random 256) (random 256) (random 256))) SHAPE-TRIO)) (check-random (add-shape (list (rectangle 25 30 "outline" "red")) "s") (cons (star STAR-SIZE "solid" (make-color (random 256) (random 256) (random 256))) (list (rectangle 25 30 "outline" "red")))) ;----- ; IMPROVED after class: ; because your tests SHOULD each have DIFFERENT argument values... (define MULTI-RINGS (list (circle 10 "outline" "red") (circle 10 "outline" "green") (circle 10 "outline" "blue") (circle 10 "outline" "black"))) (check-expect (add-shape MULTI-RINGS "g") MULTI-RINGS) (define (add-shape img-list shape-key) (cond [(string=? shape-key "c") (cons (circle CIRC-SIZE "solid" (make-color (random 256) (random 256) (random 256))) img-list)] [(string=? shape-key "t") (cons (triangle TRI-SIZE "solid" (make-color (random 256) (random 256) (random 256))) img-list)] [(string=? shape-key "s") (cons (star STAR-SIZE "solid" (make-color (random 256) (random 256) (random 256))) img-list)] [else img-list] ) ) (add-shape (list (rectangle 25 30 "outline" "red")) "s") (add-shape MULTI-RINGS "t") "=====" "type c and/or t and/or s and see " " what happens!" "=====" (big-bang SHAPE-TRIO (on-tick return-current 0.5) (to-draw draw-images-randomly) (on-key add-shape))