4
\$\begingroup\$

For my Python project, I wanted to make a crossword game GUI with SQL connectivity to display high scores. I tried to learn tkinter, but the only difficulty was that I cannot use classes or objects as they are not taught at my school yet. Still I managed to make a highly inefficient and ugly looking code (I am a newbie). Please suggest how to improve my code quality and writing style.

Here's my code:

# -*- coding: utf-8 -*-

import tkinter as tk
from PIL import ImageTk, Image
import mysql.connector
import requests
from io import BytesIO


#requesting password to access sql database
passwd = str(input("enter the password for sql database"))

#connecting to mysql
connection = mysql.connector.connect(host='localhost',
                                             user='root',
                                             password=passwd)

#creating database myschool
cursor = connection.cursor()
cursor.execute('''CREATE DATABASE IF NOT EXISTS myschool''')
cursor.execute('''USE myschool''')

#function to insert player score into database
def updatevalues(val1,val2,val3):
    cursor = connection.cursor()
    sql = "INSERT INTO crossword (User, timetaken, correctvalues) VALUES (%s, %s, %s)"
    val = (val1,val2,val3)
    cursor.execute(sql, val)
    connection.commit()

#function to create table if crossword table doesnt not exist
def createtable():
    cursor = connection.cursor()
    cursor.execute('''CREATE TABLE crossword (User varchar(255),timetaken varchar(255),correctvalues int);''')

#defining delete and entry functions
def delete(entry):
    entry.delete(0,'end')
    return None 
    
def entry_get(entry):
    value1 = entry.get()
    return value1

#defining a function to get the entered username
username = ''
def check():
    global username
    if entry_get(nameentry) :
        username = str(entry_get(nameentry))
    delete(nameentry)
    new_window.destroy()


#making a login window
new_window = tk.Tk()

tk.Label(new_window,text='Enter username:',font=('Times New Roman',25)).place(x=80,y=100)
tk.Label(new_window,text='Welcome to My Game',font=('Algerian',35,'underline')).place(x=60,y=10)
tk.Label(new_window,text='Note: The Game will start as soon as you press enter',font=('Times New Roman',15)).place(x=70,y=230)

nameentry = tk.Entry(new_window)
nameentry.place(x=320,y=110,height=30,width=200)

sub1 = tk.Button(new_window,text="Enter", command = check)
sub1.place(x=250,y=160,height=40,width=150)

new_window.geometry('600x350')
new_window.mainloop()


#making the main crossword window
window = tk.Tk()
window.title("My GUI")
lab = tk.Label(window,text='Crossword#1')
               

               
#making a 30 min timer
def update_timeText():
    if (state):
        global timer
        timer[2] += 1
        if (timer[2] >= 100):
            timer[2] = 0
            timer[1] += 1
        if (timer[1] >= 60):
            timer[0] += 1
            timer[1] = 0
        timeString = pattern.format(timer[0], timer[1], timer[2])
        timeText.configure(text=timeString)
    if timer == [30,0,0]:
        timeText.configure(text="30:00:00")
    else:
        window.after(10, update_timeText)

def start():
    global state
    state = True
    
def stop():
    global state
    state = False
    
state = False
timer = [0, 0, 0]
pattern = '{0:02d}:{1:02d}:{2:02d}'
timeText = tk.Label(window, text="00:00:00", font=("Helvetica", 30))
timeText.place(x=100,y=30)
update_timeText()
window.after(1,start)

#creating a canvas and making a crossword structure
cwidth=450
cheight=450
W = tk.Canvas(window,width=cwidth,height=cheight,highlightbackground='black')
W.place(x=100,y=100)

for i in range(0,450,50):
    W.create_line(0,i,450,i)
    W.create_line(i,0,i,450)

#marking numbers on grid
W.create_text(10,10,text=1)
W.create_text(110,10,text=2)
W.create_text(260,10,text=3)
W.create_text(310,10,text=4)
W.create_text(410,10,text=5)
W.create_text(10,110,text=6)
W.create_text(60,110,text=7)
W.create_text(160,110,text=8)
W.create_text(260,110,text=9)
W.create_text(360,110,text=10)
W.create_text(160,160,text=11)
W.create_text(10,210,text=12)
W.create_text(260,210,text=13)
W.create_text(160,260,text=14)
W.create_text(10,310,text=15)
W.create_text(110,310,text=16)
W.create_text(260,310,text=17)
W.create_text(310,310,text=18)
W.create_text(410,310,text=19)
W.create_text(10,410,text=20)
W.create_text(260,410,text=21)

#making black squares
W.create_rectangle(200,0,250,150,fill='black')
W.create_rectangle(150,50,300,100,fill='black')
W.create_rectangle(50,50,100,100,fill='black')
W.create_rectangle(350,50,400,100,fill='black')
W.create_rectangle(0,150,50,200,fill='black')
W.create_rectangle(100,150,150,200,fill='black')
W.create_rectangle(300,150,350,200,fill='black')
W.create_rectangle(400,150,451,200,fill='black')
W.create_rectangle(200,200,250,250,fill='black')
W.create_rectangle(0,250,50,300,fill='black')
W.create_rectangle(100,250,150,300,fill='black')
W.create_rectangle(300,250,350,300,fill='black')
W.create_rectangle(400,250,451,300,fill='black')
W.create_rectangle(200,300,250,451,fill='black')
W.create_rectangle(50,350,100,400,fill='black')
W.create_rectangle(150,350,300,400,fill='black')
W.create_rectangle(350,350,400,400,fill='black')

#creating section for clues
X = tk.Canvas(window,height=600,width=700,highlightbackground='black')
X.pack(padx=40,side='right')

#Across secion
X.create_text(130,50,font=('Arial',40),text='Across')
X.create_text(115,105,font=('Arial',20),text='1. Locale')
X.create_text(176,145,font=('Arial',20),text='3. Soup Containers')
X.create_text(180,185,font=('Arial',20),text='6. Nectar Gatherers')
X.create_text(150,225,font=('Arial',20),text='9. Fries or Slaw')
X.create_text(159,265,font=('Arial',20),text='11. Household pest')
X.create_text(167,305,font=('Arial',20),text='12. Belonging to Eda')
X.create_text(120,345,font=('Arial',20),text='13. __ of Evil')
X.create_text(150,385,font=('Arial',20),text='14. Morning Riser')
X.create_text(100,425,font=('Arial',20),text='15. Lazily')
X.create_text(138,465,font=('Arial',20),text='17. Buck or doe')
X.create_text(167,505,font=('Arial',20),text='20. Sunrise direction')
X.create_text(195,545,font=('Arial',19),text='21. you do this with a book')

#Down section
X.create_text(530,50,font=('Arial',40),text='Down')
X.create_text(520,105,font=('Arial',20),text='1. Long Sandwhich')
X.create_text(487,145,font=('Arial',20),text='2. Casual top')
X.create_text(471,185,font=('Arial',20),text='4. __ Baba')
X.create_text(471,225,font=('Arial',20),text='5. Observe')
X.create_text(484,265,font=('Arial',20),text='7. Concluded')
X.create_text(465,305,font=('Arial',20),text='8. Cheeky')
X.create_text(465,345,font=('Arial',20),text='9. Dont sit')
X.create_text(457,385,font=('Arial',20),text='10. Tee off')
X.create_text(516,425,font=('Arial',20),text='15. If__I said it once')
X.create_text(480,465,font=('Arial',20),text='16. __Angeles')
X.create_text(498,505,font=('Arial',20),text='18. New Years__')
X.create_text(530,545,font=('Arial',20),text='19. Scarlett or Maroon')

#linking tick image when answer is correct
img_url = "https://i.ibb.co/2PKKZrj/iconfinder-tick-16-22643.png"
response = requests.get(img_url)
img_data = response.content
img = ImageTk.PhotoImage(Image.open(BytesIO(img_data)))

def tickimg(x_co,y_co):
    panel = tk.Label(window, image=img)
    panel.place(x=x_co,y=y_co)


lis = [['1','A','site'],['1','D','sub'],['2','D','tee'],['3','A','cans'],['4','D','ali'],
       ['5','D','see'],['6','A','bees'],['7','D','ended'],['8','D','sassy'],
       ['9','A','side'],['9','D','stand'],['10','D','drive'],['11','A','ant'],['12','A','idas'],
       ['13','A','axis'],['14','A','sun'],['15','A','idly'],['15','D','ive'],
       ['16','D','los'],['17','A','deer'],['18','D','eve'],
       ['19','D','red'],['20','A','east'],['21','A','read']]

def listchange():
    stop()
    global timer
    timestring = ''
    minutes = timer[0]
    if minutes < 10:
        timestring += '0'+str(timer[0])+':'
    else:
        timestring += str(timer[0])+':'
    seconds = timer[1]
    if seconds < 10:    
        timestring += '0'+str(timer[1])+':'
    else:
        timestring += str(timer[1])+':'
    milliseconds = timer[2]
    if milliseconds < 10:    
        timestring += '0'+str(timer[2])
    else:
        timestring += str(timer[2])
    return timestring

def button_fun():
    global correct
    global username
    new_timer = listchange()
    cursor = connection.cursor()
    cursor.execute("""show tables;""")
    if ('crossword',) in cursor:
        updatevalues(username,new_timer,len(correct))
    else:
        createtable()
        updatevalues(username,new_timer,len(correct))
        
def endscreen1():    
    root = tk.Tk()
    def des():
        root.destroy()
    root.geometry('700x450')
    tk.Label(root,text='THANK YOU',font=('Algerian',60)).place(x = 140,y = 30)
    tk.Label(root,text='FOR',font=('Algerian',60)).place(x = 270, y = 120)
    tk.Label(root,text='PLAYING',font=('Algerian',60)).place(x = 190, y= 210)
    viewscore = tk.Button(root,text='VIEW HIGHSCORE',command=des)
    viewscore.place(x=270,y=340,height=40,width=150)
    root.mainloop()


    
def highscore():   
    newroot = tk.Tk()
    newroot.geometry('800x700')  
    tk.Label(newroot,text='HIGH SCORES',font=('Algerian',50,'underline')).pack(side='top',pady=20)
    Y = tk.Canvas(newroot,height=700,width=600,highlightbackground='black')
    Y.pack(side='top',pady=30)
    Y.create_line(200,0,200,700)
    Y.create_line(400,0,400,700)
    Y.create_text(100,30,text='Name',font=('Times New Roman',30))
    Y.create_text(300,30,text='Time Taken',font=('Times New Roman',30))
    Y.create_text(500,30,text='Correct',font=('Times New Roman',30))
    Y.create_text(500,60,text='Answers',font=('Times New Roman',30))
    Y.create_line(0,80,600,80)
   
    cursor = connection.cursor()
    cursor.execute('''select * from crossword order by correctvalues desc,timetaken ;''')
    
    names = []
    times = []
    correct = []
    for i in cursor:
        names.append(i[0])
        times.append(i[1])
        correct.append(i[2])
        
    x1_co = 100
    x2_co = 300
    x3_co = 500
    y_co = 60
    if len(names) > 8:
        names = names[0:8]
    for i in range(0,len(names)):
        y_co += 50
        Y.create_text(x1_co,y_co,text=names[i],font=('Times New Roman',20))
        Y.create_text(x2_co,y_co,text=times[i],font=('Times New Roman',20))
        Y.create_text(x3_co,y_co,text=correct[i],font=('Times New Roman',20))
    
    newroot.mainloop()
  
correct = []
def check_func(myvav = False):
    global correct
    global isclicked
    for i in range(len(lis)):
        if entry_get(entry1) == lis[i][0] and entry_get(entry2) == lis[i][1] and entry_get(entry3) == lis[i][2]:
            correct.append('1')
            if i == 0:
                tickimg(640,160)

                W.create_text(25,25,font=('Times New Roman',25),text='S')
                W.create_text(75,25,font=('Times New Roman',25),text='I')
                W.create_text(125,25,font=('Times New Roman',25),text='T')
                W.create_text(175,25,font=('Times New Roman',25),text='E')
                
            if i == 1:

                tickimg(980,160)
                W.create_text(25,25,font=('Times New Roman',25),text='S')
                W.create_text(25,75,font=('Times New Roman',25),text='U')
                W.create_text(25,125,font=('Times New Roman',25),text='B')
                
            if i == 2:

                tickimg(980,200)
                W.create_text(125,25,font=('Times New Roman',25),text='T')
                W.create_text(125,75,font=('Times New Roman',25),text='E')
                W.create_text(125,125,font=('Times New Roman',25),text='E')
                
            if i == 3:

                tickimg(640,200)
                W.create_text(275,25,font=('Times New Roman',25),text='C')
                W.create_text(325,25,font=('Times New Roman',25),text='A')
                W.create_text(375,25,font=('Times New Roman',25),text='N')
                W.create_text(425,25,font=('Times New Roman',25),text='S')
                
            if i == 4:

                tickimg(980,240)
                W.create_text(325,25,font=('Times New Roman',25),text='A')
                W.create_text(325,75,font=('Times New Roman',25),text='L')
                W.create_text(325,125,font=('Times New Roman',25),text='I')
                
            if i == 5:

                tickimg(980,280)
                W.create_text(425,25,font=('Times New Roman',25),text='S')
                W.create_text(425,75,font=('Times New Roman',25),text='E')
                W.create_text(425,125,font=('Times New Roman',25),text='E')
                
            if i == 6:


                tickimg(640,240)
                W.create_text(25,125,font=('Times New Roman',25),text='B')
                W.create_text(75,125,font=('Times New Roman',25),text='E')
                W.create_text(125,125,font=('Times New Roman',25),text='E')
                W.create_text(175,125,font=('Times New Roman',25),text='S')
                
            if i == 7:

                tickimg(980,320)
                W.create_text(75,125,font=('Times New Roman',25),text='E')
                W.create_text(75,175,font=('Times New Roman',25),text='N')
                W.create_text(75,225,font=('Times New Roman',25),text='D')
                W.create_text(75,275,font=('Times New Roman',25),text='E')
                W.create_text(75,325,font=('Times New Roman',25),text='D')
                
            if i == 8:

                tickimg(980,360)
                W.create_text(175,125,font=('Times New Roman',25),text='S')
                W.create_text(175,175,font=('Times New Roman',25),text='A')
                W.create_text(175,225,font=('Times New Roman',25),text='S')
                W.create_text(175,275,font=('Times New Roman',25),text='S')
                W.create_text(175,325,font=('Times New Roman',25),text='Y')
                
            if i == 9:

                tickimg(640,280)
                W.create_text(275,125,font=('Times New Roman',25),text='S')
                W.create_text(325,125,font=('Times New Roman',25),text='I')
                W.create_text(375,125,font=('Times New Roman',25),text='D')
                W.create_text(425,125,font=('Times New Roman',25),text='E')
                
            if i == 10:

                tickimg(980,400)
                W.create_text(275,125,font=('Times New Roman',25),text='S')
                W.create_text(275,175,font=('Times New Roman',25),text='T')
                W.create_text(275,225,font=('Times New Roman',25),text='A')
                W.create_text(275,275,font=('Times New Roman',25),text='N')
                W.create_text(275,325,font=('Times New Roman',25),text='D') 
                
            if i == 11:

                tickimg(980,440)
                W.create_text(275,325,font=('Times New Roman',25),text='D')
                W.create_text(375,175,font=('Times New Roman',25),text='R')
                W.create_text(375,225,font=('Times New Roman',25),text='I')
                W.create_text(375,275,font=('Times New Roman',25),text='V')
                W.create_text(375,325,font=('Times New Roman',25),text='E')
                
            if i == 12:

                tickimg(625,320)
                W.create_text(175,175,font=('Times New Roman',25),text='A')
                W.create_text(225,175,font=('Times New Roman',25),text='N')
                W.create_text(275,175,font=('Times New Roman',25),text='T')
                
            if i == 13:

                tickimg(627,360)
                W.create_text(25,225,font=('Times New Roman',25),text='I')
                W.create_text(75,225,font=('Times New Roman',25),text='D')
                W.create_text(125,225,font=('Times New Roman',25),text='A')
                W.create_text(175,225,font=('Times New Roman',25),text='S')
                
            if i == 14:

                tickimg(627,400)
                W.create_text(275,225,font=('Times New Roman',25),text='A')
                W.create_text(325,225,font=('Times New Roman',25),text='X')
                W.create_text(375,225,font=('Times New Roman',25),text='I')
                W.create_text(425,225,font=('Times New Roman',25),text='S')
                
                
            if i == 15:

                tickimg(627,440)
                W.create_text(175,275,font=('Times New Roman',25),text='S')
                W.create_text(225,275,font=('Times New Roman',25),text='U')
                W.create_text(275,275,font=('Times New Roman',25),text='N')
                
            if i == 16:

                tickimg(627,480)
                W.create_text(25,325,font=('Times New Roman',25),text='I')
                W.create_text(75,325,font=('Times New Roman',25),text='D')
                W.create_text(125,325,font=('Times New Roman',25),text='L')
                W.create_text(175,325,font=('Times New Roman',25),text='Y')
                
            if i == 17:


                tickimg(980,480)
                W.create_text(25,325,font=('Times New Roman',25),text='I')
                W.create_text(25,375,font=('Times New Roman',25),text='V')
                W.create_text(25,425,font=('Times New Roman',25),text='E')
                
            if i == 18:

                tickimg(980,520)
                W.create_text(125,325,font=('Times New Roman',25),text='L')
                W.create_text(125,375,font=('Times New Roman',25),text='O')
                W.create_text(125,425,font=('Times New Roman',25),text='S')
                
            if i == 19:

                tickimg(627,520)
                W.create_text(275,325,font=('Times New Roman',25),text='D')
                W.create_text(325,325,font=('Times New Roman',25),text='E')
                W.create_text(375,325,font=('Times New Roman',25),text='E')
                W.create_text(425,325,font=('Times New Roman',25),text='R')
                
            if i == 20:

                tickimg(980,560)
                W.create_text(325,325,font=('Times New Roman',25),text='E')
                W.create_text(325,375,font=('Times New Roman',25),text='V')
                W.create_text(325,425,font=('Times New Roman',25),text='E')
                
            if i == 21:

                tickimg(980,600)
                W.create_text(425,325,font=('Times New Roman',25),text='R')
                W.create_text(425,375,font=('Times New Roman',25),text='E')
                W.create_text(425,425,font=('Times New Roman',25),text='D')
                
            if i == 22:

                tickimg(627,560)
                W.create_text(25,425,font=('Times New Roman',25),text='E')
                W.create_text(75,425,font=('Times New Roman',25),text='A')
                W.create_text(125,425,font=('Times New Roman',25),text='S')
                W.create_text(175,425,font=('Times New Roman',25),text='T')
                
            if i == 23:

                tickimg(627,600)
                W.create_text(275,425,font=('Times New Roman',25),text='R')
                W.create_text(325,425,font=('Times New Roman',25),text='E')
                W.create_text(375,425,font=('Times New Roman',25),text='A')
                W.create_text(425,425,font=('Times New Roman',25),text='D')

    delete(entry1)
    delete(entry2)
    delete(entry3)
    
    if myvav == True:
        submitbutton.bind('<Button-1>',button_fun())
        window.destroy()
        endscreen1()
        highscore()
        
    if len(correct) == 24:
        button_fun()
        window.destroy()
        endscreen1()
        highscore()

#Entry windows ,check button and submit button
tk.Label(window,text='Number:',font=('Arial',15)).place(x=21,y=580)
entry1 = tk.Entry(window)
entry1.place(x=100,y=580,height=30,width=100)

tk.Label(window,text='A or D:',font=('Arial',15)).place(x=230,y=580)
entry2 = tk.Entry(window)
entry2.place(x=300,y=580,height=30,width=100)

tk.Label(window,text='Word:',font=('Arial',15)).place(x=437,y=580)
entry3 = tk.Entry(window)
entry3.place(x=500,y=580,height=30,width=100)

check_button = tk.Button(window,
                   text="Check",command=check_func)
check_button.place(x=270,y=630,height=30,width=100)

submitbutton = tk.Button(window,text="Submit",command=lambda: check_func(myvav=True))
submitbutton.place(x=500,y=630,height=30,width=100)

window.geometry("1366x768")

window.mainloop()

One more thing: I want to add data file handling in this, but I am not quite sure how that works. Any suggestions would be helpful.

\$\endgroup\$
2
  • \$\begingroup\$ Yep, you're right, the code looks ugly. Since you already know how to define functions with parameters, why didn't you use them for the repetitive W.create_text blocks? For example you could define add_across(627, 560, 25, 425, "EAST") or add_down(980, 600, 425, 325, "RED"). As long as there are no answers, you may still improve your code. \$\endgroup\$ Commented Nov 30, 2019 at 22:36
  • \$\begingroup\$ @RolandIllig Thanks for the advice. I will definitely implement this on my code. \$\endgroup\$ Commented Dec 1, 2019 at 10:28

1 Answer 1

1
\$\begingroup\$

Efficiency

In the for loop in the check_func function, you check the i variable 24 times every time through the loop because you have 24 separate if statements:

        if i == 0:
        
        if i == 1:
        
        ...

        if i == 23:

The code would be more efficient with a single if/elif/elif... statement:

        if i == 0:
        
        elif i == 1:
        
        ...

        elif i == 23:

DRY

In the check_func function, you set the same font many times:

            W.create_text(25,25,font=('Times New Roman',25),text='S')
            W.create_text(75,25,font=('Times New Roman',25),text='I')
            W.create_text(125,25,font=('Times New Roman',25),text='T')
            W.create_text(175,25,font=('Times New Roman',25),text='E')

At a minimum, you could create a variable to pass to the create_text call for the font.

There may be other opportunities here to wrap those calls into a function if there is some commonality among the numbers you pass in.

Layout

The assignment to the lis variable is hard to understand. It would be easier to understand if you had one array per line, for example:

lis = [
        ['1','A','site'],
        ['1','D','sub'],
        ['2','D','tee'],

I recommend moving the functions to the top, after the import statements. Having them in the middle of the code interrupts the natural flow of the code (from a human readability standpoint).

Comments

Some comments are not needed because they simply repeat what the code does:

#connecting to mysql
connection = mysql.connector.connect(host='localhost',

Naming

Some variable and function names are not very meaningful:

lis
myvav
check
check_func

Documentation

You could add usage information as comments at the top of the file. State the purpose of the code along with the required input and the expected output.

\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.