Map Foundation

Objective: Map Foundation

Welcome to Map Foundation: Setting Your Canvas!

Our objective for this micro-quest is to create a Python script using Turtle to initialize the drawing canvas with a light blue background color and draw a dark gray rectangular border to define the map's area.

This task introduces fundamental Turtle screen setup and basic shape drawing, which are essential building blocks for our map project.

Check Spec: See the Failing Tests

Before we start coding, let's run the tests to see the current state of the project and understand the engineering specification we need to meet.

Run the tests using the command pytest in your terminal.

Test Results:

  • test_setup_map_canvas

As expected, the test for setting up the map canvas is failing because we haven't implemented the required functionality yet. This confirms what we need to build.

Implement: `main.py`

Now, let's implement the solution by following the TODO comments in the main.py file.

Step by step checklist:

  1. Get a reference to the turtle screen object.
  2. Configure the screen's dimensions using the provided constants.
  3. Set the screen's background color using the provided constant.
  4. Calculate the x and y coordinates for the four corners of the border, accounting for padding.
  5. Create a new turtle object to draw the border.
  6. Hide the turtle icon.
  7. Set the drawing speed to the fastest.
  8. Set the pen's color using the provided constant.
  9. Set the pen's thickness using the provided constant.
  10. Prepare the pen for drawing.
  11. Lift the pen up.
  12. Move the pen to the calculated top-left corner.
  13. Put the pen down.
  14. Draw the rectangular border by moving the pen sequentially.
  15. Move to the top-right corner.
  16. Move to the bottom-right corner.
  17. Move to the bottom-left corner.
  18. Move back to the top-left corner to close the rectangle.

The following documentation sections are going to be helpful:

    1. Setting Up the Canvas (Screen)
    1. The Turtle (Pen)
    1. Movement and Drawing

Validate: Run the Tests Again

You've implemented the code to set up the canvas and draw the border. Now, let's run the tests again to validate your work.

Run the tests using the command pytest in your terminal.

Test Results:

  • test_setup_map_canvas All tests passed!

Great job! The tests confirm that your setup_map_canvas function correctly initializes the screen and draws the border according to the requirements.

Documentation

# Python Fundamentals Refresher

## Functions with Parameters

Functions are blocks of reusable code. Parameters are like placeholders for values that a function needs to do its job.

*   **Defining a function:**
    ```python
    def greet(name: str, greeting: str):
        # Function code uses name and greeting
        print(f"{greeting}, {name}!")
    ```
*   **Calling a function:**
    ```python
    greet("Alice", "Hello")
    # Output: Hello, Alice!
    ```
*   **Formatting Strings (f-strings):**
    A convenient way to embed expressions inside string literals.
    *   `f"{variable}"`: Inserts the value of `variable`.
    *   `f"{float_variable:.2f}"`: Formats a floating-point number to two decimal places.

## Looping with `range()`

`for` loops are used to repeat a block of code multiple times. `range()` generates a sequence of numbers.

*   **Basic loop:**
    ```python
    for i in range(3):  # i will be 0, 1, 2
        print(i)
    # Output:
    # 0
    # 1
    # 2
    ```
*   **Using the loop variable for numbered lists:**
    `range(len(my_list))` iterates through indices of a list.
    ```python
    items = ["Apple", "Banana", "Cherry"]
    for i in range(len(items)):
        # i starts at 0, so add 1 for 1-based numbering
        print(f"{i + 1}. {items[i]}")
    # Output:
    # 1. Apple
    # 2. Banana
    # 3. Cherry
    ```

## Running Scripts

The `if __name__ == "__main__":` block:
Code inside this block only runs when the script is executed directly (e.g., `python your_script.py`), not when it's imported as a module into another script.

```python
def setup():
    print("Setting up...")

def run_program():
    print("Running program logic...")

if __name__ == "__main__":
    print("Script is being run directly.")
    setup()
    run_program()

Turtle Graphics

1. Setting Up the Canvas (Screen)

The turtle module draws on a window called the "screen".

  • Get the screen:
    import turtle
    screen = turtle.Screen()
    
  • Set screen size:
    screen.setup(width=600, height=400) # Set window dimensions
    
  • Set background color:
    screen.bgcolor("lightblue") # Use color names or hex codes
    
  • Control screen updates (for faster drawing): Turn off updates before complex drawing, turn on and update when finished.
    screen.tracer(0) # Turn off updates
    # ... drawing code ...
    screen.update()  # Show the drawing
    screen.tracer(1) # Turn updates back on (optional, often done implicitly by done())
    
  • Keep the window open:
    turtle.done() # Or screen.mainloop()
    

Example of a turtle screen with a background color

2. The Turtle (Pen)

The "turtle" is the cursor that draws on the screen. You can have multiple turtles.

  • Create a Turtle:
    artist = turtle.Turtle()
    
  • Hide the Turtle icon:
    artist.hideturtle()
    
  • Set Speed: Speed can be 1-10 (slowest to fastest) or 0 (no animation, instant drawing).
    artist.speed(0) # Fastest
    artist.speed(5) # Medium speed
    
  • Set Pen Color / Fill Color:
    artist.color("red")      # Sets both pen and fill color
    artist.pencolor("blue")  # Sets only pen color
    artist.fillcolor("green")# Sets only fill color
    
  • Set Pen Size (Thickness):
    artist.pensize(3) # Set pen thickness to 3 pixels
    
  • Pen Control:
    • Lift the pen (stop drawing when moving):
      artist.penup()
      
    • Put the pen down (start drawing when moving):
      artist.pendown()
      

Example showing a turtle icon and a line drawn by it

3. Movement and Drawing

Commands to move the turtle and draw lines or shapes. The screen's center is (0, 0).

  • Go to a Specific Position: Move the turtle to coordinates (x, y). Draws a line if the pen is down.
    artist.goto(100, 50) # Move to x=100, y=50
    
  • Move Forward/Backward: Move the turtle in its current direction.
    artist.forward(100) # Move 100 units forward
    artist.backward(50) # Move 50 units backward
    
  • Turning: Change the turtle's direction.
    artist.left(90)      # Turn left by 90 degrees
    artist.right(45)     # Turn right by 45 degrees
    artist.setheading(0) # Set direction to 0 degrees (East)
                         # 0: East, 90: North, 180: West, 270: South
    
  • Drawing Shapes (Examples):
    • Square:
      # Assuming pen is down and turtle is at a corner facing along an edge
      side = 50
      for _ in range(4):
          artist.forward(side)
          artist.left(90)
      
    • Circle: Draws a circle with the given radius. The turtle's current position is the bottom of the circle if facing East.
      radius = 30
      artist.circle(radius)
      

Example of a turtle drawing a square or triangle

4. Filled Shapes

Draw shapes that are filled with a solid color.

  • Set Fill Color: Use fillcolor() or the color() command (which sets both pen and fill).
    artist.fillcolor("blue")
    
  • Start and End Fill: Call begin_fill() before drawing the shape, and end_fill() after the shape is complete.
    artist.fillcolor("yellow")
    artist.begin_fill()
    # ... drawing commands for the shape (e.g., square, circle, polygon) ...
    artist.end_fill()
    

Example of a filled shape drawn by turtle

5. Drawing with Functions

Organize your drawing code into functions for reusability.

  • Defining a drawing function: A function can take parameters like position (x, y), size, or color to make it flexible. It often takes the turtle object itself as a parameter.
    def draw_dot_at(t, x, y, dot_color, dot_size):
        t.penup()
        t.goto(x, y)
        t.pendown()
        t.dot(dot_size, dot_color) # Draws a filled circle
    
  • Calling a drawing function:
    my_turtle = turtle.Turtle()
    draw_dot_at(my_turtle, 100, 100, "purple", 20) # Draw a purple dot
    draw_dot_at(my_turtle, -50, 0, "orange", 10)  # Draw an orange dot
    

6. Drawing Multiple Shapes with Loops

Use loops to draw the same shape multiple times at different locations or with variations.

  • Looping through coordinates: Store positions in a list and iterate through the list.
    positions = [(100, 100), (-50, 0), (0, -150)]
    my_turtle = turtle.Turtle()
    my_turtle.speed(0) # Draw fast
    
    for pos_x, pos_y in positions:
        # Call a drawing function for each position
        draw_dot_at(my_turtle, pos_x, pos_y, "green", 15)
    
  • Calculating positions in a loop: Use the loop counter to calculate coordinates.
    my_turtle = turtle.Turtle()
    my_turtle.speed(0)
    
    for i in range(5): # Draw 5 circles
        x = -200 + i * 100 # Space circles 100 units apart horizontally
        y = 0
        my_turtle.penup()
        my_turtle.goto(x, y - 20) # Position for circle bottom (radius 20)
        my_turtle.pendown()
        my_turtle.circle(20)
    

Example of a loop drawing multiple shapes

7. Adding Text Labels

Use the write() method to display text on the canvas.

  • Writing text: The text is written at the turtle's current position.
    artist.penup()
    artist.goto(0, 150) # Move to position for text
    artist.color("black") # Set text color
    artist.write("My Map Title", align="center", font=("Arial", 16, "bold"))
    
  • write() parameters:
    • arg: The string to write.
    • move (optional, boolean): If True, the turtle moves to the end of the text. Default is False.
    • align (optional, string): Alignment of the text relative to the turtle's position ("left", "center", or "right"). Default is "left".
    • font (optional, tuple): A tuple (name, size, style). name is a font family string (e.g., "Arial", "Courier", "Times New Roman"). size is an integer font height. style is a string ("normal", "bold", "italic").

Example of text written on a turtle canvas