Python tkinter error return self.func(*args) , return self._configure('configure', cnf, kw)

Question:

this is my code for tic tac game (X O) in python using Tkinter and I was building with two stages of game
1- play with pc
2- play with player 2

and I think the statements and conditions well be good

but it show me some of error I can’t solve it ..

Error :

Exception in Tkinter callback

Traceback (most recent call last):

File "C:Program Files (x86)Microsoft Visual StudioSharedPython37_64libtkinter_init_.py", line 1705, in call
return self.func(*args)

File "C:UsersazooopythonCS492XOtkintermain.py", line 169, in
button3 = Button(f4, text=" ", command=lambda: gameplay(3))

File "C:UsersazooopythonCS492XOtkintermain.py", line 95, in gameplay
pt(player,choice)

File "C:UsersazooopythonCS492XOtkintermain.py", line 83, in pt
turnlabel.config(text=f'{p2} chance’)

File "C:Program Files (x86)Microsoft Visual StudioSharedPython37_64libtkinter_init_.py", line 1485, in configure
return self.configure(‘configure’, cnf, kw)
File "C:Program Files (x86)Microsoft Visual StudioSharedPython37_64libtkinter_init
.py", line 1476, in _configure
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
KeyboardInterrupt

Code :

from tkinter import *
import random

player = 1
gt = 0
gg = 0
retry = 0
Win = 1
Running = 0
Game = Running
Mark = 'X'
board = {1: " ", 2: " ", 3: " ", 4: " ", 5: " ", 6: " ", 7: " ", 8: " ", 9: " "}


def CheckPosition(x):
    if board[x] == ' ':
        return True
    else:
        return False


def CheckWin():
    global Game
    # Horizontal winning condition
    if board[1] == board[2] and board[2] == board[3] and board[1] != ' ':
        Game = Win
    elif board[4] == board[5] and board[5] == board[6] and board[4] != ' ':
        Game = Win
    elif board[7] == board[8] and board[8] == board[9] and board[7] != ' ':
        Game = Win
        # Vertical Winning Condition
    elif board[1] == board[4] and board[4] == board[7] and board[1] != ' ':
        Game = Win
    elif board[2] == board[5] and board[5] == board[8] and board[2] != ' ':
        Game = Win
    elif board[3] == board[6] and board[6] == board[9] and board[3] != ' ':
        Game = Win
        # Diagonal Winning Condition
    elif board[1] == board[5] and board[5] == board[9] and board[5] != ' ':
        Game = Win
    elif board[3] == board[5] and board[5] == board[7] and board[5] != ' ':
        Game = Win
        # Match Tie or Draw Condition
    elif (board[1] != ' ' and board[2] != ' ' and board[3] != ' ' and board[4] != ' ' and board[5] != ' ' and board[
        6] != ' ' and board[7] != ' ' and board[8] != ' ' and board[9] != ' '):
        Game = retry
    else:
        Game = Running

def retryG():
    for i in range(0,10):
        board[i] = " "
        button[i].config(text=" ")

#     gg (0)=with pc , gg(1)=with player2
#     gt (0)= easy  , gt(1)=hard
#     player(1)= player first, player(2)=pc first
#      postion= button postion
def turn(player):
    global p1, p2
    if gg == 0:
        if player == 1:
            p1 = "User"
            p2 = "PC"
        else:
            p1 = "PC"
            p2 = "User"
    elif gg == 1:
        p1 = "Player 1 "
        p2 = "Player 2 "
    return p1, p2

def pt(player,choice):
    global Mark
    if player % 2 != 0:
        turnlabel.config(text=f'{p1} chance')
        Mark = 'X'
        if p1 == "PC" and gt == 0:
            choice = random.randrange(1, 9)
        elif p1 == "PC" and gt == 1:
            pass
    elif player % 2 == 0:
        turnlabel.config(text=f'{p2} chance')
        Mark = 'O'
        if p2 == "PC" and gt == 0:
            choice = random.randrange(1, 9)
        elif p1 == "PC" and gt == 1:
            pass
    return Mark,choice

def gameplay(choice):
    global gg, gt, player, p1, p2
    turn(player)
    while (Game == Running):
        pt(player,choice)
        if CheckPosition(choice):
            board[choice] = Mark
            button[choice].config(text=str(Mark))
            player += 1
            CheckWin()
            if Game != Running:
                break
    if Game == retry:
        retryG()
    elif Game == Win:
        player -= 1
        if player % 2 != 0:
            print(f'{p1}  Won')
            turnlabel.config(text=f'{p1}  Won')
        else:
            print(f'{p2}  Won')
            turnlabel.config(text=f'{p2}  Won')


def raise_frame(frame):
    frame.tkraise()


root = Tk()

f1 = Frame(root)
f2 = Frame(root)
f3 = Frame(root)
f4 = Frame(root)

for frame in (f1, f2, f3, f4):
    frame.grid(row=0, column=0, sticky='news')

root.geometry("350x350")
root.title("X O Game")

# frame 1
welcome_label = Label(f1, text="Welcome to X O Game", font=20, padx=10, pady=10).grid(row=0, column=0, columnspan=4, )
playlabel = Label(f1, text="Play with : ", font=20, padx=10, pady=10).grid(row=1, column=0, rowspan=2)
PCg = Button(f1, text="PC", command=lambda gg=0: raise_frame(f2)).grid(row=1, column=1, padx=5, pady=5, ipadx=10,
                                                                       ipady=10)
Pl2g = Button(f1, text="Player 2", command=lambda gg=1: [raise_frame(f4)]).grid(row=2, column=1, padx=5, pady=5,
                                                                                ipadx=10, ipady=10)
exbut = Button(f1, text="exit", command=lambda: exit()).grid(row=3, column=1, ipadx=5, ipady=5, sticky="nsew")

# frame 2
xolabel1 = Label(f2, text="X O Game", font=30, padx=10, pady=10).grid(row=0, column=0, columnspan=4, )
fturnlabel = Label(f2, text="Who want to play first ? ", font=20, padx=10, pady=10).grid(row=1, column=0, columnspan=2)
PCtbut = Button(f2, text="PC", command=lambda player=2: raise_frame(f3)).grid(row=2, column=0, padx=5, pady=5, ipadx=10,
                                                                              ipady=10)
YOUtbut = Button(f2, text="You", command=lambda player=1: raise_frame(f3)).grid(row=2, column=1, padx=5, pady=5,
                                                                                ipadx=10, ipady=10)
backbut1 = Button(f2, text="back to menue", command=lambda: raise_frame(f1)).grid(row=3, column=0, ipadx=5, ipady=5,
                                                                                  columnspan=2)

# FRAME 3
xolabel2 = Label(f3, text="X O Game", font=30, padx=10, pady=10).grid(row=0, column=0, columnspan=4, )
typelabel = Label(f3, text="Choose game type ", font=20, padx=10, pady=10).grid(row=1, column=0, columnspan=2)
Hbut = Button(f3, text="Hard", command=lambda gt=1: raise_frame(f4)).grid(row=2, column=0, padx=5, pady=5, ipadx=10,
                                                                          ipady=10)  # gt means game type
Ebut = Button(f3, text="Easy", command=lambda gt=0: raise_frame(f4)).grid(row=2, column=1, padx=5, pady=5, ipadx=10,
                                                                          ipady=10)
backbut2 = Button(f3, text="back to menue", command=lambda: raise_frame(f1)).grid(row=3, column=0, ipadx=5, ipady=5,
                                                                                  columnspan=2)

# frame 4
toplabel = Label(f4, text="X O Game", font=20, padx=10, pady=10).grid(row=0, column=0, columnspan=3)
turnlabel = Label(f4, text=" ", font=16)
turnlabel.grid(row=1, column=0, columnspan=2)
button1 = Button(f4, text=" ", command=lambda: gameplay(1))
button1.grid(row=2, column=0, padx=5, pady=5, ipadx=10, ipady=10)
button2 = Button(f4, text=" ", command=lambda: gameplay(2))
button2.grid(row=2, column=1, padx=5, pady=5, ipadx=10, ipady=10)
button3 = Button(f4, text=" ", command=lambda: gameplay(3))
button3.grid(row=2, column=2, padx=5, pady=5, ipadx=10, ipady=10)
button4 = Button(f4, text=" ", command=lambda: gameplay(4))
button4.grid(row=3, column=0, padx=5, pady=5, ipadx=10, ipady=10)
button5 = Button(f4, text=" ", command=lambda: gameplay(5))
button5.grid(row=3, column=1, padx=5, pady=5, ipadx=10, ipady=10)
button6 = Button(f4, text=" ", command=lambda: gameplay(6))
button6.grid(row=3, column=2, padx=5, pady=5, ipadx=10, ipady=10)
button7 = Button(f4, text=" ", command=lambda: gameplay(7))
button7.grid(row=4, column=0, padx=5, pady=5, ipadx=10, ipady=10)
button8 = Button(f4, text=" ", command=lambda: gameplay(8))
button8.grid(row=4, column=1, padx=5, pady=5, ipadx=10, ipady=10)
button9 = Button(f4, text=" ", command=lambda: gameplay(9))
button9.grid(row=4, column=2, padx=5, pady=5, ipadx=10, ipady=10)
buttonretry = Button(f4, text="Retry").grid(row=5, column=0, padx=5, pady=5, ipadx=10, ipady=10, columnspan=3)
backbut = Button(f4, text="back to menue", command=lambda: raise_frame(f1)).grid(row=6, column=0, ipadx=5, ipady=5,columnspan=3)

button = ["", button1, button2, button3, button4, button5, button6, button7, button8, button9]
raise_frame(f1)

root.mainloop()
Asked By: PRO man

||

Answers:

It seems that the issue is caused by the line turnlabel.config(text=f'{p2} chance'). You should make sure that the turnlabel object exists and that it has the config method.

Also, you need to define p1 and p2 before you use them in the pt function.

Here is a corrected version of your code:

from tkinter import *
import random

player = 1
gt = 0
gg = 0
retry = 0
Win = 1
Running = 0
Game = Running
Mark = 'X'
board = {1: " ", 2: " ", 3: " ", 4: " ", 5: " ", 6: " ", 7: " ", 8: " ", 9: " "}

p1 = ""
p2 = ""

def CheckPosition(x):
    if board[x] == ' ':
        return True
    else:
        return False
Answered By: Aiden

I think you need to take a look at your game’s logic flow. Ignoring the formatting concerns, your buttons initiate the gameplay() function when it is clicked.

This launches a while loop with the condition of Game == Running. Within this while loop, the only time Game is changed is within CheckWin(), and unless there’s a win or a tie, Game is always changed to Running.

There is no way for it to exit this loop on the first few clicks. Something to consider is why the loop is required in the first place, or if it is even required at all? Also, even if it is necessary, having if Game != Running: break is unnecessary. If Game != Running at that position in the code, it would fail the while condition and exit the loop anyway.

def gameplay(choice):
    global gg, gt, player, p1, p2
    turn(player)
    pt(player,choice)
    if CheckPosition(choice):
        board[choice] = Mark
        button[choice].config(text=str(Mark))
        player += 1
        CheckWin()
    if Game == retry:
        retryG()
    elif Game == Win:
        player -= 1
        if player % 2 != 0:
            print(f'{p1}  Won')
            turnlabel.config(text=f'{p1}  Won')
        else:
            print(f'{p2}  Won')
            turnlabel.config(text=f'{p2}  Won')

Removing the while loop will get it to work, but there are still a lot of problems with the code. For example, in retryG() you are looping through button[i].config(...) for i in range(0,10). However, your button[0] is a string and has no .config(). Because of how tkinter works this won’t terminate your program, but it is throwing exceptions back. Also, the use of global variables when they are unnecessary can make your code more difficult to debug.

Lastly, for code readability, refer to the PEP 8 style guide so the code is more consistent and readable.

Answered By: Shorn
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.