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

user3105664 picture user3105664 · Feb 12, 2014 · Viewed 12.2k times · Source

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()

Answer

tallus picture tallus · Feb 12, 2014

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).