DarthOpto
DarthOpto

Reputation: 1662

Infinite Loop, not certain as to why

I am trying to take a text based game and make a GUI application with it. It is a number guessing game, where the computer chooses a number between 1 and 100. The user is expected to guess the correct number in the least amount of tries as possible.

My problem is that I am getting into an infinite loop when and I am not sure why or how to correct it.

The application is below:

# Guess My Number
#
# The computer picks a random number between 1 and 100
# The player tries to guess it and the computer lets the player know
# if the guess is too high, too low or right on the money

from tkinter import *
from random import randint


class Application(Frame):
    """ A GUI Application for a number guessing game """
    def __init__(self, master):
        super(Application, self).__init__(master)
        self.grid()
        self.the_number = randint(1, 100)
        self.guess_ent = Entry(self)
        self.results = None
        self.tries = 1
        self.create_widgets()

    def create_widgets(self):
        Label(self,
              text="Welcome to 'Guess My Number'"
              ).grid(row=0, column=0, columnspan=2, sticky=W+E+N+S)
        Label(self,
              text="I'm thinking of a number between 1 and 100"
              ).grid(row=1, column=0, columnspan=2, sticky=W+E+N+S)
        Label(self,
              text="Try to guess it in as few attempts as possible"
              ).grid(row=2, column=0, columnspan=2, sticky=W+E+N+S)
        Label(self,
              text="What is your guess: "
              ).grid(row=4, column=0, sticky=W)
        self.guess_ent.grid(row=4, column=1, sticky=W)
        Button(self,
               text="Submit Guess",
               command=self.guessing
               ).grid(row=5, column=0, sticky=W)
        root.bind("<Return>", self.guessing_a)

        self.results = Label(self, text="")
        self.results.grid(row=6, column=0, sticky=W+E+N+S)

    def guessing(self):
        guess = int(self.guess_ent.get())
        while guess != self.the_number:
            if guess > self.the_number:
                self.results.config(text="Lower")
                self.guess_ent.delete(0, END)
            else:
                self.results.config(text="Higher")
                self.guess_ent.delete(0, END)

            self.tries += 1
            if self.tries >= 10:
                self.results.config(text="I'm sorry you couldn't guess the "
                                     "number in the appropriate amount "
                                     "of tries. The number I was "
                                     "thinking of was: {}"
                                .format(self.the_number))

    self.results.config(text="You guessed it!. "
                             "The number I was thinking of was: {}, "
                             "and it only took you {}, tries"
                        .format(self.the_number, self.tries))

    def guessing_a(self):
        self.guessing()

# main
root = Tk()
root.title("Guess My Number")
app = Application(root)
root.mainloop()

Upvotes: 1

Views: 73

Answers (2)

Billal BEGUERADJ
Billal BEGUERADJ

Reputation: 22804

The last line of your code root.mainloop() means you already have a while loop in your program. So running a while loop inside an other one the way you did will lead to problems.

So the idea is to take an advantage of the main implicit while loop of your program and use it to increment the number of tries self.tries by one. This is in reality what is naturally when you used the command option of your button and the bind() method for Enter. I think you will understand the solution below easily.

Thus in the below program I modified only guessing() method and ... one last thing: do not forget to inject an event as a parameter to def guessing_a() method otherwise pressing on Enter will raise a TypeError exception.

Program

Here is the full program that works correctly both with pressing the button widget or the Enter keyboard button:

# Guess My Number
#
# The computer picks a random number between 1 and 100
# The player tries to guess it and the computer lets the player know
# if the guess is too high, too low or right on the money

from tkinter import *
from random import randint


class Application(Frame):
    """ A GUI Application for a number guessing game """
    def __init__(self, master):
        super(Application, self).__init__(master)
        self.grid()
        self.the_number = randint(1, 100)
        self.guess_ent = Entry(self)
        self.results = None
        self.tries = 1
        self.create_widgets()

    def create_widgets(self):
        Label(self,
              text="Welcome to 'Guess My Number'"
              ).grid(row=0, column=0, columnspan=2, sticky=W+E+N+S)
        Label(self,
              text="I'm thinking of a number between 1 and 100"
              ).grid(row=1, column=0, columnspan=2, sticky=W+E+N+S)
        Label(self,
              text="Try to guess it in as few attempts as possible"
              ).grid(row=2, column=0, columnspan=2, sticky=W+E+N+S)
        Label(self,
              text="What is your guess: "
              ).grid(row=4, column=0, sticky=W)
        self.guess_ent.grid(row=4, column=1, sticky=W)
        Button(self,
               text="Submit Guess",
               command=self.guessing
               ).grid(row=5, column=0, sticky=W)
        root.bind("<Return>", self.guessing_a)

        self.results = Label(self, text="")
        self.results.grid(row=6, column=0, sticky=W+E+N+S)

    def guessing(self):
       if self.guess_ent.get() !='': # if there is a number in the entry widget. You can also improve this by checking if the entered text is a valid number
        guess = int(self.guess_ent.get())
        if guess > self.the_number:
                self.results.config(text="Lower")
                self.guess_ent.delete(0, END)
        elif guess < self.the_number:
                self.results.config(text="Higher")
                self.guess_ent.delete(0, END)
        else:
            self.results.config(text="You guessed it!. "
                             "The number I was thinking of was: {}, "
                             "and it only took you {}, tries"
                        .format(self.the_number, self.tries))    

        self.tries += 1
        if self.tries >= 10:
               self.results.config(text="I'm sorry you couldn't guess the "
                                     "number in the appropriate amount "
                                     "of tries. The number I was "
                                     "thinking of was: {}"
                                .format(self.the_number))

        
    def guessing_a(self, event):
        self.guessing()

# main
root = Tk()
root.title("Guess My Number")
app = Application(root)
root.mainloop()

Upvotes: 2

Pythonista
Pythonista

Reputation: 11645

You have a while loop that check while guess != self.number. But, where do you change guess? This condition will always be true -> infinite loop.

You want guess inside the while loop.

Also, in Tk you shouldn't use a while loop, unless you're using threads. This is going to block the GUI. Use the after method instead.

Upvotes: 1

Related Questions