Command function for button "resets" - python

So in my tkinter python program I am calling on a command when a button is clicked. When that happens it runs a function but in the function I have it set a label to something on the first time the button is clicked and after that it should only update the said label. Basically after the attempt it changes the attempt to 1 ensuring the if statement will see that and not allow it to pass. However it keeps resetting and I don't know how to stop it. When you click the button no matter first or third the button resets and proof of that occurs because the h gets printed. It's as if the function restarts but it shouldn't since it's a loop for the GUI.
def fight(): #Sees which one is stronger if user is stronger he gets win if no he gets loss also displays enemy stats and removes used characters after round is finished
try:
attempt=0
namel = ""
namer=""
left = lbox.curselection()[0]
right = rbox.curselection()[0]
totalleft = 0
totalright = 0
if left == 0:
namel = "Rash"
totalleft = Rash.total
elif left==1:
namel = "Untss"
totalleft = Untss.total
elif left==2:
namel = "Illora"
totalleft = 60+35+80
if right == 0:
namer = "Zys"
totalright = Zys.total
elif right==1:
namer = "Eentha"
totalright = Eentha.total
elif right==2:
namer = "Dant"
totalright = Dant.total
lbox.delete(lbox.curselection()[0])
rbox.delete(rbox.curselection()[0])
print(namel)
print(namer)
if attempt == 0:
wins.set("Wins")
loss.set("Loss")
print("h")
attempt=1
if (totalleft>totalright):
wins.set(wins.get()+"\n"+namel)
loss.set(loss.get()+"\n"+namer)
else:
wins.set(wins.get()+"\n"+namer)
loss.set(loss.get()+"\n"+namel)
except IndexError:
pass
Also for those of you who saw my previous question I still need help with that I just also want to fix this bug too.

At beginning of function fight you set attempt = 0 so you reset it.
Besides attempt is local variable. It is created when you execute function fight and it is deleted when you leave function fight. You have to use global variable (or global IntVar)
attempt = 0
def fight():
global attempt
BTW: of you use only values 0/1 in attempt then you can use True/False.
attempt = False
def fight():
global attempt
...
if not attempt:
attempt = True

Related

Time.sleep() not pausing the correct moment?

Hello I have created a quiz using python and tkinter. After each option is pressed I wanted the correct answer to turn green and the three incorrect to turn red then revert to the default for the next question.The problem here being that running the code will take the buttons to the default before the user can see the colours. To do this I tried to use time.sleep() in the function however no matter where I use it it just seems to pause on the button being pressed down and then goes onto the next question without seeing any colour change.
Here is the relevant piece of code
def entry(num):
global score
global x
global count
count +=1
if Qa[x] == 1:
option1.config(bg = "green")
option2.config(bg = "red")
option3.config(bg="red")
option4.config(bg="red")
elif Qa[x] == 2:
option1.config(bg="red")
option2.config(bg="green")
option3.config(bg="red")
option4.config(bg="red")
elif Qa[x] == 3:
option1.config(bg="red")
option2.config(bg="red")
option3.config(bg="green")
option4.config(bg="red")
elif Qa[x] == 4:
option1.config(bg="red")
option2.config(bg="red")
option3.config(bg="red")
option4.config(bg="green")
if num == Qa[x]:
score += 1
x +=1
if count <10:
my_label.config(text = Qs[x])
option1.config(text = (question_prompts[x])[1],bg = "SystemButtonFace",command = lambda: entry(1) )
option2.config(text=(question_prompts[x])[2],bg = "SystemButtonFace",command = lambda: entry(2) )
option3.config(text=(question_prompts[x])[3],bg = "SystemButtonFace",command = lambda: entry(3) )
option4.config(text=(question_prompts[x])[4],bg = "SystemButtonFace",command = lambda: entry(4) )
else:
End_score =Label(text = "Well done you scored" +" "+ str(score)+" " +"out of 11", font = 40)
End_score.place(relx=0.5,rely =0.5,anchor = CENTER)
print(x,score, count, Qa[x])
I haven't put the time.sleep() in here because I have tried it everywhere in this section an it gives the same result
I would really appreciate some help
The PROBLEM here is that the options will not actually change color until Tk can get back to its main loop. As long as you are running your function, the main loop cannot pull new events. You need to set the colors, then use root.after to schedule a callback at some point in the future where you reset to all green.

Getting the computer to press a button

I'm making a tic tac toe game using tkinter for the GUI but my issue is, since i've got a function (that makes the moves) to run each time a button is clicked, it won't automatically make a move until I click a button (it doesn't matter which one) which hence stuffs up my moves indexing, and also means you have to click before the computer makes a move.
Is there anyway I can get the 'computer' itself to pretend to click a button, hence initiating the function?
Here's the make button bit:
def make_button(n, row, col):
button_list[n] = Button(tk,bg='gray', text = " ", fg='white',height=4,width=8,command=lambda:ttt(n, button_list))
button_list[n].grid(row=row,column=col,sticky = S+N+E+W)
and here's the make move bit (its wip so don't mind the fact that currently computer move will only play the middle or the corners):
def computer_move(buttons, index):
global bclick
buttons["text"] = "O"
COM.add(index)
bclick = True
buttons=StringVar()
bclick = True
corner_moves = {0,2,6,8}
def ttt(n, buttons):
global bclick
if n not in P and n not in COM and bclick == True:
button_list[n]["text"] = "X"
P.add(n)
bclick = False
elif bclick == False and 4 not in COM and 4 not in P:
computer_move(button_list[4], 4)
elif bclick == False:
corners_not_COM = (corner_moves.difference(COM))
corners_not_P_or_COM = (corners_not_COM.difference(P))
list_corners_not_P_or_COM = list(corners_not_P_or_COM)
random_corner_index = random.randint(0,len(list_corners_not_P_or_COM))
random_corner = list_corners_not_P_or_COM[random_corner_index]
computer_move(button_list[random_corner], random_corner)
Try using:
computer_move.invoke()
it has the same effect as clicking on the button it should work in your case. It calls the function. You can call it after you have moved and it will call computer_move for you. Happy coding!

Is there anyway I can make an if statement about an led on a button-shim being a certain color?

I am currently making a burglar alarm for a school project. I am trying to make a button that will disable the alarm when pressed. I originally thought to have a variable change when the button shim is pressed but, while the rest of the activities in the if loop happen, the variable is not being changed.
My code looks like this:
while (check1 == 0):
if (bE == 0): #if button E has not been pressed
if (check() = 1): # a function that returns if there is moton
check1 = 1
#buttonshim.on_press(buttonshim.BUTTON_E)
def button_e(button, pressed):
buttonshim.set_pixel(0xff, 0x00, 0x00) #changes led to red no prob
bE = 1 #supposed to change variable to 1 not working
print "button e pressed" #prints out fine
time.sleep(sleeptime) #so it's not checking constantly
else:
check1=1 #so it breaks out of while loop is E is pressed
I had already defined check1 and bE as variables before this code segment.
This is not working properly and I was wondering if there is any way that I can detect if the led is red so I can make an if statement and set the variable through that?
The syntax error in your first line might be the issue. Same with your if .statements
while (check1 = 0): #should be while (check1 == 0):
# rest of the code

How to make while loop keep going while still looking for input in Python

I am making a Cookie clicker like game in Python, and I am trying to have the while loop keep going so it checks if a second has gone (so it adds "cookies") while still looking if the user is making an input (clicking on "Cookie").
Whenever I try this it waits for the input instead of doing the rest of the loop.
This is what my current code looks like (There's more of course):
While True:
console.clear()
cookieText = "You have " + str(cookies) + " cookies"
print cookieText
clicker = raw_input("")
if clicker == "":
cookies += clickerPower
more...
This is what I want to add:
While True:
last = time()
if last == timer:
timer = last
more...
this worked for me (source)
import msvcrt
num = 0
done = False
while not done:
print num
num += 1
if msvcrt.kbhit():
print msvcrt.getch()
done = True
The answer is threading. But it's not simple.

Function called without being told to

Newish to python, working on a text adventure, testing out the use of functions.
def cell1():
loop = 1
while loop == 1:
print("ONE")
cave1 = input()
if cave1 == ("end?"):
print("\nthis should end program")
loop = 0
break
elif cave1 == ("TWO"):
global testvar
testvar = 1
option1()
else:
print("INVALID")
def option1():
print("TWO")
loop = 1
while loop == 1:
print("test1 definition")
print (testvar)
test1 = input()
if test1 == ("ONE"):
print("you pick up the cheese")
loop = 0
cell1()
elif test1 == ("THREE"):
option2()
else:
print("INVALID")
def option2():
print("THREE")
loop = 1
while loop == 1:
print("This is option 3")
test2 = input()
if test2 == ("ONE"):
print("testering2")
cell1()
elif test2 == ("TWO"):
global testvar
testvar = 2014
option1()
else:
print("INVALID")
run = True
while run == (True):
print ("testing 123")
cell1()
print("restart about to activate")
cont = input("Restart? ")
if (cont) != "yes":
break
This program should allow you to go between options (what would be rooms) and eventually in cell1, the program should be end-able.
if the program is run and "end?" is typed as the first input, the program goes into the continue bit at the bottom, however, if you go between the 'rooms' then back to cell1, typing "end?" will call option 2.
Ive had a look around and it is still baffling me, am i ding something wrong?
Any help is appreciated, thank you.
The reason "end?" only quits for the player when they are within the first cell is because you're only checking for that input therein. The execution contained within option1() and option2() doesn't affect the execution of cell1(). You're not returning anything from your option functions, nor are you changing a sentinel value.
So, there's two basic ways you could go about this.
First, you could return a value from your functions:
if option1() == "END":
break
Or, you could alter your while loop:
# is_running is defined globally
while is_running:
And then just set is_running to False in any of your methods whenever the user types "end?". That'd probably be the easiest way with the design you're using now.
I'm sure you can tell, though, that in general your program is going to get exponentially more complex as you add more rooms and your function calls get further nested.
I'm pretty sure that the issue you're having is because you don't always break out of the loop in one function when you call another function. For instance, if your entries were TWO, ONE then end?, you'd find yourself still in the cell1 loop. That's because when the inner call to cell1 returns, the control flow of the program goes back to where that function was called from, which is option1, since loop is now 0, the loop ends and option1 returns, to the outer call to cell1, where the loop is still running.
Unless you want the game you're designing to have a tree structure, where you can return to where you came from with different semantics than moving to some other place, I'd suggest using a different architecture. Rather than each of your functions calling the next function when appropriate, return that function instead. Then you'd write a single top level loop that calls the function. Here's an example where the function to be called by the top level loop is saved in a variable named state:
def cell1():
print("In cell1!")
while True:
choice = input("pick 'ONE' or 'TWO' (or type 'quit' to exit):")
if choice == "ONE":
return option1
elif choice == "TWO":
return option2
elif choice == "quit":
return None
else:
print("I'm sorry, I didn't understand that.")
def option1(): # these other two functions are very basic in my example
print("In option1!") # but you can make them as complex as you want
return option2
def option2():
print("in option2!")
return cell1
def control_loop(initial_state=cell1):
state = initial_state
while state is not None:
state = state() # the next state is the return value of the previous state
The problem is you are getting deeper and deeper within nested functions. For example, changing
if test1 == ("ONE"):
print("you pick up the cheese")
loop = 0
cell1()
to
if test1 == ("ONE"):
print("you pick up the cheese")
loop = 0
break
will allow you to run your program, enter room two, go back to room one, and "end?" will work properly. This won't fix your issues completely though because there is a similar problem where when you go from two to three where if you simply changed
if test2 == ("ONE"):
print("testering2")
cell1()
to
if test2 == ("ONE"):
print("testering2")
break
it would break the current function and go back into option1() (if you run your program, go to room two, then to room three, then back to one) where "end?" doesn't do anything. Hopefully this gets you on the right track.

Categories