0

so I tried to create a board with buttons for a game called "othello" though I wanted to test the buttons first so I put a simple command to print the position of the button. Pretty simple right? here is the code

WHITE='white'
BLACK='black'
n=8
No_changes=0
changes=list()
from tkinter import *
def create_board():
    board=[['lawn green' for count in range(n)]for rows in range(n)]
    board[3][3]=WHITE
    board[3][4]=BLACK
    board[4][3]=BLACK
    board[4][4]=WHITE
    return board
def print_board(board):
    root = Tk()
    Grid.rowconfigure(root, 0, weight=1)
    Grid.columnconfigure(root, 0, weight=1)
    frame=Frame(root)
    frame.grid(row=0,column=0,sticky=N+E+S+W)
    for x in range(8):
        for y in range(8):
            Grid.rowconfigure(frame,x,weight=1)
            Grid.columnconfigure(frame,y,weight=1)
            btn = Button(frame,bg=board[x][y],command=lambda:move(x,y,board[x][y]))
            btn.grid(column=x,row=y,padx=5,pady=5, sticky=N+S+E+W)
    root.mainloop()
def move(row,column,who):
    print(row,column,who)
board=create_board()
print_board(board)

and I get just the last position of the grid. What should I do?

1 Answers1

0

Use a partial instead of a lambda:

from functools import partial
...
btn = Button(frame,bg=board[x][y],command=partial(move, x, y, board[x][y])

There are other options, but this is what I tend to do. Using a lambda in the way you are, only the names x, y etc., are remembered rather than the objects they point to at any given iteration of your for loop, so at the end of the loop x and y will point to their most recent values, and that is what will be passed to move(). With partial() the values that x and y point to at each iteration are "frozen" with the function, so that the values you want are passed when the the Button is finally pressed.

elethan
  • 16,408
  • 8
  • 64
  • 87
  • you can solve this with `lambda`, too. http://stackoverflow.com/questions/17677649/tkinter-assign-button-command-in-loop-with-lambda – Bryan Oakley Jan 06 '17 at 15:40