Make a grid with the Tkinter rectangle

I am trying to simulate a grid like what would be used for a game board using tkinter rectangles being drawn onto a canvas, however I am having trouble making a loop that does so correctly.

Pretty much I have a variable that contains a certain amount of rows for a grid and a variable for the amount of columns, and I need to create a grid of rectangles based off of those configurations which can change anytime the application is run, which is making it a bit tricky for me.

Anyways, I currently have a function to draw a rectangle to the screen like so:

def _place_empty_tiles(self):
        self._canvas.update()
        width = self._canvas.winfo_width()
        height = self._canvas.winfo_height()
        self.x = width / self._game.columns
        self.y = height / self._game.rows
        for i in range(self._game.columns):
            click_point = point.from_pixel(self.x, self.y, width, height)
            self._state.handle_click(click_point)
            self.x += 60

    def _redraw_game_pieces(self)->None:
        '''Delete and redraw all the  of game pieces'''
        self._canvas.delete(tkinter.ALL)
        canvas_width = self._canvas.winfo_width()
        canvas_height = self._canvas.winfo_height()

        for tile in self._state.all_tiles():
            center_x, center_y = tile.center().pixel(canvas_width, canvas_height)

            radius_x = tile.radius_frac() * canvas_width
            radius_y = tile.radius_frac() * canvas_height

            self._canvas.create_rectangle(
                center_x - radius_x, center_y - radius_y,
                center_x + radius_x, center_y + radius_y,
                fill = '#006000', outline = '#000000')

You may noticed I have some custom coordinate conversion methods going on to compensate for the screen re sizing. However, my problem is under the function _place_empty_tiles(self) in the for loop. Let's say the amount of columns is 4, it will currently print out on the canvas the following:

However,

  1. it is actually making a row, and
  2. that is only one row.

How can I make it so I can create a grid with a similar style given the amount of rows and columns are stored in self._game.columns and self._game.rows?

UPDATE: Tried basing it off The tkinter Knight's Tour Demo I rewrote the function like so:

def _place_empty_tiles(self):
    self._canvas.update()
    width = self._canvas.winfo_width()
    height = self._canvas.winfo_height()
    for r in range(self._game.rows -1,-1,-1):
        for c in range(self._game.columns):
            click_point = point.from_pixel(c*30+4, r*30+4, c*30+30, r*30+30)
            self._state.handle_click(click_point)
    self._redraw_game_pieces()

which is close, but still getting some unexpected results:


The Tk demos include a Knight's Tour demo that draws a chessboard. Someone converted it for tkinter and you can examine the _draw_board function to see an example of how to create such a layout using canvas rectangles:

def draw_board(canvas):
    # draw checkerboard
    for r in range(7, -1, -1):
        for c in range(8):
            if c&1 ^ r&1:
                fill = 'tan3'
                dfill = 'tan4'
            else:
                fill = 'bisque'
                dfill= 'bisque3'
            coords = (c*30+4, r*30+4, c*30+30, r*30+30)
            canvas.create_rectangle(coords, fill=fill, disabledfill=dfill,
                                    width=2, state='disabled')