# ----------------------------------------------------------------------------- # The next few lines show how to: # - Construct a second SimpleTurtle, # set its pen and speed INSTANCE VARIABLES, and ask it to do things. # ----------------------------------------------------------------------------- natasha = rg.SimpleTurtle('turtle') natasha.pen = rg.Pen('red', 30) # Second argument is the Pen's thickness natasha.speed = 5 # Bigger means faster, max is usually about 10 natasha.backward(50) natasha.right(90) natasha.forward(125) natasha.speed = 1 # Now slower natasha.go_to(rg.Point(-100, 200)) ############################################################################### # # TODO: 4. # Add a few more lines of your own code to make one of the existing # SimpleTurtles move some more and/or have different characteristics. # # ** Nothing fancy is required. ** # ** A SUBSEQUENT exercise will let you show your creativity. ** # # As always, test by running the module. # ############################################################################### natasha.speed = 19 natasha.forward(700)
def run_test_RETURN_circle(): """ Tests the RETURN_circle function. """ print() print('-----------------------------------------') print('Testing RETURN_circle:') print('-----------------------------------------') print() print('See the graphics window for this test.') print('If an error msg appears at any point,') print('then you have FAILED this test.') # ------------------------------------------------------------------ # Tests 1 and 2 (on one window): # ------------------------------------------------------------------ window = rg.RoseWindow(500, 400, 'Testing RETURN_circle') text = rg.Text(rg.Point(250, 125), '') text.attach_to(window.initial_canvas) circle = rg.Circle(rg.Point(200, 300), 50) circle.fill_color = 'blue' circle.attach_to(window.initial_canvas) msg = 'Note: If you see an error message at ANY point,\n' msg = msg + 'then you have failed this test.\n\n' msg = msg + 'I have drawn the original, blue circle.\n\n' msg = msg + 'So you should see a BLUE circle below\n' msg = msg + '(and nothing else).\n\n' msg = msg + 'Click the mouse to continue this test.\n' text.text = msg window.render(0.5) window.get_next_mouse_click() new_circle = RETURN_circle(circle, 'red') if new_circle: new_circle.attach_to(window.initial_canvas) msg = 'I have now called your RETURN_circle function\n' msg = msg + 'and drawn the CLONED, RED circle that your\n' msg = msg + 'RETURN_circle function should have returned.\n\n' msg = msg + 'So you should see a RED circle below\n' msg = msg + '(and nothing else, since the blue circle\n' msg = msg + 'is beneath the red circle).\n\n' msg = msg + 'Click the mouse to continue this test.' text.text = msg window.render(0.5) window.get_next_mouse_click() if new_circle: new_circle.detach_from(window.initial_canvas) msg = 'I have now UN-drawn the CLONED, RED circle.\n\n' msg = msg + 'So you should see the original, BLUE circle below\n' msg = msg + '(and nothing else).\n\n' msg = msg + 'Click the mouse to continue this test.' text.text = msg window.render(0.5) window.get_next_mouse_click() circle.detach_from(window.initial_canvas) msg = 'I have now UN-drawn the ORIGINAL, blue circle.\n\n' msg = msg + 'So you should see NO circles below.\n\n' msg = msg + 'Click the mouse to continue this test.' text.text = msg window.render(0.5) window.get_next_mouse_click() if new_circle: new_circle.attach_to(window.initial_canvas) msg = 'Now I have RE-drawn the CLONED, RED circle\n' msg = msg + 'that your RETURN_circle function\n' msg = msg + 'should have returned.\n\n' msg = msg + 'So you should see a RED circle below\n' msg = msg + '(and nothing else).\n\n' msg = msg + 'Click the mouse to continue this test.' text.text = msg window.render(0.5) window.get_next_mouse_click() # ------------------------------------------------------------------ # Note: The following statements make the variable new_circle # refer to a new, green circle. So we can no longer refer # to the RED circle (to which the variable new_circle once # referred). But the red circle still exists! # ------------------------------------------------------------------ new_circle = RETURN_circle(circle, 'green') if new_circle: new_circle.attach_to(window.initial_canvas) msg = 'Now I have ALSO drawn the CLONED, GREEN circle\n' msg = msg + 'that your RETURN_circle function\n' msg = msg + 'should have returned.\n\n' msg = msg + 'So you should see a GREEN circle below\n' msg = msg + '(and nothing else, since the red circle\n' msg = msg + 'is beneath the green circle).\n\n' msg = msg + 'Click the mouse to continue this test.' text.text = msg window.render(0.5) window.get_next_mouse_click() if new_circle: new_circle.detach_from(window.initial_canvas) msg = 'I have now UN-drawn the CLONED, GREEN circle.\n\n' msg = msg + 'So you should see the cloned, RED circle below\n' msg = msg + '(and nothing else).\n\n' msg = msg + 'Click the mouse to continue this test.' text.text = msg window.render(0.5) window.get_next_mouse_click() new_circle2 = RETURN_circle(rg.Circle(rg.Point(250, 350), 25), 'white') if new_circle: new_circle.attach_to(window.initial_canvas) if new_circle2: new_circle2.attach_to(window.initial_canvas) msg = 'I have now RE-drawn the CLONED, GREEN circle.\n' msg = msg + 'Additionally, I called your RETURN_circle function\n' msg = msg + 'again, asking it to return a smaller WHITE circle\n' msg = msg + 'that is below and to the right of the other circles.\n\n' msg = msg + 'So you should see a GREEN circle below\n' msg = msg + 'and a smaller WHITE circle below and to its right\n' msg = msg + '(but NOT the red circle, since it\n' msg = msg + 'is beneath the green circle).\n\n' msg = msg + 'Click the mouse to conclude this test.' text.text = msg window.render(0.5) window.get_next_mouse_click() window.close()
def circle_and_rectangle(): """ -- Constructs an rg.RoseWindow. -- Constructs and draws a rg.Circle and rg.Rectangle on the window such that: -- They fit in the window and are easily visible. -- The rg.Circle is filled with 'blue' -- Prints (on the console, on SEPARATE lines) the following data associated with your rg.Circle: -- Its outline thickness. -- Its fill color. -- Its center. -- Its center's x coordinate. -- Its center's y coordinate. -- Prints (on the console, on SEPARATE lines) the same data but for your rg.Rectangle. -- Waits for the user to press the mouse, then closes the window. Here is an example of the output on the console, for one particular circle and rectangle: 1 blue Point(180.0, 115.0) 180 115 1 None Point(75.0, 150.0) 75.0 150.0 """ window = rg.RoseWindow(700, 500) center = rg.Point(150, 400) radius = 100 circle = rg.Circle(center, radius) circle.fill_color = 'blue' circle.attach_to(window) circle_outline = circle.outline_thickness circle_fill = circle.fill_color circle_center = circle.center center_x = center.x center_y = center.y print("CIRCLE") print("circle outline thickness:", circle_outline) print("fill color:", circle_fill) print("center:", circle_center) print("center x-coordinate:", center_x) print("center y-coordinate:", center_y) print() #start rectangle r1 = rg.Point(422, 50) r2 = rg.Point(690, 172) rectangle = rg.Rectangle(r1, r2) rectangle.attach_to(window) rect_outline = rectangle.outline_thickness rect_fill = rectangle.fill_color rect_cent_x = (r1.x + r2.x) / 2 rect_cent_y = (r1.y + r2.y) / 2 print("RECTANGLE") print("rectangle outline thickness:", rect_outline) print("fill color:", rect_fill) print("center:", rect_cent_x, ",", rect_cent_y) print("center x-coordinate:", rect_cent_x) print("center y-coordinate:", rect_cent_y) print() window.render() window.close_on_mouse_click()
def problem2a(circle, rectangle, window): """ See problem2a_picture.pdf in this project for pictures that may help you better understand the following specification: What comes in: -- An rg.Circle. -- An rg.Rectangle. -- An rg.RoseWindow. What goes out: Nothing (i.e., None). Side effects: -- Draws the given rg.Circle and rg.Rectangle on the given rg.RoseWindow, DONE then waits for the user to click the window. -- Then draws an rg.Line from the upper-right corner of the rg.Rectangle to its lower-left corner, with the line drawn as an arrow, then waits for the user to click the window. -- Changes the fill color of the given rg.Circle to the outline color of the given rg.Rectangle, then renders the window again (with no waiting for a click from the user this time). Must ** NOT close ** the window. Type hints: :type circle: rg.Circle :type rectangle: rg.Rectangle :type window: rg.RoseWindow """ # ------------------------------------------------------------------ # DONE: 2. Implement and test this function. # Tests have been written for you (above). # ------------------------------------------------------------------ # ------------------------------------------------------------------ # DIFFICULTY AND TIME RATINGS (see top of this file for explanation) # DIFFICULTY: 6 # TIME ESTIMATE: 10 to 15 minutes. # ------------------------------------------------------------------ circle.attach_to(window) rectangle.attach_to(window) window.render(0.03) window.continue_on_mouse_click() start = rg.Point(rectangle._upper_right_corner.x, rectangle._upper_right_corner.y) end = rg.Point(rectangle._lower_left_corner.x, rectangle._lower_left_corner.y) line = rg.Line(start, end) line.attach_to(window) window.render(0.03) window.continue_on_mouse_click() circle.fill_color = rectangle.outline_color window.render(0.03) window.continue_on_mouse_click() circle.attach_to(window) rectangle.attach_to(window)
def return_point(point): return rg.Point(77, point.y) # Returns a NEW rg.Point
def draw_squares_from_circle(n, circle, window): """ What comes in: Three arguments: -- A positive integer n. -- An rg.Circle. -- An rg.RoseWindow. What goes out: Nothing (i.e., None). Side effects: See draw_squares_from_circle.pdf in this project for pictures that may help you better understand the following specification: First draws the given rg.Circle on the given rg.RoseWindow. Then draws n rg.Squares on the given rg.RoseWindow, such that: -- The first rg.Square circumscribes the given rg.Circle. -- Each subsequent rg.Square has its upper-left quarter on top of the lower-right quarter of the previous rg.Square, so that the squares form an overlapping sequence that goes down and to the right. Must ** render ** but ** NOT close ** the window. Type hints: :type n: int :type circle: rg.Circle :type window: rg.RoseWindow """ # ------------------------------------------------------------------ # DONE: 2. Implement and test this function. # Tests have been written for you (above). # # CONSIDER using the ACCUMULATOR IN GRAPHICS pattern, # as in draw_row_of_circles in m1e, # instead of directly using the loop variable. # #################################################################### # HINT: To figure out the code that computes the necessary # positions of each square, # ** FIRST DO A CONCRETE EXAMPLE BY HAND! ** #################################################################### # ------------------------------------------------------------------ r = circle.radius point = circle.center up_left_x = point.x - r up_left_y = point.y - r bot_right_x = point.x + r bot_right_y = point.y + r circle.attach_to(window) for k in range(n): top_left = rg.Point(up_left_x + (k * r), up_left_y + (k * r)) bot_right = rg.Point(bot_right_x + (k * r), bot_right_y + (k * r)) rectangle = rg.Rectangle(top_left, bot_right) rectangle.attach_to(window) window.render(.05)
def draw_lines_from_rectangles(r1, r2, n, window): """ What comes in: Four arguments: -- Two rg.Rectangles. -- A positive integer n. -- An rg.RoseWindow. What goes out: Nothing (i.e., None). Side effects: See draw_lines_from_rectangles.pdf in this project for pictures that may help you better understand the following specification: First draws the given rg.Rectangles on the given rg.RoseWindow. Then draws n rg.Lines on the given rg.RoseWindow, such that: -- The 1st rg.Line goes from the center of one of the 1st rg.Rectangle to the center of the 2nd rg.Rectangle. -- The 2nd rg.Line goes from the lower-left corner of the 1st rg.Rectangle and is parallel to the 1st rg.Line, with the same length and direction as the 1st rg.Line. -- Subsequent rg.Lines are shifted from the previous rg.Line in the same way that the 2nd rg.Line is shifted from the 1st. -- Each of the rg.Lines has thickness 5. -- The colors of the rg.Lines alternate, as follows: - The 1st, 3rd, 5th, ... rg.Line has color R1_color - The 2nd, 4th, 6th, ... rg.Line has color R2_color where - R1_color is the outline color of the 1st rg.Rectangle - R2_color is the outline color of the 2nd rg.Rectangle Must ** render ** but ** NOT close ** the window. Type hints: :type rectangle1: rg.Rectangle :type rectangle2: rg.Rectangle :type n: int :type window: rg.RoseWindow """ # ------------------------------------------------------------------ # TODO: 5. Implement and test this function. # Tests have been written for you (above). # # CONSIDER using the ACCUMULATOR IN GRAPHICS pattern, # as in draw_row_of_circles in m1e, # instead of directly using the loop variable. # #################################################################### # HINT: To figure out the code that computes the necessary # endpoints for each line, # ** FIRST DO A CONCRETE EXAMPLE BY HAND! ** #################################################################### # ------------------------------------------------------------------ r1.attach_to(window) r2.attach_to(window) line = rg.Line(r1.get_center(),r2.get_center()) line.color= r1.outline_color line.attach_to(window) w = r1.get_width()/2 h = r1.get_height()/2 a = w b = h for k in range(n-1): start = rg.Point(r1.get_center().x - a, r1.get_center().y + b) end = rg.Point(r2.get_center().x - a, r2.get_center().y + b) linemod = rg.Line(start,end) if k % 2 == 0: linemod.color = r2.outline_color else: linemod.color = r1.outline_color a =a + w b = b + h linemod.attach_to(window) window.render()
def many_hourglasses(window, square, m, colors): """ See many_hourglasses_picture.pdf in this project for pictures that may help you better understand the following specification: Displays m rectangles, where: -- Each rectangle has an hourglass of circles inside it, per the hourglass function above. -- The circles in the hourglasses are all the same size. -- The leftmost rectangle is the given square, and it contains an hourglass with a single circle that fills the square. -- Each successive rectangle is immediately to the right of the previous rectangle, and each contains an hourglass with the hourglass' n being one greater than the n used for the previous rectangle. -- The colors for the hourglass figures use the given sequence of colors, "wrapping" if m exceeds the length of the sequence. Preconditions: :type window: rg.RoseWindow :type square: rg.Square :type m: int :type colors: (list | tuple) of str where m is positive and colors is a sequence of strings, each of which denotes a color that rosegraphics understands. """ # ------------------------------------------------------------------ # DONE: 3. Implement and test this function. # We provided some tests for you (above). # ------------------------------------------------------------------ #################################################################### # IMPORTANT: # 1. Partial credit if you draw JUST the rectangles. # 2. No additional credit unless you CALL the hourglass function # in the PREVIOUS problem appropriately # to draw the hourglass figures. #################################################################### # ------------------------------------------------------------------ # DIFFICULTY AND TIME RATINGS (see top of this file for explanation) # DIFFICULTY: 7 (assuming that you already have # a correct "hourglass" function above) # TIME ESTIMATE: 20 minutes (warning: this problem is challenging) # ------------------------------------------------------------------ center = square.center centerx = square.center.x centery = square.center.y length = square.length_of_each_side original_length = length ul = rg.Point(square.center.x - (original_length / 2), square.center.y - (original_length / 2)) original_ul = ul lr = rg.Point(square.center.x + (original_length / 2), square.center.y + (original_length / 2)) original_lr = lr ulx = ul.x original_ulx = ulx uly = ul.y original_uly = uly lrx = lr.x original_lrx = lrx lry = lr.y original_lry = lry index = 0 for k in range(m): rect = rg.Rectangle(rg.Point(ulx, uly), rg.Point(lrx, lry)) rect.attach_to(window) hourglass(window, k + 1, rect.get_center(), length / 2, colors[index]) window.render() index = index + 1 if index == len(colors): index = 0 ulx = ulx + (k + 1) * length uly = uly - (length) * (1 / 1.15) lrx = lrx + ((1 + (k + 1)) * length) lry = lry + length * (1 / 1.15)
def hourglass(window, n, point, radius, color): """ See hourglass_picture.pdf in this project for pictures that may help you better understand the following specification: Displays an "hourglass" shape of circles in the given window. -- Each circle has the given radius and given color. -- Each circle has a horizontal line drawn through it. -- The middlemost of the circles is centered at the given point. -- There is a single circle in that middlemost row. -- There are n rows (including the middlemost row) of circles going UP from the middlemost circle. -- There are n rows (including the middlemost row) of circles going DOWN from the middlemost circle. -- Each circle barely touches its neighbor circles. Preconditions: :type window: rg.RoseWindow :type n: int :type point: rg.Point :type radius: int :type color: str where n and radius are positive and color is a string that denotes a color that rosegraphics understands. """ # ------------------------------------------------------------------ # DONE: 2. Implement and test this function. # We provided some tests for you (above). # ------------------------------------------------------------------ #################################################################### # BONUS: Avoid replicated code if you can. Hint: You are allowed # to define an additional function(s) if you wish. #################################################################### # ------------------------------------------------------------------ # DIFFICULTY AND TIME RATINGS (see top of this file for explanation) # DIFFICULTY: 8 # TIME ESTIMATE: 25 minutes (warning: this problem is challenging) # ------------------------------------------------------------------ original_center_x = point.x original_center_y = point.y center_x = original_center_x center_y = original_center_y for k in range(n - 1): for i in range(n - k): upper_circles = rg.Circle( rg.Point(center_x - (n - 1) * radius, center_y - (n - 1) * math.sqrt(3) * radius), radius) upper_circles.fill_color = color upper_circles.attach_to(window) upper_line = rg.Line( rg.Point(center_x - (n - 1) * radius - radius, center_y - (n - 1) * math.sqrt(3) * radius), rg.Point(center_x - (n - 1) * radius + radius, center_y - (n - 1) * math.sqrt(3) * radius)) upper_line.attach_to(window) window.render() center_x = center_x + 2 * radius center_x = original_center_x + ((k + 1) * radius) center_y = original_center_y + ((k + 1) * math.sqrt(3) * radius) center_circle = rg.Circle(rg.Point(original_center_x, original_center_y), radius) center_circle.fill_color = color center_line = rg.Line( rg.Point(original_center_x - radius, original_center_y), rg.Point(original_center_x + radius, original_center_y)) center_circle.attach_to(window) center_line.attach_to(window) window.render() new_original_center_x = center_circle.center.x new_original_center_y = center_circle.center.y new_center_x = new_original_center_x new_center_y = new_original_center_y for j in range(n - 1): for l in range(j + 2): lower_circles = rg.Circle( rg.Point(new_center_x - radius, new_center_y + math.sqrt(3) * radius), radius) lower_circles.fill_color = color lower_line = rg.Line( rg.Point(new_center_x - radius - radius, new_center_y + math.sqrt(3) * radius), rg.Point(new_center_x - radius + radius, new_center_y + math.sqrt(3) * radius)) lower_circles.attach_to(window) lower_line.attach_to(window) window.render() new_center_x = new_center_x + 2 * radius new_center_x = new_original_center_x - (j + 1) * radius new_center_y = new_original_center_y + (j + 1) * math.sqrt(3) * radius
def run_test_even_better_draw_circles(): even_better_draw_circles(5, 15, rg.Point(200, 300), 'blue', 10) even_better_draw_circles(15, 5, rg.Point(100, 150), 'red', 15) even_better_draw_circles(3, 30, rg.Point(200, 200), 'orange', 5)
def draw_lines_from_rectangles(rectangle1, rectangle2, n, window): """ What comes in: Four arguments: -- Two rg.Rectangles. -- A positive integer n. -- An rg.RoseWindow. What goes out: Nothing (i.e., None). Side effects: See draw_lines_from_rectangles.pdf in this project for pictures that may help you better understand the following specification: First draws the given rg.Rectangles on the given rg.RoseWindow. Then draws n rg.Lines on the given rg.RoseWindow, such that: -- The 1st rg.Line goes from the center of one of the 1st rg.Rectangle to the center of the 2nd rg.Rectangle. -- The 2nd rg.Line goes from the lower-left corner of the 1st rg.Rectangle and is parallel to the 1st rg.Line, with the same length and direction as the 1st rg.Line. -- Subsequent rg.Lines are shifted from the previous rg.Line in the same way that the 2nd rg.Line is shifted from the 1st. -- Each of the rg.Lines has thickness 5. -- The colors of the rg.Lines alternate, as follows: - The 1st, 3rd, 5th, ... rg.Line has color R1_color - The 2nd, 4th, 6th, ... rg.Line has color R2_color where - R1_color is the outline color of the 1st rg.Rectangle - R2_color is the outline color of the 2nd rg.Rectangle Must ** render ** but ** NOT close ** the window. Type hints: :type rectangle1: rg.Rectangle :type rectangle2: rg.Rectangle :type n: int :type window: rg.RoseWindow """ rectangle1.attach_to(window) rectangle2.attach_to(window) window.render() p1 = rectangle1.get_center() p2 = rectangle2.get_center() ln = rg.Line(p1, p2) ln.color = rectangle1.outline_color ln.thickness = 5 ln.attach_to(window) window.render() point_corner = rectangle1.get_lower_left_corner() x_difference = (point_corner.x - p1.x) y_difference = (point_corner.y - p1.y) new_1 = rg.Point(p1.x + x_difference, p1.y + y_difference) new_2 = rg.Point(p2.x + x_difference, p2.y + y_difference) for k in range(n - 1): lnf = rg.Line(new_1, new_2) if ((k + 1) % 2) == 0: lnf.color = rectangle1.outline_color else: lnf.color = rectangle2.outline_color lnf.thickness = 5 lnf.attach_to(window) window.render() new_1.x += x_difference new_1.y += y_difference new_2.x += x_difference new_2.y += y_difference
def run_test_problem2(): """ Tests the problem2 function. """ print() print('--------------------------------------------------') print('Testing the problem2 function:') print(' See the graphics windows that pop up.') print('--------------------------------------------------') # TWO tests on ONE window. title = 'Tests 1 and 2 of problem2' window = rg.RoseWindow(400, 250, title) # Test 1: line = rg.Line(rg.Point(30, 25), rg.Point(80, 200)) other_line = rg.Line(rg.Point(130, 60), rg.Point(90, 100)) line.thickness = 5 line.color = 'forest green' other_line.color = 'red' problem2(line, other_line, 5, window) window.render() # In case students forget to do so. window.continue_on_mouse_click() # Test 2: line = rg.Line(rg.Point(350, 100), rg.Point(300, 250)) other_line = rg.Line(rg.Point(250, 20), rg.Point(375, 100)) line.thickness = 1 other_line.thickness = 5 line.color = 'blue' other_line.color = 'black' problem2(line, other_line, 3, window) window.render() # In case students forget to do so. window.close_on_mouse_click() # A third test on ANOTHER window. title = 'Test 3 of problem2' window = rg.RoseWindow(300, 300, title) # Test 3: line = rg.Line(rg.Point(100, 50), rg.Point(200, 50)) other_line = rg.Line(rg.Point(50, 200), rg.Point(200, 200)) line.thickness = 8 other_line.thickness = 2 line.color = 'magenta' other_line.color = 'black' problem2(line, other_line, 8, window) window.render() # In case students forget to do so. window.close_on_mouse_click()
def run_test_problem3a(): """ Tests the problem3a function. """ # ------------------------------------------------------------------ # DONE: 2. Implement this TEST function. # It TESTS the problem1a function defined below. # Include at least ** 5 ** tests (we wrote four for you). # ------------------------------------------------------------------ # ------------------------------------------------------------------ # DIFFICULTY AND TIME RATINGS (see top of this file for explanation) # DIFFICULTY: 4 # TIME ESTIMATE: 10 to 15 minutes. # ------------------------------------------------------------------ # Window 1: title = 'Problem 3a. Test 1: Start at (30, 30), 6 lines' window1 = rg.RoseWindow(350, 200, title) # Test 1 (it is on window 1): point = rg.Point(30, 30) expected = 36 answer = problem3a(window1, point, 6) print() print('Test 1 expected:', expected) print(' actual: ', answer) window1.close_on_mouse_click() # Window 2: title = 'Problem 3a. Test 2: Start at (80, 10), 9 lines.' title += ' Test 3: Start at (30, 50), 3 lines.' window2 = rg.RoseWindow(550, 200, title) # Test 2 (it is on window 2): point = rg.Point(80, 10) expected = 75 answer = problem3a(window2, point, 9) print() print('Test 2 expected:', expected) print(' actual: ', answer) # Test 3 (it is also on window 2): point = rg.Point(30, 50) expected = 9 answer = problem3a(window2, point, 3) print() print('Test 3 expected:', expected) print(' actual: ', answer) window2.close_on_mouse_click() # Window 3: title = 'Problem 3a. Test 4: Start at (30, 30), 20 lines' window3 = rg.RoseWindow(450, 300, title) # Test 4 (it is on window 3): point = rg.Point(30, 30) expected = 218 answer = problem3a(window3, point, 20) print() print('Test 4 expected:', expected) print(' actual: ', answer) # Test 4 (it is on window 3): point = rg.Point(30, 30) expected = 218 answer = problem3a(window3, point, 20) print() print('Test 4 expected:', expected) print(' actual: ', answer) window3.close_on_mouse_click()
def problem3b(m, point1): """ See problem3b_picture.pdf in this project for pictures that may help you better understand the following specification: What comes in: -- A positive integer m. -- An rg.Point. What goes out: -- Returns the sum of the thicknesses of ALL of the lines drawn (over all m sets of lines). Side effects: -- Constructs and displays an rg.RoseWindow that is 400 wide by 650 tall. -- Draws, on the rg.RoseWindow, m SETS of lines, where: -- Each SET of lines is drawn *** by a call to ** problem3a **. *** -- The first set has 3 lines that start at point1 (the given point). -- The second set has 5 lines that start 60 pixels directly below point1. -- The third set has 7 lines that start 120 pixels directly below point1. -- The fourth set has 9 lines that start 180 pixels directly below point1. -- etc until m SETS of lines are drawn (where m is given). -- Each set of lines should have widths (thicknesses) per problem3a. -- Waits for the user to click the mouse (and displays an appropriate message prompting the user to do so), then closes the window. Type hints: :type m: int :type point1: rg.Point """ # ------------------------------------------------------------------------- # DONE: 4. Implement and test this function. # Tests have been written for you (above). # ########################################################################### # IMPORTANT: # ** For full credit you must appropriately use (call) # ** the problem3a function that you implemented above. ########################################################################### # ------------------------------------------------------------------------- # DIFFICULTY AND TIME RATINGS (see top of this file for explanation) # DIFFICULTY: 8 or 9 # TIME ESTIMATE: 20 to 30 minutes. # ------------------------------------------------------------------------- window=rg.RoseWindow(400,650) sum=0 for k in range(m): num=3+(2*k) Point=rg.Point(point1.x, point1.y+(60*k)) sum=sum+ problem3a(window,Point,num) window.render() window.close_on_mouse_click() return sum
def draw_circles_from_rectangle(m, n, rectangle, window): """ What comes in: Four arguments: -- Positive integers m and n. -- An rg.Rectangle. -- An rg.RoseWindow. What goes out: Nothing (i.e., None). Side effects: See draw_circles_from_rectangle.pdf in this project for pictures that may help you better understand the following specification: First draws the given rg.Rectangle on the given rg.RoseWindow. Then draws m rg.Circles on the given rg.RoseWindow, such that: -- The diameter of each rg.Circle is the same as the height of the given rg.Rectangle. -- The first rg.Circle is immediately to the left of the given rg.Rectangle -- Each subsequent rg.Circle is immediately to the left of the previous rg.Circle, so that the circles form a row that goes to the left. -- Each rg. Circle has the same fill_color as the given rg.Rectangle (and has no outline_color). Then draws n rg.Circles on the given RoseWindow, such that: -- The diameter of each rg.Circle is the same as the width of the given rg.Rectangle. -- The first rg.Circle is immediately above the given rg.Rectangle -- Each subsequent rg.Circle is immediately above the previous rg.Circle, so that the circles form a column that goes up. -- Each rg.Circle has the same outline_color as the given rg.Rectangle (and has no fill_color). Must ** render ** but ** NOT close ** the window. Type hints: :type m: int :type n: int :type rectangle: rg.Rectangle :type window: rg.RoseWindow """ # ------------------------------------------------------------------ # DONE: 4. Implement and test this function. # Tests have been written for you (above). # # CONSIDER using the ACCUMULATOR IN GRAPHICS pattern, # as in draw_row_of_circles in m1e, # instead of directly using the loop variable. # #################################################################### # HINT: To figure out the code that computes the necessary # positions of each circle, # ** FIRST DO A CONCRETE EXAMPLE BY HAND! ** #################################################################### # ------------------------------------------------------------------ corner_1_x = rectangle.corner_1.x corner_1_y = rectangle.corner_1.y corner_2_x = rectangle.corner_2.x corner_2_y = rectangle.corner_2.y r_x = abs(corner_2_x - corner_1_x)/2 r_y = abs(corner_2_y - corner_1_y)/2 if corner_1_x < corner_2_x: corner_x = corner_1_x else: corner_x = corner_2_x if corner_1_y > corner_2_y: corner_y = corner_2_y else: corner_y = corner_1_y center_x = rg.Point(corner_x - r_y, corner_y + r_y) center_y = rg.Point(corner_x + r_x, corner_y - r_x) rectangle.attach_to(window) for k in range(m): circle1 = rg.Circle(center_x, r_y) circle1.fill_color = rectangle.fill_color circle1.attach_to(window) center_x = rg.Point(center_x.x - 2 * r_y, center_x.y) for k in range(n): circle2 = rg.Circle(center_y, r_y) circle2.outline_color = rectangle.outline_color circle2.attach_to(window) center_y = rg.Point(center_y.x, center_y.y - 2 * r_x) window.render()
def run_test_swap_colors(): """ Tests the swap_colors function. """ print() print('--------------------------------------------------') print('Testing the swap_colors function:') print('--------------------------------------------------') # ------------------------------------------------------------------ # Test 1: Note that it tests both: # -- what was SUPPOSED to be mutated (fill_color) and # -- what was NOT supposed to be mutated (all else). # The code passes this test if the expected value printed # is the same as the actual value printed. # ------------------------------------------------------------------ circle = rg.Circle(rg.Point(100, 150), 50) circle.fill_color = 'blue' rectangle = rg.Rectangle(rg.Point(200, 30), rg.Point(350, 150)) rectangle.fill_color = 'green' expected_c = 'Circle: center=(100, 150), radius=50,' expected_c += ' fill_color=green, outline_color=black,' expected_c += ' outline_thickness=1.' expected_r = 'Rectangle: corner_1=(200, 30), corner_2=(350, 150),' expected_r += ' fill_color=blue, outline_color=black,' expected_r += ' outline_thickness=1.' swap_colors(circle, rectangle) print() print('Expected circle after the function call:') print(expected_c) print('Actual circle after the function call:') print(circle) print() print('Expected rectangle after the function call:') print(expected_r) print('Actual rectangle after the function call:') print(rectangle) # ------------------------------------------------------------------ # Test 2: This is a VISUAL test. # The code passes this test if the objects are drawn per the test. # # Here, that means that when the window pauses and asks the user # to press any key to continue: # -- the circle is black_filled and # -- the rectangle is red_filled # and then when the user presses a key and the window pauses # again, now the reverse is true: # -- the circle is red_filled and # -- the rectangle is black_filled. # ------------------------------------------------------------------ title = 'The code passes the test if the fill colors of the circle' title += ' and rectangle get SWAPPED.' window = rg.RoseWindow(700, 400, title) circle = rg.Circle(rg.Point(100, 50), 40) circle.fill_color = 'black' circle.attach_to(window) rectangle = rg.Rectangle(rg.Point(200, 280), rg.Point(350, 350)) rectangle.fill_color = 'red' rectangle.attach_to(window) msg1 = 'At this point, the circle should be filled with BLACK\n' msg1 += 'and the rectangle should be filled with RED' message = rg.Text(rg.Point(400, 100), msg1) message.attach_to(window) # At this point, the CIRCLE should be filled with BLACK # and the RECTANGLE filled with RED. window.render() window.continue_on_mouse_click() swap_colors(circle, rectangle) # At this point, the CIRCLE should be filled with RED # and the RECTANGLE filled with BLACK. msg2 = 'Now, the circle should be filled with RED\n' msg2 += 'and the rectangle should be filled with BLACK.\n' msg2 += 'If so, and if nothing else changed,\n' msg2 += 'the code passed this test.' message.text = msg2 window.render() window.close_on_mouse_click()
def draw_lines_from_rectangles(rectangle1, rectangle2, n, window): """ What comes in: Four arguments: -- Two rg.Rectangles. -- A positive integer n. -- An rg.RoseWindow. What goes out: Nothing (i.e., None). Side effects: See draw_lines_from_rectangles.pdf in this project for pictures that may help you better understand the following specification: First draws the given rg.Rectangles on the given rg.RoseWindow. Then draws n rg.Lines on the given rg.RoseWindow, such that: -- The 1st rg.Line goes from the center of one of the 1st rg.Rectangle to the center of the 2nd rg.Rectangle. -- The 2nd rg.Line goes from the lower-left corner of the 1st rg.Rectangle and is parallel to the 1st rg.Line, with the same length and direction as the 1st rg.Line. -- Subsequent rg.Lines are shifted from the previous rg.Line in the same way that the 2nd rg.Line is shifted from the 1st. -- Each of the rg.Lines has thickness 5. -- The colors of the rg.Lines alternate, as follows: - The 1st, 3rd, 5th, ... rg.Line has color R1_color - The 2nd, 4th, 6th, ... rg.Line has color R2_color where - R1_color is the outline color of the 1st rg.Rectangle - R2_color is the outline color of the 2nd rg.Rectangle Must ** render ** but ** NOT close ** the window. Type hints: :type rectangle1: rg.Rectangle :type rectangle2: rg.Rectangle :type n: int :type window: rg.RoseWindow """ # ------------------------------------------------------------------ # DONE: 5. Implement and test this function. # Tests have been written for you (above). # # CONSIDER using the ACCUMULATOR IN GRAPHICS pattern, # as in draw_row_of_circles in m1e, # instead of directly using the loop variable. # #################################################################### # HINT: To figure out the code that computes the necessary # endpoints for each line, # ** FIRST DO A CONCRETE EXAMPLE BY HAND! ** #################################################################### # ------------------------------------------------------------------ rectangle1.attach_to(window) corner_1_x = rectangle1.corner_1.x corner_2_x = rectangle1.corner_2.x corner_1_y = rectangle1.corner_1.y corner_2_y = rectangle1.corner_2.y center1_x = abs(corner_1_x - corner_2_x) / 2 center1_y = abs(corner_1_y - corner_2_y) / 2 if corner_1_x < corner_2_x: val_x = corner_1_x else: val_x = corner_2_x if corner_1_y > corner_2_y: val_y = corner_2_y else: val_y = corner_1_y center_1 = rg.Point(val_x + center1_x, val_y + center1_y) rectangle2.attach_to(window) corner2_1_x = rectangle2.corner_1.x corner2_2_x = rectangle2.corner_2.x corner2_1_y = rectangle2.corner_1.y corner2_2_y = rectangle2.corner_2.y center2_x = abs(corner2_1_x - corner2_2_x) / 2 center2_y = abs(corner2_1_y - corner2_2_y) / 2 if corner2_1_x < corner2_2_x: val2_x = corner2_1_x else: val2_x = corner2_2_x if corner2_1_y > corner2_2_y: val2_y = corner2_2_y else: val2_y = corner2_1_y center_2 = rg.Point(val2_x + center2_x, val2_y + center2_y) for k in range(n): line = rg.Line(center_1, center_2) if k % 2 == 0: line.color = rectangle1.outline_color else: line.color = rectangle2.outline_color line.thickness = 5 line.attach_to(window) center_1 = rg.Point(center_1.x - center1_x, center_1.y + center1_y) center_2 = rg.Point(center_2.x - center2_x, center_2.y + center2_y) window.render()
def many_hourglasses(window, square, m, colors): """ See many_hourglasses_picture.pdf in this project for pictures that may help you better understand the following specification: Displays m rectangles, where: -- Each rectangle has an hourglass of circles inside it, per the hourglass function above. -- The circles in the hourglasses are all the same size. -- The leftmost rectangle is the given square, and it contains an hourglass with a single circle that fills the square. -- Each successive rectangle is immediately to the right of the previous rectangle, and each contains an hourglass with the hourglass' n being one greater than the n used for the previous rectangle. -- The colors for the hourglass figures use the given sequence of colors, "wrapping" if m exceeds the length of the sequence. Preconditions: :type window: rg.RoseWindow :type square: rg.Square :type m: int :type colors: (list | tuple) of str where m is positive and colors is a sequence of strings, each of which denotes a color that rosegraphics understands. """ # ------------------------------------------------------------------ # Done: 3. Implement and test this function. # We provided some tests for you (above). # ------------------------------------------------------------------ #################################################################### # IMPORTANT: # 1. Partial credit if you draw JUST the rectangles. # 2. No additional credit unless you CALL the hourglass function # in the PREVIOUS problem appropriately # to draw the hourglass figures. #################################################################### # ------------------------------------------------------------------ # DIFFICULTY AND TIME RATINGS (see top of this file for explanation) # DIFFICULTY: 7 (assuming that you already have # a correct "hourglass" function above) # TIME ESTIMATE: 20 minutes (warning: this problem is challenging) # ------------------------------------------------------------------ radius = square.length_of_each_side / 2 point = square.center topleftx = point.x - radius toplefty = point.y - radius bottomrightx = point.x + radius bottomrighty = point.y + radius topleft = rg.Point(topleftx, toplefty) bottomright = rg.Point(bottomrightx, bottomrighty) yshift = (2 * radius**2 + radius**2)**0.5 quad = rg.Rectangle(bottomright, topleft) for k in range(m): quad.attach_to(window) hourglass(window, k + 1, point, radius, colors[k % 3]) topleftx = bottomrightx toplefty += -yshift bottomrightx += (k + 2) * (2 * radius) bottomrighty += yshift topleft = rg.Point(topleftx, toplefty) bottomright = rg.Point(bottomrightx, bottomrighty) quad = rg.Rectangle(topleft, bottomright) point.x = (topleftx + bottomrightx) / 2 point.y = (toplefty + bottomrighty) / 2 window.render()
def draw_circles_from_rectangle(m, n, rectangle, window): """ What comes in: Four arguments: -- Positive integers m and n. -- An rg.Rectangle. -- An rg.RoseWindow. What goes out: Nothing (i.e., None). Side effects: See draw_circles_from_rectangle.pdf in this project for pictures that may help you better understand the following specification: First draws the given rg.Rectangle on the given rg.RoseWindow. Then draws m rg.Circles on the given rg.RoseWindow, such that: -- The diameter of each rg.Circle is the same as the height of the given rg.Rectangle. -- The first rg.Circle is immediately to the left of the given rg.Rectangle -- Each subsequent rg.Circle is immediately to the left of the previous rg.Circle, so that the circles form a row that goes to the left. -- Each rg. Circle has the same fill_color as the given rg.Rectangle (and has no outline_color). Then draws n rg.Circles on the given RoseWindow, such that: -- The diameter of each rg.Circle is the same as the width of the given rg.Rectangle. -- The first rg.Circle is immediately above the given rg.Rectangle -- Each subsequent rg.Circle is immediately above the previous rg.Circle, so that the circles form a column that goes up. -- Each rg.Circle has the same outline_color as the given rg.Rectangle (and has no fill_color). Must ** render ** but ** NOT close ** the window. Type hints: :type m: int :type n: int :type rectangle: rg.Rectangle :type window: rg.RoseWindow """ # ------------------------------------------------------------------ # DONE: 4. Implement and test this function. # Tests have been written for you (above). # # CONSIDER using the ACCUMULATOR IN GRAPHICS pattern, # as in draw_row_of_circles in m1e, # instead of directly using the loop variable. # #################################################################### # HINT: To figure out the code that computes the necessary # positions of each circle, # ** FIRST DO A CONCRETE EXAMPLE BY HAND! ** #################################################################### # ------------------------------------------------------------------ rectangle.attach_to(window) height = rectangle.get_height() center = rectangle.get_center() width = rectangle.get_width() radius = height/2 start = rectangle.get_upper_left_corner() for _ in range(m): circle = rg.Circle(rg.Point(start.x -radius, center.y), radius) circle.fill_color = rectangle.fill_color circle.attach_to(window) start.x = start.x - 2*radius window.render() for _ in range(n): circle = rg.Circle(rg.Point(center.x,start.y-width/2), width/2) circle.outline_color= rectangle.outline_color circle.attach_to(window) start.y = start.y - width window.render()
def hourglass(window, n, point, radius, color): """ See hourglass_picture.pdf in this project for pictures that may help you better understand the following specification: Displays an "hourglass" shape of circles in the given window. -- Each circle has the given radius and given color. -- Each circle has a horizontal line drawn through it. -- The middlemost of the circles is centered at the given point. -- There is a single circle in that middlemost row. -- There are n rows (including the middlemost row) of circles going UP from the middlemost circle. -- There are n rows (including the middlemost row) of circles going DOWN from the middlemost circle. -- Each circle barely touches its neighbor circles. Preconditions: :type window: rg.RoseWindow :type n: int :type point: rg.Point :type radius: int :type color: str where n and radius are positive and color is a string that denotes a color that rosegraphics understands. """ # ------------------------------------------------------------------ # Done: 2. Implement and test this function. # We provided some tests for you (above). # ------------------------------------------------------------------ #################################################################### # BONUS: Avoid replicated code if you can. Hint: You are allowed # to define an additional function(s) if you wish. #################################################################### # ------------------------------------------------------------------ # DIFFICULTY AND TIME RATINGS (see top of this file for explanation) # DIFFICULTY: 8 # TIME ESTIMATE: 25 minutes (warning: this problem is challenging) # ------------------------------------------------------------------ original = rg.Point(point.x, point.y) for k in range(1, n + 1): for j in range(k): circle = rg.Circle(point, radius) circle.fill_color = color circle.attach_to(window) rightside = point.x + radius leftside = point.x - radius start = rg.Point(rightside, point.y) finish = rg.Point(leftside, point.y) line = rg.Line(start, finish) line.attach_to(window) point.x += -(2 * radius) point.x += (3 + 2 * j) * radius point.y += (2 * radius**2 + radius**2)**0.5 point = original for k in range(1, n + 1): for j in range(k): circle = rg.Circle(point, radius) circle.fill_color = color circle.attach_to(window) rightside = point.x + radius leftside = point.x - radius start = rg.Point(rightside, point.y) finish = rg.Point(leftside, point.y) line = rg.Line(start, finish) line.attach_to(window) point.x += -(2 * radius) point.x += (3 + 2 * j) * radius point.y += -(2 * radius**2 + radius**2)**0.5 window.render()
def test_draw_lines_from_rectangles(): """ Tests the draw_lines_from_rectangles function. """ print() print('--------------------------------------------------') print('Testing the draw_lines_from_rectangles function:') print(' See the graphics windows that pop up.') print('--------------------------------------------------') # TWO tests on ONE window. title = 'Tests 1 & 2 of DRAW_LINES_FROM_RECTANGLES:' title += ' 5 lines, 8 lines!' window1 = rg.RoseWindow(900, 400, title) rectangle1 = rg.Rectangle(rg.Point(100, 25), rg.Point(150, 125)) rectangle2 = rg.Rectangle(rg.Point(300, 150), rg.Point(400, 175)) rectangle1.outline_color = 'red' rectangle2.outline_color = 'blue' draw_lines_from_rectangles(rectangle1, rectangle2, 5, window1) rectangle1 = rg.Rectangle(rg.Point(870, 30), rg.Point(750, 100)) rectangle2 = rg.Rectangle(rg.Point(700, 90), rg.Point(650, 60)) rectangle2.outline_color = 'green' draw_lines_from_rectangles(rectangle1, rectangle2, 8, window1) window1.close_on_mouse_click() # A third test on ANOTHER window. title = 'Test 3 of DRAW_LINES_FROM_RECTANGLES: 11 lines!' window2 = rg.RoseWindow(700, 700, title) rectangle1 = rg.Rectangle(rg.Point(550, 200), rg.Point(650, 100)) rectangle2 = rg.Rectangle(rg.Point(600, 50), rg.Point(650, 75)) rectangle1.outline_color = 'brown' rectangle2.outline_color = 'cyan' rectangle2.outline_thickness = 10 draw_lines_from_rectangles(rectangle1, rectangle2, 11, window2) window2.close_on_mouse_click()
def problem3a(window, point, n): """ See problem3a_picture.pdf in this project for pictures that may help you better understand the following specification: What comes in: -- An rg.RoseWindow. -- An rg.Point. -- A nonnegative integer n. What goes out: -- Returns the sum of the thicknesses of the rg.Lines that are drawn as described in the Side effects (below). Side effects: Draws n rg.Lines on the given rg.RoseWindow, as follows: -- There are the given number (n) of rg.Lines. -- Each rg.Line is vertical and has length 50. (All units are pixels.) -- The top of the first (leftmost) rg.Line is at the given rg.Point. -- Each successive rg.Line is 20 pixels to the right and 10 pixels down from the previous rg.Line. -- The first rg.Line has thickness 1. -- Each successive rg.Line has thickness 2 greater than the rg.Line to its left, but no greater than 13. (So once a rg.Line has thickness 13, it and all the rg.Lines to its right have thickness 13.) Type hints: :type window: rg.RoseWindow :type point: rg.Point :type n: int """ # ------------------------------------------------------------------ # DONE: 3. Implement and test this function. # Note that you should write its TEST function first (above). # ------------------------------------------------------------------ # ------------------------------------------------------------------ # DIFFICULTY AND TIME RATINGS (see top of this file for explanation) # DIFFICULTY: 7 or 8 # TIME ESTIMATE: 20 to 35 minutes. # ------------------------------------------------------------------ oend = rg.Point(point.x, point.y + 50) original = rg.Line(point, oend) original.attach_to(window) thickness = 1 sum = 1 for _ in range(n - 1): point.x = point.x + 20 point.y = point.y + 10 newpoint = rg.Point(point.x, point.y) oend.x = oend.x + 20 oend.y = oend.y + 10 newend = rg.Point(oend.x, oend.y) new = rg.Line(newpoint, newend) new.attach_to(window) if thickness < 13: thickness = thickness + 2 new.thickness = thickness sum = sum + new.thickness window.render() return sum
def main(): # ------------------------------------------------------------------ # 1. Constructs an rg.Point, assigning its instance variables values. # Then assigns an instance variable in the object a new value, # thus MUTATING the OBJECT, because # one of its INSTANCE VARIABLES was ASSIGNED a new value. # ------------------------------------------------------------------ print('Showing mutation via assignment:') point = rg.Point(45, 100) print('Before:', point) point.y = 33 # The next line shows that the INSIDES of point has changed. print('After: ', point) # Look at what gets printed! # ------------------------------------------------------------------ # 2. Mutates the object again, this time from within a function call # ------------------------------------------------------------------ print() print('Showing mutation via a function call') print('(which does assignment):') print('Before:', point) mutate_point(point) # The next line shows that the INSIDES of point has changed. print('After: ', point) # Look at what gets printed! # ------------------------------------------------------------------ # 3. Assigns another variable to refer to the same rg.Point # to which the point variable refers. # That creates two NAMES (variables) # that refer to the same OBJECT. # When one mutates, so does the other. # ------------------------------------------------------------------ print() print('Showing two NAMES that refer to the same OBJECT:') point2 = point print('Before:', point, point2) point2.x = 100 print('After: ', point, point2) # Note that point.x ALSO changed # ------------------------------------------------------------------ # 4. Re-assigns the point variable to refer to another rg.Point. # This is ASSIGNMENT and NOT mutation. # ------------------------------------------------------------------ print() print('RE-ASSIGNING an object is NOT MUTATING the OBJECT:') print('Before:', point, point2) point = rg.Point(10, 6) print(point, point2) # Prints the two DIFFERENT rg.Points # ------------------------------------------------------------------ # 5. Shows the difference betwee the is operator # (two things refer to the same place in memory) # and the == operator (two things contain the same data). # ------------------------------------------------------------------ print() print('Shows the difference between two operators') print(' -- a IS b (do a and b refer to the same place in memory?') print(' -- a == b (do a and b have the same data?)') print('Predict what will get printed by the following, if you can.') print() print('First, two Points are constructed. See IS vs == in action:') point3 = rg.Point(100, 20) point4 = rg.Point(100, 20) print() print('Before: point3 and point4 are:', point3, point4) print('T or F: point3 is point4?', point3 is point4) print('T or F: point3 == point4?', point3 == point4) point3.fill_color = 'blue' print() print('After: point3 and point4 are:', point3, point4) print('Fillcolors are:', point3.fill_color, point4.fill_color) print('T or F: point3 is point4?', point3 is point4) print('T or F: point3 == point4?', point3 == point4) print() print('Second, another Point (point5) is assigned') print('to one of the existing ones (point3).') print() print('Here is the IS operator:') point5 = point3 print('points3, 4 and 5 are:', point3, point4, point5) print('Fillcolors are:', point3.fill_color, point4.fill_color, point5.fill_color) print('T or F: point3 is point5?', point3 is point5) print('T or F: point3 is point4?', point3 is point4) print('T or F: point4 is point5?', point4 is point5) print() print('Now the == operator:') print('T or F: point3 == point5?', point3 == point5) print('T or F: point3 == point4?', point3 == point4) print('T or F: point4 == point5?', point4 == point5) print() print('Finally, a tricky one that your instruction will explain:') x = 'hello' y = 'hello' print() print('T or F: "hello" is "hello"?', x is y) print('T or F: "hello" == "hello"?', x == y) x = 1 * x y = 1 * y print() print('T or F: (1 * "hello") is (1 * "hello"?', x is y) print('T or F: (1 * "hello") == (1 * "hello"?', x == y) x = 2 * x y = 2 * y print() print('T or F: (2 * "hello") is (2 * "hello"?', x is y) print('T or F: (2 * "hello") == (2 * "hello"?', x == y)
def run_test_problem3a(): """ Tests the problem3a function. """ # ------------------------------------------------------------------ # DONE: 2. Implement this TEST function. # It TESTS the problem1a function defined below. # Include at least ** 5 ** tests (we wrote four for you). # ------------------------------------------------------------------ # ------------------------------------------------------------------ # DIFFICULTY AND TIME RATINGS (see top of this file for explanation) # DIFFICULTY: 4 # TIME ESTIMATE: 10 to 15 minutes. # ------------------------------------------------------------------ # Window 1: title = 'Problem 3a. Test 1: Start at (30, 30), 6 lines' window1 = rg.RoseWindow(350, 200, title) # Test 1 (it is on window 1): point = rg.Point(30, 30) expected = 36 answer = problem3a(window1, point, 6) print() print('Test 1 expected:', expected) print(' actual: ', answer) window1.close_on_mouse_click() # Window 2: title = 'Problem 3a. Test 2: Start at (80, 10), 9 lines.' title += ' Test 3: Start at (30, 50), 3 lines.' window2 = rg.RoseWindow(550, 200, title) # Test 2 (it is on window 2): point = rg.Point(80, 10) expected = 75 answer = problem3a(window2, point, 9) print() print('Test 2 expected:', expected) print(' actual: ', answer) # Test 3 (it is also on window 2): point = rg.Point(30, 50) expected = 9 answer = problem3a(window2, point, 3) print() print('Test 3 expected:', expected) print(' actual: ', answer) window2.close_on_mouse_click() # Window 3: title = 'Problem 3a. Test 4: Start at (30, 30), 20 lines' window3 = rg.RoseWindow(450, 300, title) # Test 4 (it is on window 3): point = rg.Point(30, 30) expected = 218 answer = problem3a(window3, point, 20) print() print('Test 4 expected:', expected) print(' actual: ', answer) window3.close_on_mouse_click() # ------------------------------------------------------------------ # TO DO: 2 (continued). # Below this comment (or integrated with one of the above tests, # your choice), add 1 more test case of your own choosing. # ------------------------------------------------------------------ title = 'Test 5' window4 = rg.RoseWindow(450, 400, title) # Test 5 point = rg.Point(20, 20) expected = 16 actual = problem3a(window4, point, 4) print('Test 5 expected:', expected) print('Test 5 actual:', actual) window4.close_on_mouse_click()
def run_test_rectangles_from_circles(): """ Tests the rectangles_from_circles function. """ print() print('-----------------------------------------------------------') print('Testing the rectangles_from_circles function:') print('-----------------------------------------------------------') print('See the graphics window that pops up.') print('It should show circles, then the circles circumscribed,') print('then more circles, then the new circles circumscribed too.') print() print('See rectangles_from_circles.pdf in this project') print('for pictures of the anticipated results.') # ------------------------------------------------------------------------- # Test 1 is ALREADY DONE (here). # ------------------------------------------------------------------------- window = rg.RoseWindow(650, 350, 'rectangles_from_circles, two tests') circles = [rg.Circle(rg.Point(50, 80), 40), rg.Circle(rg.Point(150, 50), 30), rg.Circle(rg.Point(300, 100), 50), rg.Circle(rg.Point(220, 70), 60)] circles[0].fill_color = 'red' circles[1].fill_color = 'white' circles[2].fill_color = 'blue' circles[3].fill_color = 'green' # ------------------------------------------------------------------------- # This test calls the draw_shapes function that YOU write, # above. So if your draw_shapes breaks, so will this test. # ------------------------------------------------------------------------- draw_shapes(circles, window) message = 'The circles to be circumscribed are shown above.' message = message + ' Click to continue.' window.continue_on_mouse_click(message) rectangles = rectangles_from_circles(circles) if rectangles is None: print() print('Either you have not yet gotten') print(' to the rectangles_from_circles problem (OK, no problem)') print(' or you have forgotten to return a result from that function.') window.close_on_mouse_click() return draw_shapes(rectangles, window) message = 'Now you should see the circumscribing rectangles too.' message = message + ' Click to continue.' window.continue_on_mouse_click(message) # ------------------------------------------------------------------------- # Test 2 is ALREADY DONE (here). # It runs in the same window as Test 1. # ------------------------------------------------------------------------- circles = [] center = rg.Point(50, 150) radius = 35 for _ in range(10): circle = rg.Circle(center, radius) circle.fill_color = 'magenta' circles = circles + [circle] center.x = center.x + 2 * radius center.y = center.y + 15 radius = radius - 3 draw_shapes(circles, window) message = 'More circles to be circumscribed are shown above.' message = message + ' Click to continue.' window.continue_on_mouse_click(message) rectangles = rectangles_from_circles(circles) draw_shapes(rectangles, window) message = 'Now you should see the circumscribing rectangles too.' message = message + ' Click to exit.' window.continue_on_mouse_click(message, close_it=True)
def run_test_generate_points_on_circle(): """ Tests the generate_points_on_circle function. """ # ------------------------------------------------------------------------- # DONE: 2. Implement this TEST function. # It TESTS the generate_points_on_circle function defined below. # Include at least ** 1 ** ADDITIONAL test (that YOU write). # # As usual, include both EXPECTED and ACTUAL results in your test # and compute the latter BY HAND (not by running your program). # # Your professor may do this exercise with you as "live coding". # ------------------------------------------------------------------------- print() print('--------------------------------------------------') print('Testing the generate_points_on_circle function:') print('--------------------------------------------------') # Test 1: expected = [ rg.Point(125.0, 50.0), # All numbers are approximate. rg.Point(112.5, 71.7), rg.Point(87.5, 71.7), rg.Point(75.0, 50.0), rg.Point(87.5, 28.3), rg.Point(112.5, 28.3) ] circle = rg.Circle(rg.Point(100, 50), 25) answer = generate_points_on_circle(circle, 6) print('Expected:', expected) print('Actual: ', answer) # ------------------------------------------------------------------------- # Test 2: (YOU write THIS test) # ------------------------------------------------------------------------- # Test 2: expected = [ rg.Point(150.0, 200.0), # All numbers are approximate. rg.Point(100, 250), rg.Point(50, 200), rg.Point(100, 150) ] circle = rg.Circle(rg.Point(100, 200), 50) answer = generate_points_on_circle(circle, 4) print('Expected:', expected) print('Actual: ', answer)
def run_test_MUTATE_circle(): """ Tests the MUTATE_circle function. """ print() print('-----------------------------------------') print('Testing MUTATE_circle:') print('-----------------------------------------') print() print('See the graphics window for this test.') print('If an error msg appears at any point,') print('you have failed this test.') # Tests 1 and 2 (on one window): window = rg.RoseWindow(500, 450, 'Testing MUTATE_circle') text = rg.Text(rg.Point(250, 125), '') text.attach_to(window.initial_canvas) circle = rg.Circle(rg.Point(250, 300), 50) circle.fill_color = 'yellow' circle.attach_to(window.initial_canvas) msg = 'Note: If you see an error message at ANY point,\n' msg = msg + 'then you have failed this test.\n\n' msg = msg + 'I have drawn the original, yellow circle.\n\n' msg = msg + 'So you should see a YELLOW circle below\n' msg = msg + '(and nothing else).\n\n' msg = msg + 'Click the mouse to continue this test.\n' text.text = msg window.render(0.5) window.get_next_mouse_click() result = MUTATE_circle(circle, 'pink', 200) msg = 'I have called your MUTATE_circle function.\n' msg = msg + 'It should have MUTATED the (sole) circle to be pink\n' msg = msg + 'and 200 units to the right of where it was.\n\n' msg = msg + 'So you should see (only) a PINK circle below,\n' msg = msg + 'almost touching the right side of the window.\n\n' msg = msg + 'Click the mouse to continue this test.' if result is not None: msg = msg + '\n\nERROR: You returned a value! Wrong!!!' text.text = msg window.render(0.5) window.get_next_mouse_click() circle.detach_from(window.initial_canvas) msg = 'I have now UN-drawn the (sole) circle.\n\n' msg = msg + 'So you should see NO circles below.\n\n' msg = msg + 'Click the mouse to continue this test.' text.text = msg window.render(0.5) window.get_next_mouse_click() circle.attach_to(window.initial_canvas) msg = 'Now I have RE-drawn the (now pink) circle.\n\n' msg = msg + 'So you should see (only) a PINK circle below,\n' msg = msg + 'just touching the right side of the window.\n' msg = msg + 'Click the mouse to continue this test.' text.text = msg window.render(0.5) window.get_next_mouse_click() result = MUTATE_circle(circle, 'black', -400) msg = 'I have called your MUTATE_circle function again.\n' msg = msg + 'It should have MUTATED the (sole) circle to be black\n' msg = msg + 'and 400 units to the left of where it was.\n\n' msg = msg + 'So you should see (only) a BLACK circle below,\n' msg = msg + 'just touching the left side of the window.\n\n' msg = msg + 'Click the mouse to continue this test.' if result is not None: msg = msg + '\n\nERROR: You returned a value! Wrong!!!' text.text = msg window.render(0.5) window.get_next_mouse_click() another_circle = rg.Circle(circle.center, 25) another_circle.fill_color = 'red' another_circle.attach_to(window.initial_canvas) msg = 'I have constructed and drawn another circle.\n' msg = msg + 'It is red and smaller than the black circle,\n' msg = msg + 'and currently centered on the black circle.\n\n' msg = msg + 'So you should now see a BLACK circle below,\n' msg = msg + 'just touching the left side of the window,\n' msg = msg + 'with a smaller red circle on top of the black circle.\n\n' msg = msg + 'Click the mouse to continue this test.' text.text = msg window.render(0.5) window.get_next_mouse_click() result = MUTATE_circle(another_circle, 'white', 65) msg = 'I have called your MUTATE_circle function again.\n' msg = msg + 'It should have MUTATED the small, red circle to be white\n' msg = msg + 'and 65 units to the left of where it was.\n\n' msg = msg + 'So you should see a BLACK circle below,\n' msg = msg + 'just touching the left side of the window,\n' msg = msg + 'with a WHITE circle slightly overlapping the black one.\n\n' msg = msg + 'Click the mouse to conclude this test.' if result is not None: msg = msg + '\n\nERROR: You returned a value! Wrong!!!' text.text = msg window.render(0.5) window.get_next_mouse_click() window.close()
def generate_points_on_circle(circle_for_points, number_of_points_to_generate): """ What comes in: -- an rg.Circle -- a positive integer that specifies how many rg.Points to generate What goes out: Returns a list containing the given number of rg.Points, where the rg.Points: -- all lie on the circumference of the given rg.Circle, -- are equally distant from each other, and -- go clockwise around the circumference of the given rg.Circle, starting at the rightmost point on the rg.Circle. Side effects: None. Examples: See the 'draw_points_on_circle' pictures in the pizza.pdf file attached, with the points shown on those pictures. Type hints: :type circle_for_points: rg.Circle :type number_of_points_to_generate: int :rtype: list of rg.Points """ # ------------------------------------------------------------------------- # Students: # Do NOT touch the above generate_points_on_circle function - # it has no TO DO. # Do NOT copy code from this function. # # Instead, ** CALL ** this function as needed in the problems below. # ------------------------------------------------------------------------- radius = circle_for_points.radius center_x = circle_for_points.center.x center_y = circle_for_points.center.y # ------------------------------------------------------------------------- # Each point is delta_degrees from the previous point, # along the circumference of the given circle. # ------------------------------------------------------------------------- delta_degrees = 360 / number_of_points_to_generate points = [] degrees = 0 for _ in range(number_of_points_to_generate): # --------------------------------------------------------------------- # Compute x and y of the point on the circumference of the # circle by using a polar representation. # --------------------------------------------------------------------- angle = math.radians(degrees) x = radius * math.cos(angle) + center_x y = radius * math.sin(angle) + center_y # --------------------------------------------------------------------- # Construct the point and append it to the list. # --------------------------------------------------------------------- point_on_circumference = rg.Point(x, y) points.append(point_on_circumference) # --------------------------------------------------------------------- # The next point will be delta_degrees from this point, # along the circumference of the given circle. # --------------------------------------------------------------------- degrees = degrees + delta_degrees return points
def draw_row_of_circles(n, starting_point, color, window): """ What comes in: The four arguments are: -- A positive integer n. -- An rg.Point. -- A color appropriate for rosegraphics (e.g. 'red') -- An rg.RoseWindow. What goes out: Nothing (i.e., None). Side effects: Draws n rg.Circle objects in a row, all on the given rg.RoseWindow, such that: -- The first rg.Circle is centered at the given starting_point. -- Each rg.Circle just touches the previous one (to its left). -- Each rg.Circle has radius 20. -- Each rg.Circle is filled with the given color. Must ** render ** but ** NOT close ** the rg.RoseWindow. Type hints: :type n: int :type starting_point: rg.Point :type color: str :type window: rg.RoseWindow """ # ------------------------------------------------------------------------- # The example below shows one way to solve problems using # HELPER variables (aka AUXILIARY variables) # In this approach: # 1. You determine all the variables that you need # to construct/draw whatever the problem calls for. # We call these HELPER variables. # 2. You initialize them BEFORE the loop, choosing values that # make them just right for constructing and drawing the # FIRST object to be drawn, in the FIRST time through the loop. # For example, x = starting_point.x in the example below. # 3. You determine how many times the loop should run # (generally, however many objects you want to draw) # and write the FOR statement for the loop. # For example, for _ in range(n): in the example below. # 4. Inside the loop you write the statements to construct and # draw the FIRST object to be drawn, using your helper # variables. This is easy because you chose just the right # values for those helper variables for this FIRST object. # 5. Test: Make sure the FIRST object appears. # (It will be redrawn many times, that is OK). # 6. Add code at the BOTTOM of the loop that changes the helper # variables appropriately for the NEXT time through the loop. # For example, x = x + diameter in the example below. # 7. Test and fix as needed. # # Many students (and professionals) find this technique less # error-prone that using the loop variable to do all the work. # ------------------------------------------------------------------------- radius = 20 diameter = 2 * radius x = starting_point.x # Initialize x and y BEFORE the loop. Choose ... y = starting_point.y # ... values that make the FIRST object easy to draw. for _ in range(n): # Loop that does NOT use its index variable # --------------------------------------------------------------------- # Construct the relevant object(s), # based on the current x, y and other variables. # --------------------------------------------------------------------- center = rg.Point(x, y) circle = rg.Circle(center, radius) circle.fill_color = color # Attach the object(s) to the window. circle.attach_to(window) # --------------------------------------------------------------------- # Increment x (and in other problems, other variables) # for the thing(s) to draw in the NEXT iteration of the loop. # --------------------------------------------------------------------- x = x + diameter window.render()
def run_test_practice_problem3a(): """ Tests the practice_problem3a function. """ # ------------------------------------------------------------------ # 6 tests. # They use the imported simple_testing (st) module. # Each test is a SimpleTestCase with 3 arguments: # -- the function to test, # -- a list containing the argument(s) to send to the function, # -- the correct returned value. # For example, the first test below will call # practice_problem3a((rg.Circle(rg.Point(5, 10), 20), # rg.Circle(rg.Point(2, 20), 20), # rg.Circle(rg.Point(7, 30), 10), # rg.Circle(rg.Point(10, 40), 20), # rg.Circle(rg.Point(2, 50), 10))) # and compare the returned value against 1400 (the correct answer). # ------------------------------------------------------------------ tests = [ st.SimpleTestCase( practice_problem3a, [(rg.Circle(rg.Point(5, 10), 20), rg.Circle(rg.Point(2, 20), 20), rg.Circle(rg.Point(7, 30), 10), rg.Circle(rg.Point(10, 40), 20), rg.Circle(rg.Point(2, 50), 10))], 5 * 2 * 7 * 10 * 2), st.SimpleTestCase(practice_problem3a, [(rg.Circle(rg.Point(58, 10), 20), )], 58), st.SimpleTestCase(practice_problem3a, [(rg.Circle( rg.Point(84, 100), 200), rg.Circle(rg.Point( 28, 200), 200), rg.Circle(rg.Point(10005, 300), 100))], 84 * 28 * 10005), st.SimpleTestCase(practice_problem3a, [()], 1), st.SimpleTestCase( practice_problem3a, [(rg.Circle(rg.Point(5, 10), 20), rg.Circle(rg.Point(0, 20), 20), rg.Circle(rg.Point(7, 30), 10), rg.Circle(rg.Point(10, 40), 20), rg.Circle(rg.Point(2, 50), 10))], 5 * 0 * 7 * 10 * 2), ] circles = [] for k in range(1, 101): circles.append(rg.Circle(rg.Point(k, k + 20), 5 * k)) answer = math.factorial(100) tests.append(st.SimpleTestCase(practice_problem3a, [circles], answer)) # ------------------------------------------------------------------ # Run the 6 tests in the tests list constructed above. # ------------------------------------------------------------------ st.SimpleTestCase.run_tests('practice_problem3a', tests)