tkinter callbacks stop working

namenobodywants at gmail.com namenobodywants at gmail.com
Fri Oct 21 08:26:18 EDT 2016


hello pythonistas

the script below plays tictactoe; everything works; but if i replace the block at the bottom

if True:
    <tkinter code>

with this instead

def function():
    <tkinter code>
function()

then the tkinter callbacks don't work anymore; can anybody make sense of this? thanks if you can help

peace
stm

ps: here's the code...


ex, oh, blank = 'XO '

rows      = [[3*i + j for j in range(3)] for i in range(3)]
columns   = [[3*i + j for i in range(3)] for j in range(3)]
diagonals = [[3+3, 4, 5-3], [3-3, 4, 5+3]]
lines     = rows + columns + diagonals

putmark    = lambda board, square, mark: board[:square] + mark + board[square + 1:]
getblanks  = lambda board: [square for square in range(9) if board[square]==blank]
getmover   = lambda board: ex if board.count(ex)==board.count(oh) else oh
getlines   = lambda board: [[board[square] for square in line] for line in lines]
getwinners = lambda board: [player for player in [ex, oh] if [player] * 3 in getlines(board)]

def evaluate(board):
    winners  = getwinners(board)
    mover    = getmover(board)
    blanks   = getblanks(board)
    value    = (+1) if winners==[ex] else (-1) if winners==[oh] else 0
    optimum  = max  if mover  == ex  else min  if mover  == oh  else None
    if winners or not blanks: return value, []
    values   = [evaluate(putmark(board,square,mover))[0] for square in blanks]
    optimal  = optimum(values)
    return optimal, [square for (index, square) in enumerate(blanks) if values[index]==optimal]

isvalid   = lambda board: len(getwinners(board)) < 2 and board.count(ex)-board.count(oh) in {0,1}
cartesian = lambda strings: [''] if not strings else [x + ys for x in strings[0] for ys in cartesian(strings[1:])] 
getmoves  = lambda: {board: evaluate(board)[1] for board in cartesian([marks] * 9) if isvalid(board)}

def getmove(board):
    from random import choice
    blanks = getblanks(board)
    evens  = [square for square in blanks if (square % 2)==0]
    return choice(evaluate(board)[1]) if len(blanks)<8 else 4 if 4 in blanks else choice(evens)

def getdisplay(board):
    template  = ' {} | {} | {} '
    separator = '\n-----------\n'
    return separator.join(template.format(*(board[square] for square in row)) for row in rows)
    
def getstatus(board):    
    winners   = getwinners(board)
    numblanks = board.count(blank)
    if winners:      return winners[0] + ' wins' 
    if numblanks==0: return 'draw'
    if numblanks==9: return 'X goes first'
    else:            return getmover(board) + ' goes next'


show = lambda board: print('\n' + getdisplay(board) + '\n\n' + getstatus(board) + '\n')

def newgame():
	global board
	board = blank * 9
	show(board)
		
def makemove():
	global board
	board = board if getwinners(board) or blank not in board else putmark(board, getmove(board), getmover(board))
	show(board)
	
def takemove(square):
	global board
	board = board if getwinners(board) or board[square] != blank else putmark(board, square, getmover(board))
	show(board)	


show = lambda board: status.set(getstatus(board)) or [squares[i].set(board[i]) for i in range(9)]

if True: 
	
    from tkinter import Tk, Frame, Label, Button   
    
    window         = Tk()
    status         = StringVar()
    squares        = [StringVar() for i in range(9)]

    statusframe    = Frame(window)
    buttonframe    = Frame(window)
    boardframe     = Frame(window)
    statuslabel    = Label(statusframe)
    newgamebutton  = Button(buttonframe)
    makemovebutton = Button(buttonframe)
    rowframes      = [Frame(boardframe)       for i in range(3)]
    squarebuttons  = [Button(rowframes[i//3]) for i in range(9)]
    
    statuslabel                         .configure(textvariable=status)
    newgamebutton                       .configure(command=newgame,  text='new game')
    makemovebutton                      .configure(command=makemove, text='make move')
    for i in range(9): squarebuttons[i] .configure(textvariable=squares[i], command=lambda i=i:takemove(i))
    
    statuslabel                         .configure(padx=0,  pady=10)
    boardframe                          .configure(padx=20, pady=20)
    for button in squarebuttons: button .configure(width=4, height=2)
    
    boardframe                          .pack(side=TOP)
    buttonframe                         .pack(side=TOP)
    statusframe                         .pack(side=TOP)
    newgamebutton                       .pack(side=LEFT)
    makemovebutton                      .pack(side=RIGHT)
    statuslabel                         .pack(side=TOP)
    for frame  in rowframes:     frame  .pack(side=TOP) 
    for button in squarebuttons: button .pack(side=LEFT) 
		      
    newgame() 
    window.title(' tictactoe')                        
    window.mainloop()


""" #)----------------------------------------
""" #)----------------------------------------   



More information about the Python-list mailing list