I have made a digital version of a pen-and-paper game as my first major python practice project. You can see from the attached picture that the main board consists of buttons. They can be toggled between two states: they start displaying a number and are True
, when clicked they display an "X" and become False
. You will see from the screenshot that there is a score multiplier that tells you how many points you get for each row depending on how many buttons are displaying "X", i.e. in the False
state.
At the moment the user has to enter the score manually for each row. What I'm trying to do is have the appropriate score appear in the appropriate box depending on the number of buttons that are False
. For example, if four red buttons have been clicked, so are False
, 10 would be displayed in the red Score box.
The help I am seeking: I do not know how to check the current boolean state of each button, nor do I know how to total the results.
I am very new to programming and am learning for fun. I do not want or expect a whole program to be written for me that I can copy and paste; I would like to be pointed in the right direction.
I have included below just the code relevent to the main board (the 4 coloured rows) and the score boxes. Below I have included the code for just the red row of the main board, and the score boxes.
import tkinter
import tkinter.messagebox
class MyGUI:
def __init__(self):
# Window setup
self.window = tkinter.Tk()
self.window.title("Quixx")
self.window.geometry("600x400")
self.window.maxsize(600, 400)
self.window.minsize(600, 400)
# Main board function variables
self.state1 = True
self.state2 = True
self.state3 = True
self.state4 = True
self.state5 = True
self.state6 = True
self.state7 = True
self.state8 = True
self.state9 = True
self.state10 = True
self.state11 = True
# Removed for brevity.
# Main board setup.
button_frame = tkinter.Frame(self.window)
button_frame.columnconfigure(0, weight=1)
button_frame.columnconfigure(1, weight=1)
button_frame.columnconfigure(2, weight=1)
button_frame.columnconfigure(3, weight=1)
button_frame.columnconfigure(4, weight=1)
button_frame.columnconfigure(5, weight=1)
button_frame.columnconfigure(6, weight=1)
button_frame.columnconfigure(7, weight=1)
button_frame.columnconfigure(8, weight=1)
button_frame.columnconfigure(9, weight=1)
button_frame.columnconfigure(10, weight=1)
button_frame.columnconfigure(11, weight=1)
# Red row
self.btn1 = tkinter.Button(button_frame, text="2", background="red", command=self.btn1_change)
self.btn1.grid(row=0, column=0, sticky="we",)
self.btn2 = tkinter.Button(button_frame, text="3", background="red", command=self.btn2_change)
self.btn2.grid(row=0, column=1, sticky="we")
self.btn3 = tkinter.Button(button_frame, text="4", background="red", command=self.btn3_change)
self.btn3.grid(row=0, column=2, sticky="we")
self.btn4 = tkinter.Button(button_frame, text="5", background="red", command=self.btn4_change)
self.btn4.grid(row=0, column=3, sticky="we")
self.btn5 = tkinter.Button(button_frame, text="6", background="red", command=self.btn5_change)
self.btn5.grid(row=0, column=4, sticky="we")
self.btn6 = tkinter.Button(button_frame, text="7", background="red", command=self.btn6_change)
self.btn6.grid(row=0, column=5, sticky="we")
self.btn7 = tkinter.Button(button_frame, text="8", background="red", command=self.btn7_change)
self.btn7.grid(row=0, column=6, sticky="we")
self.btn8 = tkinter.Button(button_frame, text="9", background="red", command=self.btn8_change)
self.btn8.grid(row=0, column=7, sticky="we")
self.btn9 = tkinter.Button(button_frame, text="10", background="red", command=self.btn9_change)
self.btn9.grid(row=0, column=8, sticky="we")
self.btn10 = tkinter.Button(button_frame, text="11", background="red", command=self.btn10_change)
self.btn10.grid(row=0, column=9, sticky="we")
self.btn11 = tkinter.Button(button_frame, text="12", background="red", command=self.btn11_change)
self.btn11.grid(row=0, column=10, sticky="we")
# Yellow row
# removed for brevity
# Green row
# removed for brevity
# Blue row
# removed for brevity
# Score calculation frame setup
score_calc_frame = tkinter.Frame(self.window)
score_calc_frame.columnconfigure(0, weight=1)
score_calc_frame.columnconfigure(1, weight=1)
score_calc_frame.columnconfigure(2, weight=1)
score_calc_frame.columnconfigure(3, weight=1)
score_calc_frame.columnconfigure(4, weight=1)
score_calc_frame.columnconfigure(5, weight=1)
score_calc_frame.columnconfigure(6, weight=1)
score_calc_frame.columnconfigure(7, weight=1)
score_calc_frame.columnconfigure(8, weight=1)
score_calc_frame.columnconfigure(9, weight=1)
score_calc_frame.columnconfigure(10, weight=1)
score_calc_frame.columnconfigure(11, weight=1)
# Score labels and textboxes
self.score_calc_label1 = tkinter.Label(score_calc_frame, text="Score", font=('arial', 16))
self.score_calc_label1.grid(row=0, column=0, sticky="we")
self.score_calc_textbox_red = tkinter.Text(score_calc_frame, height=1, width=1, background="red")
self.score_calc_textbox_red.grid(row=0, column=1, sticky="we",)
self.score_calc_label2 = tkinter.Label(score_calc_frame, text="+", font=('Arial', 18))
self.score_calc_label2.grid(row=0, column=2, sticky="we")
self.score_calc_textbox_yellow = tkinter.Text(score_calc_frame, height=1, width=1, background="yellow")
self.score_calc_textbox_yellow.grid(row=0, column=3, sticky="we")
self.score_calc_label3 = tkinter.Label(score_calc_frame, text="+", font=('arial', 18))
self.score_calc_label3.grid(row=0, column=4, sticky="we")
self.score_calc_textbox_green = tkinter.Text(score_calc_frame, height=1, width=1, background="green")
self.score_calc_textbox_green.grid(row=0, column=5, sticky="we")
self.score_calc_label4 = tkinter.Label(score_calc_frame, text="+", font=('arial', 18))
self.score_calc_label4.grid(row=0, column=6, sticky="we")
self.score_calc_textbox_blue = tkinter.Text(score_calc_frame, height=1, width=1, background="blue")
self.score_calc_textbox_blue.grid(row=0, column=7, sticky="we")
self.score_calc_label5 = tkinter.Label(score_calc_frame, text="-", font=('arial', 18))
self.score_calc_label5.grid(row=0, column=8, sticky="we")
self.score_calc_textbox_subtract = tkinter.Text(score_calc_frame, height=1, width=1)
self.score_calc_textbox_subtract.grid(row=0, column=9, sticky="we")
self.score_calc_label6 = tkinter.Label(score_calc_frame, text="=", font=('arial', 18))
self.score_calc_label6.grid(row=0, column=10, sticky="we")
self.score_calc_label_result = tkinter.Label(score_calc_frame, height=1, width=1, background="white")
self.score_calc_label_result.grid(row=0, column=11, sticky="we")
# Main board button frame packing
button_frame.pack(fill="x", anchor="n", padx=10, pady=20)
# Score calculation frame packing
score_calc_frame.pack(fill="x", padx=5, anchor="center")
self.window.mainloop()
# Main board button functions
# Red row
def btn1_change(self):
if self.state1 == True:
self.btn1.config(text="X")
else:
self.btn1.config(text="2")
self.state1 = not self.state1
def btn2_change(self):
if self.state2 == True:
self.btn2.config(text="X")
else:
self.btn2.config(text="3")
self.state2 = not self.state2
def btn3_change(self):
if self.state3 == True:
self.btn3.config(text="X")
else:
self.btn3.config(text="4")
self.state3 = not self.state3
def btn4_change(self):
if self.state4 == True:
self.btn4.config(text="X")
else:
self.btn4.config(text="5")
self.state4 = not self.state4
def btn5_change(self):
if self.state5 == True:
self.btn5.config(text="X")
else:
self.btn5.config(text="6")
self.state5 = not self.state5
def btn6_change(self):
if self.state6 == True:
self.btn6.config(text="X")
else:
self.btn6.config(text="7")
self.state6 = not self.state6
def btn7_change(self):
if self.state7 == True:
self.btn7.config(text="X")
else:
self.btn7.config(text="8")
self.state7 = not self.state7
def btn8_change(self):
if self.state8 == True:
self.btn8.config(text="X")
else:
self.btn8.config(text="9")
self.state8 = not self.state8
def btn9_change(self):
if self.state9 == True:
self.btn9.config(text="X")
else:
self.btn9.config(text="10")
self.state9 = not self.state9
def btn10_change(self):
if self.state10 == True:
self.btn10.config(text="X")
else:
self.btn10.config(text="11")
self.state10 = not self.state10
def btn11_change(self):
if self.state11 == True:
self.btn11.config(text="X")
else:
self.btn11.config(text="12")
self.state11 = not self.state11
# Yellow row
# removed for brevity
# Green row
# removed for brevity
# Blue row
# removed for brevity
MyGUI()
And this is the code that I thought looked most promising from my research on how to solve this, but I'm unsure how to implement it:
def btn1_change(self):
c=0
for i in self.red_row_list:
if(i==False):
c+=1
return c
Given that you save the state in various fields (state1
, state2
etc.) you would have to check one by one:
def btn1_change(self):
if self.state1 == True:
self.btn1.config(text="X")
else:
self.btn1.config(text="2")
self.state1 = not self.state1
c = 0
if not self.state1:
c += 1
if not self.state2:
c += 1
if not self.state3:
c += 1
if not self.state4:
c += 1
if not self.state5:
c += 1
if not self.state6:
c += 1
if not self.state7:
c += 1
if not self.state8:
c += 1
if not self.state9:
c += 1
if not self.state10:
c += 1
if not self.state11:
c += 1
self.score_calc_textbox_red.replace('1.0', tkinter.END, c)
Not only that, you would have to execute this in every callback, so you would either repeat this code or (preferably) move it to a function to be called from every button.
But there are may ways in which it can be improved. Here I will suggest one improvement:
You can reduce this amount of code by saving the state in a list, instead of having one field per state:
class MyGUI:
def __init__(self):
# Window setup
self.window = tkinter.Tk()
self.window.title("Quixx")
self.window.geometry("600x400")
self.window.maxsize(600, 400)
self.window.minsize(600, 400)
# Main board function variables
# Here we create a list with eleven True values
self.state = [True] * 11
def btn1_change(self):
if self.state[0] == True:
self.btn1.config(text="X")
else:
self.btn1.config(text="2")
self.state[0] = not self.state[0]
c = 0
for s in self.state:
# In general `not s` is preferable for `s == False`
if not s:
c += 1
self.score_calc_textbox_red.replace('1.0', tkinter.END, c)
Of course, much more could be changed, but since you are still learning, I believe there is enough here for you to unpack. Good luck!