How to make python wait for it's turn (tkinter) - python-3.x

Right now the code executes executes the following "if statement" under the computer_move function *. I want it to wait for the player to click another button. Right now, the code places the x before the player clicks a button to place an "o".
import tkinter as tk
board = tk.Tk()
def player_move(widget):
if widget["o"] not in ("o", "x"):
widget["text"] = "o"
widget["state"] = "disabled"
computer_move()
def computer_move():
if i["text"] == "Open Space":
i["text"] = "x"
i["state"] = "disabled"
else:
c["text"] = "x"
c["state"] = "disabled"
if a["text"] and c["text"] == "x" or "o": # *
b["text"] = "x"
b["state"] = "disabled"
board.geometry("400x500")
board.title("Board")
buttons = []
a = tk.Button(board, text="x", state = "disabled")
a["command"] = lambda x=a:player_move(x)
a.grid(row=0, column = 0)
buttons.append(a)
board.mainloop()

Code doesn't set x but you do it in line
a = tk.Button(board, text="x", state= "disabled")
so remove text="x", state="disabled"
BTW:
widget["o"] is incorrect - button doesn't have property with name "o".
It has property "text" - widget["text"] - which may have value "o" or "x"
if a["text"] and c["text"] == "x" or "o": is rather incorrent. Especially
c["text"] == "x" or "o"
It has to be
c["text"] == "x" or c["text"] == "o"
or
c["text"] in ("x", "o")
I think you try to do
if a["text"] in ("x", "o") and c["text"] in ("x", "o"):
It is better to keep button on list - you can use for loop to check all buttons in computer_move
import tkinter as tk
# --- functions ---
def player_move(btn):
# if button is empty
if btn["text"] not in ("o", "x"):
# then set `o` and disable button
btn["text"] = "o"
btn["state"] = "disabled"
# and make comuter move
computer_move()
def computer_move():
# check all buttons
for btn in buttons:
# if button is empty
if btn["text"] not in ("o", "x"):
# then set `x` and disable button
btn["text"] = "x"
btn["state"] = "disabled"
# and skip checking other buttons
break
# --- main ---
board = tk.Tk()
board.geometry("400x500")
board.title("Board")
buttons = []
for row in range(3):
for col in range(3):
btn = tk.Button(board, width=1)
btn["command"] = lambda x=btn:player_move(x)
btn.grid(row=row, column=col)
buttons.append(btn)
board.mainloop()

Related

Update a checkbox based on selected values of another checkbox

I want to have a select all checkbox in my PySimpleGUI. When the select all checkbox is selected, all other checkboxes should change to True, and if any other box is unchecked, the select all checkbox should change to false state?
I can do it through button clicks, but I couldn't find a way to update checkboxes based on values selected in an another checkbox?
import PySimpleGUI as sg
layout = [
[sg.Checkbox ('select all', key = 'checkbox')],
[sg.Checkbox ('value 1', key='check_value1')],
[sg.Checkbox ('value 2',key='check_value2')],
[sg.Button ('ON', key = 'ON')],
[sg.Button ('OFF', key = 'OFF')]
]
window = sg.Window ('Sample GUI', layout) .Finalize ()
while True: # Event Loop
event,values=window.read()
if event in (None, 'Exit'):
break
elif event == 'ON':
window ['checkbox']. Update (value = True)
elif event == 'OFF':
window ['checkbox']. Update (value = False)
print(event,values)
window.close ()
Is there any way to implement this?
Option value or first argument in method upgrade if True checks the checkbox, False clears it,
Demo code,
import PySimpleGUI as sg
sg.theme('DarkBlue')
layout = [
[sg.Checkbox('All checked', enable_events=True, key='Check_All'),
sg.Checkbox('All unchecked', enable_events=True, key='Uncheck_All')],
[sg.HorizontalSeparator()]] + [
[sg.Checkbox(f'check ({j}, {i})', enable_events=True, key=f'check{j}{i}')
for i in range(5)] for j in range(4)
]
window = sg.Window ('Sample GUI', layout, finalize=True)
while True: # Event Loop
event, values = window.read (timeout = 100)
if event == sg.WINDOW_CLOSED:
break
elif event == 'Check_All':
for j in range(4):
for i in range(5):
window[f'check{j}{i}'].update(True)
window['Uncheck_All'].update(False)
elif event == 'Uncheck_All':
for j in range(4):
for i in range(5):
window[f'check{j}{i}'].update(False)
window['Check_All'].update(False)
elif event.startswith('check'):
if not values[event]:
window['Check_All'].update(False)
else:
window['Uncheck_All'].update(False)
window.close ()
Update Of the method Value Switch parameters.
In the example below, if you press the ON button, a check will be entered, and if you press the OFF button, the check will be removed.
import PySimpleGUI as sg
from PySimpleGUI import Checkbox, Button
layout = [
[sg.Checkbox ('checkbox', key = 'checkbox')],
[sg.Button ('ON', key = 'ON')],
[sg.Button ('OFF', key = 'OFF')]
]
window = sg.Window ('Sample GUI', layout) .Finalize ()
while True: # Event Loop
event, values ​​= window.read (timeout = 100)
if event in (None, 'Exit'):
break
elif event == 'ON':
window ['checkbox']. Update (value = True)
elif event == 'OFF':
window ['checkbox']. Update (value = False)
window.close ()
For more you can refer to this docs also https://pysimplegui.readthedocs.io/en/latest/call%20reference/#checkbox-element

tkinter only works via functions?

I've made a tic tac toe game using PyCharm IDE. I've tried to make it run with tkinter but i got some issues.
My program asks the user to choose between X and O , also if X plays first or second. Also if u were to put incorrect answer the program would tell the user to retype his/her answer (with a while statement). On tkinter I can't make that, for example when the program asks "Do you want X or O" and the user types X and then ok_button, it does not store that information anywhere. And if I try to put in a while loop, it goes on an infinity loop (since it loops through the first answer the user clicked ok)
My question is how can I create a sequence since tkinter runs with classes and functions (at least i dont know something else). For example: Program asks "Do you want to be X or O?", after putting correct input to entry, the program should ask "Do you want to go first or second?".
from tkinter import *
def name_choose(x):
# "print" message to Label
message["text"] = player_decide(x)[2]
# how do i store that info below ? so i can use it later
player_1 =player_decide(x)[0]
player_2 =player_decide(x)[1]
window = Tk()
....
message = Label(window_frame1)
message.place(relwidth=0.5, relheight=1)
entry = Entry(window_frame1)
entry.place(relx=0.55, relwidth=0.2, relheight=1)
button_Ok = Button(window_frame1, text="Ok", command = lambda: name_choose(entry.get()) )
button_Ok.place(relx=0.8, relwidth=0.2, relheight=1)
....
window.mainloop()
def player_decide(player_1):
player_2 = ""
if player_1.upper() == "X":
message = "Player 1 : X , Player 2 : O"
player_2 = "O"
game_status = 1
elif player_1.upper() == "O":
player_2 = "X"
message = "Player 1 : O , Player 2 : X"
game_status = 1
else:
message = "Retry Input"
game_status = 0
return player_1, player_2, message , game_status
Here is the fixed code:
from tkinter import *
def name_choose(x):
# "print" message to Label
message["text"] = player_decide(x)[2]
# how do i store that info below ? so i can use it later
player_1 =player_decide(x)[0]
player_2 =player_decide(x)[1]
window = Tk()
....
message = Label(window_frame1)
message.place(relwidth=0.5, relheight=1)
entry = Entry(window_frame1)
entry.place(relx=0.55, relwidth=0.2, relheight=1)
button_Ok = Button(window_frame1, text="Ok", command = lambda: name_choose(entry.get()) )
button_Ok.place(relx=0.8, relwidth=0.2, relheight=1)
....
def player_decide(player_1):
player_2 = ""
if player_1.upper() == "X":
message = "Player 1 : X , Player 2 : O"
player_2 = "O"
game_status = 1
elif player_1.upper() == "O":
player_2 = "X"
message = "Player 1 : O , Player 2 : X"
game_status = 1
else:
message = "Retry Input"
game_status = 0
return player_1, player_2, message , game_status
window.mainloop()
The problem was because you had the function defined after the mainloop. Make sure all the code is run before the mainloop starts.

Tic-tac-toe using python tkinter

Tic-tac-toe game using python tkinter is not working correctly.
Tic-tac-toe structure is correct. I just want to change the click event.
Only button9 output shown when click to any button
Every time I click any button this output is shown
from tkinter import *
bclick = True
tk = Tk()
tk.title("Tic Tac toe")
tk.geometry("300x400")
n = 9
btns = []
def ttt(button):
global bclick
print(button)
if button["text"] == "" and bclick == True:
print("if")
button.config(text="X")
bclick = False
elif button["text"] == "" and bclick == False:
print("else")
button["text"] = "0"
bclick = True
for i in range(9):
btns.append(Button(font=('Times 20 bold'), bg='white', fg='black', height=2, width=4))
row = 1
column = 0
index = 1
print(btns)
buttons = StringVar()
for i in btns:
i.grid(row=row, column=column)
i.config(command=lambda: ttt(i))
print(i, i["command"])
column += 1
if index % 3 == 0:
row += 1
column = 0
index += 1
tk.mainloop()
Common misstake. The lambda function is using the last value assigned to i so every lambda will use i=.!button9. change the lambda function to:
i.config(command=lambda current_button=i: ttt(current_button))
which will make lambda use the value of i when the lambda was created.

Name is not defined

this is my code for connect four so far, the error is coming up
NameError: name 'CheckWinVt' is not defined
i'm not sure how to fix this can anyone help?
class ConnectFourBoard:
def __init__(self, cols = 7, rows = 6, requiredToWin = 4):
self.__space = ''
self.__board = []
self.cols = cols
self.rows = rows
self.Win = requiredToWin
self.__board = [[''] * cols for i in range(rows)]
def MakeMove(self, row, col, element):
global __board
self.__board[row][col] = element
def CheckWin(board):
print("Check Winner")
CheckWinVt(board)
CheckWinHz(board)
CheckWinDiag(board)
def CheckWinVt(board):
for x in range(rows):
for y in range(columns):
if (board[(x,y)] == "X" and board[(x+1,y)] == "X" and board[(x+2,y)] == "X" and board[(x+3,y)] == "X"):
print ("Winner == HumanPlayer")
break
elif (board[(x,y)] == "O" and board[(x+1,y)] == "O" and board[(x+2,y)] == "O" and board[(x+3,y)] == "O"):
print ("Winner == ComputerPlayer")
break
def CheckWinHz(board):
for x in range(rows):
for y in range(columns):
if (board[(x,y)] == "X" and board[(x,y+1)] == "X" and board[(x,y+2)] == "X" and board[(x,y+3)] == "X"):
print ("Winner == HumanPlayer")
break
elif (board[(x,y)] == "O" and board[(x,y+1)] == "O" and board[(x,y+2)] == "O" and board[(x,y+3)] == "O"):
print ("Winner == ComputerPlayer")
break
def CheckWinDiag(board):
for x in range(rows):
for y in range(columns):
if (board[x,y] == "X" and board[(x+1,y+1)] == "X" and board[(x+2,y+2)] == "X" and board[(x+3,y+3)] =="X"):
print ("Winner == HumanPlayer")
elif (board[x,y] == "O" and board[(x+1,y+1)] == "O" and board[(x+2,y+2)] == "O" and board[(x+3,y+3)] =="O"):
print ("Winner == ComputerPlayer")
elif (board[x,y] == "X" and board[(x-1,y-1)] == "X" and board[(x-2,y+2)] == "X" and board[(x-3,y+3)] =="X"):
print ("Winner == HumanPlayer")
elif (board[x,y] == "O" and board[(x-1,y-1)] == "O" and board[(x-2,y+2)] == "O" and board[(x-3,y+3)] =="O"):
print ("Winner == ComputerPlayer")
def FullBoard(self):
row = ""
for x in range (6):
for y in range (7):
row += self.__board[x][y]
if "" in row:
return False
row = ""
return True
def FreeSpace(self, row, col):
if self.__board[row][col] == "":
return True
return False
def show_board_dynamic(self):
print()
print("-------")
for i in range(len(self.__board)):
for j in range(len(self.__board[0])):
print("|", end = "")
print(self.__board[i][j], end = ""),
print("|")
print("-------")
print()
in my main class:
winner = gboard.CheckWin()
all your functions of the form
def CheckWin(board):
...
CheckWinVt(board)
should probably implemented this way (and access the board in this manner):
def CheckWin(self):
board = self.__board # if you need to do stuff with board
# or just access self.__board directly
self.CheckWinVt()
....

What is wrong with my elif statement? Invalid Syntax

if option == "1":
with open("sample.txt","r") as f:
print(f.read())
numbers = []
with open("sample2.txt","r") as f:
for i in range(9):
numbers.append(f.readline().strip())
print(numbers)
from random import randint
for i in range(9):
print(numbers[randint(0,8)])
from tkinter import *
def mhello():
mtext = ment.get()
mLabel2 = Label(test, text=mtext).pack()
return
test = Tk()
ment = StringVar()
test.geometry('450x450+500+10')
test.title('Test')
mlabel = Label(test, text='Time to guess').pack()
mbutton = Button(test, text='Click', command = mhello).pack()
mEntry = Entry(test, textvariable=ment).pack()
test.mainloop()
from tkinter import *
def mhello():
my_word = 'HELLO'
mtext = ment.get()
if my_word == mtext:
mLabel2 = Label(test, text='Correct').pack()
else:
mLabel2 = Label(test, text='Incorrect').pack()
return
test = Tk()
ment = StringVar()
test.geometry('450x450+500+300')
test.title('Test')
def label_1():
label_1 = Label(test, text='Hello. Welcome to my game.').pack()
def label_2():
label_2 = Label(test, text='What word am I thinking of?').pack()
button_1 = Button(test, text='Click', command = mhello).pack()
entry_1 = Entry(test, textvariable=ment).pack()
label_1()
test.after(5000, label_2)
test.mainloop()
from tkinter import *
from random import shuffle
game = Tk()
game.geometry('200x200')
game.grid()
game.title("My Game")
board = [1, 2, 3, 4, 5, 6, 7, 8, 9]
def board_1():
board1 = []
k = 0
for i in range(3):
for j in range(3):
board1.append(Label(game, text = board[k]))
board1[k].grid(row = i, column = j)
k +=1
def board_2():
shuffle(board)
board2 = []
k = 0
for i in range(3):
for j in range(3):
board2.append(Label(game, text = board[k]))
board2[k].grid(row = i, column = j)
k +=1
board_1()
game.after(5000, board_2)
game.mainloop()
#2nd Option
elif option == "2":
print ("You have chosen option 2. Well Done, You Can Type! XD")
The bit that has the Syntax Error is the 1st elif statement (2nd Option). Ignore all the code prior to this if necessary (it is there for context). Whenever I run the code it says that there is a syntax error and just positions the typing line (I don't know what it's called) at the end of the word elif.
This is a simple fix, with if else statements you need to have a closing ELSE and in this case there is not so when your program runs it sees that theres a lonely if without its else :)
if option == "1":
elif option == "2":
else:
'do something else in the program if any other value was recieved'
also a switch statement can be used here so it does not keep checking each condition and just goes straight to the correct case :D
The problem is that your block is separated from the first if-statement, where it actually belongs to. As it is, it follows the game.mainloop() statement, and adds an unexpected indentation. Try to rearrange your code like so:
if option == "1":
with open("sample.txt","r") as f:
print(f.read())
numbers = []
with open("sample2.txt","r") as f:
for i in range(9):
numbers.append(f.readline().strip())
print(numbers)
from random import randint
for i in range(9):
print(numbers[randint(0,8)])
elif option == "2":
print ("You have chosen option 2. Well Done, You Can Type! XD")
[ Rest of the code ]

Resources