1
\$\begingroup\$

For an assignment, I had to draw a checkers board, with blue and red checkers, in python. What I have works, but I'm wondering if there's a more elegant and/or efficient way to accomplish this feat? Any and all suggestions are welcome!

import turtle

def draw_box(t,x,y,size,fill_color):
  t.penup() 
  t.goto(x,y) 
  t.pendown() 
  t.fillcolor(fill_color)
  t.begin_fill()  

  for i in range(0,4):
    board.forward(size) 
    board.right(90) 
  t.end_fill() 

def draw_circle(t,x,y,radius,color):
  t.penup()
  t.goto(x,y)
  t.pendown()
  t.fillcolor(color)
  t.begin_fill()
  t.circle(radius)
  t.end_fill()

def draw_chess_board():
  square_color = "black" 
  start_x = 0 
  start_y = 0 
  box_size = 30 
  for i in range(0,8): 
      for j in range(0,8):
          draw_box(board, start_x + j * box_size, start_y + i * box_size, box_size, square_color)
          square_color = 'black' if square_color == 'white' else 'white'
          if square_color == 'black' and i < 3:
              draw_circle(board, board.xcor() + (box_size / 2), board.ycor() - box_size, box_size / 2, "red")
          if square_color == 'black' and i > 4:
              draw_circle(board, board.xcor() + (box_size / 2), board.ycor() - box_size, box_size / 2, "blue")   
      square_color = 'black' if square_color == 'white' else 'white' 

board = turtle.Turtle()

draw_chess_board()

turtle.done()
\$\endgroup\$
4
\$\begingroup\$

In essence, the code is well designed. You’ve split the code into simple, reusable functions and the logic is clear.

But there are still improvements to be made:

  • You relly on the global variable board, which is a bad habit to get into. Instead, pass it as parameter, even for your draw_chess_board function;
  • The check for the square_color == 'black' feels really odd, prefer to check for 'white' as it is how it will draw and then change the background color;
  • Using strings to alternate between two states is unnecessarily verbose, prefer to use booleans that you convert to string at the right moment;
  • I don't see any reason to define start_x and start_y and they doesn't contribute mathematically either, you can drop them;
  • You could simplify some of your computation by storing intermediate constants into variables;
  • You should avoid magic numbers by naming them.

Proposed improvements:

import turtle


def draw_box(canvas, x, y, size, fill_color):
    canvas.penup()
    canvas.goto(x, y)
    canvas.pendown()
    canvas.fillcolor(fill_color)

    canvas.begin_fill()
    for i in range(4):
        canvas.forward(size)
        canvas.right(90)
    canvas.end_fill()


def draw_circle(canvas, x, y, radius, color):
    canvas.penup()
    canvas.goto(x, y)
    canvas.pendown()
    canvas.fillcolor(color)

    canvas.begin_fill()
    canvas.circle(radius)
    canvas.end_fill()


def draw_chess_board(canvas, box_size=30, board_size=8, pawn_lines=3):
    half_box_size = box_size / 2
    white_square = False
    for i in range(board_size):
        y = i * box_size
        for j in range(board_size):
            x = j * box_size
            draw_box(canvas, x, y, box_size, 'white' if white_square else 'black')
            if white_square and i < pawn_lines:
                draw_circle(canvas, x + half_box_size, y - box_size, half_box_size, 'red')
            if white_square and i >= board_size - pawn_lines:
                draw_circle(canvas, x + half_box_size, y - box_size, half_box_size, 'blue')
            white_square = not white_square
        white_square = not white_square


if __name__ == '__main__':
    t = turtle.Turtle()
    draw_chess_board(t)
    t.hideturtle()
    turtle.done()
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.