user3105664
user3105664

Reputation: 179

Trying to draw a checkerboard using Turtle in Python - how do I fill in every other square?

I'm trying to draw a checkerboard.

I drew the board, but now I have to define a function (a loop) that fills in every other square with black. I've been trying to write a loop to do this for a while, can someone help?

Here's my code:

import turtle


def drawGrid():
turtle.penup()
turtle.goto(-300, 250)
turtle.pendown()
turtle.forward(300)
turtle.right(90)
turtle.forward(300)
turtle.right(90)
turtle.forward(300)
turtle.right(90)
turtle.forward(300)

def drawColumns():
for i in range(4):
    turtle.right(90)
    turtle.forward(37.5)
    turtle.right(90)
    turtle.forward(300)
    turtle.left(90)
    turtle.forward(37.5)
    turtle.left(90)
    turtle.forward(300)

def drawRows():
turtle.left(180)
rows = 0 
while rows <= 3:
    rows += 1
    turtle.forward(37.5)
    turtle.right(90)
    turtle.forward(300)
    turtle.left(90)
    turtle.forward(37.5)
    turtle.left(90)
    turtle.forward(300)
    turtle.right(90)

def main():
drawGrid()
drawColumns()
drawRows()
if __name__ == "__main__":
main()

Upvotes: 4

Views: 16234

Answers (4)

Red
Red

Reputation: 27577

Let's have a look at the zig-zag approach (the explanation of the code is commented inside):

import turtle

def drawGrid(rows, cols, size):
    turtle.sety(turtle.ycor() + size * rows) # Draw the initial line
    f = size * 2
    turtle.begin_fill()
    for j in range(cols): # Make the columns
        if j % 2:
            turtle.backward(f) # Make room for the zig-zag up and zig-zag down
        for i in range(rows * 2): # rows * 2 because there will be both zig-zag down and a zig-zag up for each row
            turtle.forward(size)
            turtle.right(90)
            if i % 2:
                turtle.left, turtle.right = turtle.right, turtle.left # Switch the zig-zag direction
        turtle.left(180)
    turtle.end_fill()
    turtle.sety(turtle.ycor() - size * rows) # Draw the final line
    
turtle.penup()
turtle.goto(-300, -50) # Set the bottom-left position of the grid
turtle.pendown()
turtle.speed("fastest") # Because I have no patience
drawGrid(8, 8, 40)

Output:

enter image description here

Note that the number of rows and columns must be even for this to work.

Upvotes: 0

tallus
tallus

Reputation: 168

Turtles fill method works on shapes, i.e. a completely bounded area. So rather than drawing a grid you need to think in terms of drawing a series of squares.

So lets start by defining a simple function to draw a filled in square. It takes a turtle object and a size which is the length of the side.

import turtle

def draw_filled_square(this_turtle, size):    
    """Draw a square by drawing a line and turning through 90 degrees 4 times"""
    this_turtle.pendown()
    this_turtle.fill(True)
    for _ in range(4):
        this_turtle.forward(size)
        this_turtle.right(90)
    this_turtle.fill(False)
    this_turtle.penup()

we can call it like this:

window = turtle.Screen()
myturtle = turtle.Turtle()
square_size = 90
myturtle.goto(-300, 200)

draw__filled_square(myturtle, square_size)

Which draws a single square. Note that it puts it back at the starting place, so we need to move it before drawing the next square.

Now, in practice, as long as we draw the outline of the box we only need to draw filled squares, unfilled squares can be represented negative space. But for the purposes of explanation I'm going to also draw them.

Defining a function for an unfilled square is easy -- just duplicate the existing function but set this_turtle.fill(False) at the beginning instead.

Anytime something needs to count in a repeating sequence (1, 2, 3, 4, 1, 2, 3, 4, ...) it calls for use of modulo (remainder). Modulo means remainder so if x modulo y is 0 it means x is exactly divisible by y. This translates into code as if x % y == 0:

Here's a simple drum machine to demonstrate:

def drum_loop(x):
     # go bang on the fourth beat
     if x % 4 == 0:
         print("bang!")
     else:
         print("tish")

# prints tish, tish, tish, bang! tish, tish, tish, bang!
for i in range(1,9):
   drum_loop(i)

Alternating is just like counting 0, 1 , 0, 1 repeatedly.

So we can draw a row like this:

for i in range(8): 
    if i % 2 == 0:
        draw_filled_square(myturtle, square_size)
    else:
        draw_unfilled_square(myturtle, square_size)
    # move to start of next square
    myturtle.forward(square_size)

Now just repeating this isn't going to do the trick, but it should be clear you can use modulo 2 again to make the rows alternate properly.

Do this by defining a row function that will alternate between starting with a black and starting with a white square, then calling this from within another loop. (Don't forget to go back to the beginning and move down every time you start a row).

Upvotes: 3

cdlane
cdlane

Reputation: 41872

Here's another example where drawing creates more work for the poor turtle than simply stamping. Rather than thinking about drawing and filling boxes, think about the board itself as a filled square onto which other filled squares are stamped:

from turtle import Turtle, Screen

NUMBER_SQUARES = 8
SQUARE_SIZE = 40
BOARD_SIZE = SQUARE_SIZE * NUMBER_SQUARES
BORDER_FRACTION = 1.025  # add a slight edge to board

STAMP_SIZE = 20  # size of turtle square image

turtle = Turtle(shape='square', visible=False)
turtle.shapesize(BOARD_SIZE / STAMP_SIZE * BORDER_FRACTION)
turtle.color('black')
turtle.stamp()

turtle.shapesize(SQUARE_SIZE / STAMP_SIZE)
turtle.color('white')
turtle.penup()

for y in range(-NUMBER_SQUARES//2, NUMBER_SQUARES//2):
    parity = y % 2 == 0

    for x in range(-NUMBER_SQUARES//2, NUMBER_SQUARES//2):
        if parity:
            turtle.goto(x * SQUARE_SIZE + SQUARE_SIZE//2, y * SQUARE_SIZE + SQUARE_SIZE//2)
            turtle.stamp()

        parity = not parity

Screen().exitonclick()

This solution can print a board in any two colors (e.g. black and red), it doesn't assume a white background. Just another example of better living through stamping.

Upvotes: 1

Omkar Thawkar
Omkar Thawkar

Reputation: 11

import turtle

turtle.pensize(2)
turtle.penup()
turtle.goto(-160,-160)
turtle.pendown()
turtle.color("black")

for i in range(4):
    turtle.forward(320)
    turtle.left(90)

for y in range(-160,160,80):
    for x in range(-160,160,80):
        turtle.begin_fill()
        turtle.penup()
        turtle.goto(x,y)
        turtle.pendown()

        for k in range(4):
            turtle.forward(40)
            turtle.left(90)

        turtle.end_fill()       

for y in range(-120,160,80):
    for x in range(-120,160,80):
        turtle.begin_fill()
        turtle.penup()
        turtle.goto(x,y)
        turtle.pendown()
        for k in range(4):
            turtle.forward(40)
            turtle.left(90)
        turtle.end_fill()   

turtle.done()

Upvotes: 0

Related Questions