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.
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
I'm trying to create a game that generates 2 random numbers and then the user has to type the correct answer of the product of it, then 1 point is gained. I'm trying to get it to stop once it's been done 10 times however I can't seem to get it to end. I tried using a loop rather than recursion but I also got stuck on that.
import tkinter as tk
from tkinter import *
import random
numbers = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
qm_score = 0
global recursion_count
recursion_count = 0
quickmulti_page = tk.Tk()
quickmulti_page.title =("Quick multiplication")
quickmulti_page.config(background="SlateGray1")
quickmulti_page.geometry("300x200")
def endgame():
print("Youre done")
print(qm_score)
def multiplication():
def multi_answer(event):
recursion_count = recursion_count + 1
if recursion_count == 10:
if user_answer == answer:
qm_score = qm_score + 1
endgame()
else:
endgame()
elif recursioncount > 3:
multiplication()
else:
endgame()
num1 = random.choice(numbers)
num2 = random.choice(numbers)
answer = num1 * num2
qlabel = Label(quickmulti_page, text=(num1,"x", num2), font=100, width=20, height=3).place(x=50,y=40)
user_answer = Entry(quickmulti_page,width=30)
user_answer.place(x=50, y=120)
user_answer.bind('<Return>', multi_answer)
I know that you can check if the entry box is empty by checking its length. I'm having a hard time implementing it though, because my entry boxes are dynamically created and you can't traverse in all of it in a single loop.
Here is my code:
from tkinter import *
class Window(Canvas):
def __init__(self,master=None,**kwargs):
Canvas.__init__(self,master,**kwargs)
self.frame = Frame(self)
self.create_window(0,0,anchor=N+W,window=self.frame)
self.row = 1
self.input_x = []
self.input_y = []
self.x_values = []
self.y_values = []
self._init_entries()
def _init_entries(self):
x_value = Label(self.frame, text='x', font='Helvetica 10 bold').grid(row = self.row, column = 2)
y_value = Label(self.frame, text='y', font='Helvetica 10 bold').grid(row = self.row, column = 3)
self.row += 1
def add_entry(self):
def validate_int_entry(text):
if text == "":
return True
try:
value = int(text)
except ValueError:
return False
return value
vcmd_int = (root.register(validate_int_entry), "%P")
x_value = Entry(self.frame, validate = "key", validatecommand=vcmd_int, justify = RIGHT, width=10)
x_value.grid(row = self.row, column = 2)
y_value = Entry(self.frame, validate = "key", validatecommand=vcmd_int, justify = RIGHT, width=10)
y_value.grid(row = self.row, column = 3)
self.row += 1
self.input_x.append(x_value)
self.input_y.append(y_value)
def save_entry(self):
self.x_values.clear()
self.y_values.clear()
for entry in self.input_x:
x = int(entry.get())
self.x_values.append(x)
print(self.x_values)
for entry in self.input_y:
x = int(entry.get())
self.y_values.append(x)
print(self.y_values)
if __name__ == "__main__":
root = Tk()
root.resizable(0,0)
root.title('Lot')
lot = Window(root)
lot.grid(row=0,column=0)
scroll = Scrollbar(root)
scroll.grid(row=0,column=1,sticky=N+S)
lot.config(yscrollcommand = scroll.set)
scroll.config(command=lot.yview)
lot.configure(scrollregion = lot.bbox("all"), width=1000, height=500)
def add_points():
lot.add_entry()
lot.configure(scrollregion = lot.bbox("all"))
b1 = Button(root, text = "Add points", command = add_points)
b1.grid(row=1,column=0)
def get_value():
b1.destroy()
lot.save_entry()
b2 = Button(root, text = "Get value!", command = get_value)
b2.grid(row=2,column=0)
root.mainloop()
Here's the GUI example wherein the user clicked the 'Add points' button 5 times but forgot to fill one of the entry boxes.
Since I set that the entry boxes can only accept 'int', then it will throw an error. How can I show a MessageBox every time an entry box is empty (and if it's possible, can tell the user what entry box is empty)?
I have change your add_entry function before adding new row it will check the both fields if it find it empty the warning message will popup.
def add_entry(self):
for entry in self.input_x:
if entry.get() is '':
return messagebox.showwarning('Warning', 'Empty Fields')
for entry in self.input_y:
if entry.get() is '':
return messagebox.showwarning('Warning', 'Empty Fields')
def validate_int_entry(text):
if text == "":
return True
try:
value = int(text)
except ValueError:
return False
return value
vcmd_int = (root.register(validate_int_entry), "%P")
x_value = Entry(self.frame, validate = "key", validatecommand=vcmd_int, justify = RIGHT, width=10)
x_value.grid(row = self.row, column = 2)
y_value = Entry(self.frame, validate = "key", validatecommand=vcmd_int, justify = RIGHT, width=10)
y_value.grid(row = self.row, column = 3)
self.row += 1
self.input_x.append(x_value)
self.input_y.append(y_value)
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 ]
from tkinter import *
import tkinter as tk
q = 0
s = -1
count = 0
correct = 0
incorrect = 0
question = ["Is this a quiz","Are you sure","Dont be","see its not a quiz"]
answer = ["yes","yes","ok","ok"]
answer_cap = ["Yes","Yes","Ok","Ok"]
root = Tk()
name = tk.Label(root,text = "GUI Quiz")
name.pack()
label = tk.Label(root,text = question[0])
label.pack()
entry = tk.Entry(root)
entry.pack()
def out():
global q,correct,incorrect,s,count
count = count + 1
ans = entry.get()
print (ans)
print (question[q])
print (answer[q])
if count < 4:
if answer[q] or answer_cap[q] == ans :
q = q + 1
entry.delete(0, END)
correct = correct + 1
label.config(text = question[q])
else:
q = q + 1
entry.delete(0, END)
incorrect = incorrect + 1
label.config(text = question[q])
else:
entry.delete(0, END)
label.config(text = "Correct: "+str(correct) + " Incorrect: "+str(incorrect))
def stop():
global q,correct,incorrect
q = 0
correct = 0
incorrect = 0
entry.delete(0, END)
label.config(text = question[0])
button = tk.Button(root,text = "Submit",command = out)
button.pack()
button_two = tk.Button(root,text = "Restart",command = stop)
button_two.pack()
root.mainloop()
nothing actually wrong with the code its just how I'm doing it. When I run module it will ask my four questions and I will give the answer, but no matter what I put it will say I got 3 correct and none wrong. Am I missing something obvious or is it how I layed out the code.
The first part of your out function should not have 'count = count + 1' because this adds one to you score regardless of weather you were right or wrong; relocate the commented code.
def out():
global q,correct,incorrect,s,count
#count = count + 1
ans = entry.get()
print (ans)
print (question[q])
print (answer[q])