Python Tkinter: I'm not sure how to align the guess input with the question

Question:

For this code, I’m trying to make a quiz game that has the user convert hexadecimal to decimal. My only issue is that it’s always a hexadecimal behind. To clarify, when I press enter to start the game, it turns the enter (which is blank) into a guess for the first hexadecimal.

The code is originally from the Color game tutorial from geeksforgeeks, but I’ve changed it up to make it work for my Hex game. In the color game though, it uses an array and it shuffles the color after the first run so it essentially aligns itself.

Here’s my code:

# import the modules
import tkinter
import random
from random import randint

# hex converter
conversionTable = [
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
    'F'
]


def decimalToHexadecimal(decimal):
    hexadecimal = ''
    while (decimal > 0):
        remainder = decimal % 16
        hexadecimal = conversionTable[remainder] + hexadecimal
        decimal = decimal // 16
    return hexadecimal  # return hexadecimal to main

# Other version of hex converter
# def gen_hex():
    # hex() - converts random number into the corresponding hex string
    # randint(0,255) - generates random int value between 0-255
    # [2:] - removes 0x from the resulting string
    rand_hex_str = hex(randint(0, 256))[2:]
    # retuns hex value
   # return rand_hex_str


# the score
score = 0

# the game time left, initially 30 seconds.
timeleft = 160

# function that will start the game.


def onEnter(event):
    label.config(text="You entered!")
    startGame()


def startGame():

    if timeleft == 160:

        # starts the countdown timer.
        countdown()

    # run the function to
    # choose the next numer
    nextNumber()


# Function to choose and
# display the next number


def nextNumber():

    # use the globally declared 'score'
    # and 'play' variables above.
    global score
    global timeleft

    # Utilizes the function to convert number to hex
    decimalNumber = random.randint(0, 255)
    hexNumber = decimalToHexadecimal(decimalNumber)

    # if the game is on
    if timeleft > 0:

        # makes the text entry box active
        e.focus_set()

        # debug code
        guess = e.get()
        print('decimal: ' + str(decimalNumber))
        print('guess: ' + str(guess))
        if guess == str(decimalNumber):
            score += 1

        # clear the text entry box.
        e.delete(0, tkinter.END)

        # changes the number
        label.config(text=hexNumber)

        # updates the score.
        scoreBoard.config(text="Score: " + str(score))


# Countdown timer function
def countdown():

    global timeleft

    # if a game is in play
    if timeleft > 0:

        # decrements the timer
        timeleft -= 1

        # update the time left label
        timeLabel.config(text="Time left: "
                         + str(timeleft))

        # run the function again after 1 second.
        timeLabel.after(1000, countdown)


# Background code
# creates a GUI window
root = tkinter.Tk()

# set the title of window
root.title("HEX GAME")

# set the window size
root.geometry("450x200")

# intro, hopefully it works
intro = """Welcome to the Hexadecimal Game! n You will be given a point for every hexadecimal you get right and one point
deducted if wrong.
Press enter to start."""

# instructions label
instructions = tkinter.Label(root, text="The main objective is to determine "
                             "the decimal of the hexadecimal value that is given.",
                             font=('Helvetica', 12))
instructions.pack()

# scoreboard
scoreBoard = tkinter.Label(root, text=intro,
                           font=('Helvetica', 12))
scoreBoard.pack()

# add a time left label
timeLabel = tkinter.Label(root, text="Time left: " +
                          str(timeleft), font=('Helvetica', 12))

timeLabel.pack()

# add a label for displaying the numbers
label = tkinter.Label(root, font=('Helvetica', 60))
label.pack()

# text entry box for text
e = tkinter.Entry(root)

# runs the 'startGame' function when enter is pressed
root.bind('<Return>', onEnter)
e.pack()

# sets focus on the entry box
e.focus_set()

# starts the GUI
root.mainloop()

So originally, my root.bind was:

root.bind('<Return>',startGame)

And I thought my code revision above would be able to stop the hexadecimal from immediately running after entering, but it didn’t do anything. I’ve also created a "guess = tkinter.Entry(root)" and switched all the "e.[function]"’s in my nextNumber() function to "guess.[function]" thinking it would differentiate from the "Press to Enter" entry box but it just broke the game. I’ve tried both hex converters, tried taking out the if loop and putting a while loop with a set amount of turns, tried taking out the timer entirely, along with placing the random.randint() function in different places to see if it would stop the hexadecimal from immediately starting after entering, but nada. Is there any way I can make sure the guess matches with its current hexadecimal question?

Asked By: asha

||

Answers:

The main issue was trying to check guess at the same time the number was being initialized.
Guess at that time is blank.

NextNumber is essentially an interface initialization.

I added a button check_answer.
Attached to the value is a command = do_check.
The command is what is called a callback function.

A GUI is an event-driven interface.
Clicking the button generates an event that calls the function to do the computations.

An alternative approach would have been to use events triggered by the entry box. But that would add additional complexity.

I do not know what resources you have. You might find python-course.eu useful. Tkinter – the Python interface for Tk.

Some comments and prints are added in the code, which I hope will help.
I suggest you go through the answer code in your development environment, clean up, and add comments to help you understand what is happening.

# import the modules
import random
import tkinter

# hex converter
conversionTable = [
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
    'F'
]


def decimalToHexadecimal(decimal):
    hexadecimal = ''
    while (decimal > 0):
        remainder = decimal % 16
        hexadecimal = conversionTable[remainder] + hexadecimal
        decimal = decimal // 16
    return hexadecimal  # return hexadecimal to main

    # Other version of hex converter
    # def gen_hex():
    # hex() - converts random number into the corresponding hex string
    # randint(0,255) - generates random int value between 0-255
    # [2:] - removes 0x from the resulting string
    # rand_hex_str = hex(randint(0, 256))[2:]
    # returns hex value


# return rand_hex_str


# the score
score = 0

# the game time left, initially 30 seconds.
timeleft = 160
decimalNumber = 0  # store the decimal equivalent of a HEX number


# function that will start the game.


def onEnter(event):
    label.config(text="You entered!")
    startGame()


def startGame():
    if timeleft == 160:
        # starts the countdown timer.
        countdown()

    # run the function to
    # choose the next numer
    nextNumber()


# Function to choose and
# display the next number


def nextNumber():
    print('def nextNumber(): is initializing the GUI interface.')
    # use the globally declared 'score'
    # and 'play' variables above.
    global score
    global timeleft
    global decimalNumber
    # Utilizes the function to convert number to hex
    decimalNumber = random.randint(0, 255)
    hexNumber = decimalToHexadecimal(decimalNumber)

    # if the game is on
    if timeleft > 0:
        # makes the text entry box active
        e.focus_set()
        print('So guess = e.get() is empty at initialization')
        # debug code
        guess = e.get()
        print('decimal: ' + str(decimalNumber))
        print('guess: ' + str(guess))
        # if guess == str(decimalNumber):
        #     score += 1

        # clear the text entry box.
        e.delete(0, tkinter.END)

        # changes the number
        label.config(text=hexNumber)
        #
        # # updates the score.
        # scoreBoard.config(text="Score: " + str(score))


def do_check():
    """Checks an entry against the provided global decimalNumber"""
    global score
    # debug code
    guess = e.get()
    print('decimal: ' + str(decimalNumber))
    print('guess: ' + str(guess))
    if guess == str(decimalNumber):
        score += 1
    else:
        score -= 1
    # clear the text entry box.
    e.delete(0, tkinter.END)
    # updates the score.
    scoreBoard.config(text="Score: " + str(score))
    nextNumber()


# Countdown timer function
def countdown():
    global timeleft

    # if a game is in play
    if timeleft > 0:
        # decrements the timer
        timeleft -= 1

        # update the time left label
        timeLabel.config(text="Time left: "
                              + str(timeleft))

        # run the function again after 1 second.
        timeLabel.after(1000, countdown)


# Background code
# creates a GUI window
root = tkinter.Tk()

# set the title of window
root.title("HEX GAME")

# set the window size
root.geometry("450x300")

# intro, hopefully it works
intro = """Welcome to the Hexadecimal Game! n You will be given a point for every hexadecimal you get right and one point
deducted if wrong.
Press enter to start."""

# instructions label
instructions = tkinter.Label(root, text="The main objective is to determine "
                                        "the decimal of the hexadecimal value that is given.",
                             font=('Helvetica', 12))
instructions.pack()

# scoreboard
scoreBoard = tkinter.Label(root, text=intro,
                           font=('Helvetica', 12))
scoreBoard.pack()

# add a time left label
timeLabel = tkinter.Label(root, text="Time left: " +
                                     str(timeleft), font=('Helvetica', 12))

timeLabel.pack()

# add a label for displaying the numbers
label = tkinter.Label(root, font=('Helvetica', 60))
label.pack()
check_answer = tkinter.Button(root, text="Click to check enter",
                              command=do_check, )
check_answer.pack()
# text entry box for text
e = tkinter.Entry(root)

# runs the 'startGame' function when enter is pressed
root.bind('<Return>', onEnter)
e.pack()

# sets focus on the entry box
e.focus_set()

# starts the GUI
root.mainloop()

Answered By: Carl_M
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.