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.
Related
from tkinter import *
import random
command_list = []
def next_turn(r, c):
global player
global command_list
global game_started
command_list.append((r, c))
if buttons[r][c]['text'] == "" and check_winner() is False:
if player == players[0]:
buttons[r][c]['text'] = player
game_started = True
if check_winner() is False:
player = players[1]
player_label.configure(text=(player + "'s turn"))
elif check_winner() is True:
player_label.configure(text=(player + " WINS!"))
elif check_winner() == 'Tie':
player_label.configure(text='TIE!')
else:
buttons[r][c]['text'] = player
if check_winner() is False:
player = players[0]
player_label.configure(text=(player + "'s turn"))
elif check_winner() is True:
player_label.configure(text=(player + " WINS!"))
elif check_winner() == 'Tie':
player_label.configure(text='TIE!', bg='yellow')
def check_winner():
# rows wise
for r in range(3):
if buttons[r][0]['text'] == buttons[r][1]['text'] == buttons[r][2]['text'] != "":
buttons[r][0].configure(bg='green')
buttons[r][1].configure(bg='green')
buttons[r][2].configure(bg='green')
return True
# column wise
for c in range(3):
if buttons[0][c]['text'] == buttons[1][c]['text'] == buttons[2][c]['text'] != "":
buttons[0][c].configure(bg='green')
buttons[1][c].configure(bg='green')
buttons[2][c].configure(bg='green')
return True
# diagonal wise
if buttons[0][0]['text'] == buttons[1][1]['text'] == buttons[2][2]['text'] != "":
buttons[0][0].configure(bg='green')
buttons[1][1].configure(bg='green')
buttons[2][2].configure(bg='green')
return True
if buttons[0][2]['text'] == buttons[1][1]['text'] == buttons[2][0]['text'] != "":
buttons[0][2].configure(bg='green')
buttons[1][1].configure(bg='green')
buttons[2][0].configure(bg='green')
return True
if empty_space():
return False
return "Tie"
def empty_space():
for r in range(3):
for c in range(3):
if buttons[r][c]['text'] == '':
return True
return False
def new_game():
global player
player = random.choice(players)
player_label.configure(text=player + "'s turn")
for r in range(3):
for c in range(3):
buttons[r][c].configure(text="", bg='grey')
def undo():
global player
if check_winner() is False and len(command_list) != 0:
undo_row, undo_column = command_list[-1][0], command_list[-1][1]
buttons[undo_row][undo_column]['text'] = ''
if player == players[1]:
player = players[0]
player_label.configure(text=(player + "'s turn"))
else:
player = players[1]
player_label.configure(text=(player + "'s turn"))
command_list.pop()
mainWindow = Tk()
mainWindow.title("Tic-Tac-Toe")
mainWindow.configure(background='grey')
players = ["X", "O"]
# pick a random player.
player = random.choice(players)
# end button
end_button = Button(mainWindow, text="Close", background='red', font=('consolas', 20), command=mainWindow.destroy)
end_button.pack(anchor='w')
player_label = Label(mainWindow, text=player + "'s turn", font=('consolas', 40))
player_label.pack(side='top')
reset_button = Button(mainWindow, text='New Game', font=('consolas', 20), command=new_game)
reset_button.pack(side='top')
# undo button
undo_button = Button(mainWindow, text='Undo', font=('consolas', 20), command=undo)
undo_button.pack(side='top', anchor='e')
# Buttons structure
buttons = [[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]
# Game Board.
board = Frame(mainWindow)
board.configure(background='grey')
board.pack()
for row in range(3):
for column in range(3):
buttons[row][column] = Button(board, text="", font=('consolas', 40), width=5, height=2,
command=lambda bt_row=row, bt_column=column:
next_turn(bt_row, bt_column))
buttons[row][column].grid(row=row, column=column)
buttons[row][column].configure(background='grey')
mainWindow.mainloop()
The above program is a game called Tic-Tak-Toe.
I am able to run the program on IDE without any error.
This is the program that i want to run on windows or linux or any other platform without using the IDE or command line, just like other application such as word, execel , halo 3(game) etc. How can I do it ?
You need to target an operating system and create an executable file. For example you could create a c program that calls your .py pgoram. Below is an example of how to do that for windows.
For windows - I used windows Ubuntu linux subsystem to create the executable targeting windows 64-bit:
sudo apt-get install mingw-w64. Read more.
make new file game.c
#include <stdlib.h>
int main() {
system("py ./temp.py");
return 0;
}
Put your game.py and game.c in the same folder and run
x86_64-w64-mingw32-gcc -o game.exe game.c
Working Picture
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.
hello i have a code that looks like this
from multiprocessing import Process
from tkinter.messagebox import *
from time import sleep
def timerclose():
sumtimer = 0
while sumtimer <= 10 :
sleep(0.1)
sumtimer = sumtimer + 0.1
print("sumtimer",sumtimer)
return sumtimer
def conout():
confirmation = askokcancel ("confirmation","are you sure ?")
return confirmation
if __name__=='__main__':
p1 = Process(target=timerclose)
p1.start()
p2 = Process(target=conout)
p2.start()
I wanted to create an askokcancel message box with a timeout. i want the messagebox to popout to ask the user if we wants to exit or not and simultaneously starts a counter. after 10 seconds if the user does not press anything (ok or cancel) i would get the return value from the timerclose ignore the conout function and continue with the rest of the programm.
i solve it with one process and a shared value
def conout(n):
n.value = int(0)
confirmation = askokcancel ("confirmation","Σε 10 sec κλείνω Οκ ?")
if confirmation == True :
n.value = int(1)
else:
n.value = int(2)
if __name__=="__main__":
p2 = Process(target=conout, args=(num,))
p2.start()
timerls = 0
while timerls <= 10:
sleep(0.25)
timerls += 0.25
print("timerls",timerls)
if num.value == 1 :
print ("end true",num.value)
break
elif num.value == 2:
print ("end false", num.value)
break
else:
print ("end0", num.value)
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()
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 ]