0

I'm currently trying to use the entry widget in tkinter to get a number from the user, and then use that number to define a parameter of one of my other functions.

The code is very long, so I'll try summarize my thoughts after the block.

class NimGame():

    def __init__(self, numberOfBalls):
        self.numberOfBallsRemaining = numberOfBalls
        print("Nim game initialized with {} balls.".format(self.numberOfBallsRemaining))

    def remainingBalls(self):
        return self.numberOfBallsRemaining

    def take(self, numberOfBalls):
        if (numberOfBalls < 1) or (numberOfBalls > 3) or (numberOfBalls > self.numberOfBallsRemaining):
            print("You can't take that number of balls. Try again.")
            # ## Update Label in the GUI to tell user they can't take that many balls.
            # It might be better to "inactivate" the buttons that correspond to invalid number to take.
            statusLabel.configure(text="You can't take that number of balls. Try again.")
        else:
            self.numberOfBallsRemaining = self.numberOfBallsRemaining - numberOfBalls
            print("You took {} balls. {} remain.".format(numberOfBalls, self.numberOfBallsRemaining))
            if self.numberOfBallsRemaining == 0:
                print("Computer wins!")
            else:
                # ## After removing player-chosen balls, update graphics and then pause for 1.0 seconds
                # before removing computer-chosen balls.  This way the player can "see" the
                # intermediate status.  Perhaps think about a nicer way of showing this.
                updateGraphics()
                sleep(1.0)

                computerMaxBalls = min(3, self.numberOfBallsRemaining)
                compBallsTaken = random.randint(1,computerMaxBalls)
                self.numberOfBallsRemaining = self.numberOfBallsRemaining - compBallsTaken

                # ## After removing computer-chosen balls, update graphics again.
                updateGraphics()
                print("Computer took {} balls. {} remain.".format(compBallsTaken, self.numberOfBallsRemaining))
                if self.numberOfBallsRemaining == 0:
                    print("You win!")

def updateGraphics():
    canvas.delete('all')
    centerX = leftmostBallXPosition
    centerY = ballYPosition
    for i in range(nimGame.remainingBalls()):
        canvas.create_oval(centerX - halfBallSize,
                           centerY - halfBallSize,
                           centerX + halfBallSize,
                           centerY + halfBallSize,
                           fill="#9999ff")
        centerX = centerX + spaceBetweenBalls + ballSize
        canvas.update_idletasks()

def initializeNewGame():
    numberOfBalls = e1.get()
    initializeNimAndGUI(numberOfBalls)

def initializeNimAndGUI(numberOfBalls):
    global nimGame
    global ballSize, halfBallSize, spaceBetweenBalls, leftmostBallXPosition, ballYPosition

    nimGame = NimGame(numberOfBalls)

    canvas.delete('all') 
    ballSize = min(maxBallSize, int(((canvasWidth-canvasBorderBuffer)//numberOfBalls)/1.2))
    halfBallSize = ballSize // 2
    spaceBetweenBalls = int(0.2 * ballSize)
    leftmostBallXPosition = (canvasBorderBuffer//2) + (spaceBetweenBalls//2) + halfBallSize
    ballYPosition = canvasHeight // 2
    updateGraphics()

 def createGUI():
    global rootWindow
    global canvas
    global statusLabel
    global textEntry
    global e1

    rootWindow = Tk()
    canvasAndButtons = Frame(rootWindow)
    canvas = Canvas(canvasAndButtons, height=canvasHeight, width=canvasWidth, relief=SUNKEN, borderwidth=2)
    canvas.pack(side=LEFT)

    buttonframe = Frame(canvasAndButtons)
    e1 = Entry(buttonframe)
    e1.pack()
    button1 = Button(buttonframe, text='Take 1', command=lambda:takeBalls(1))
    button2 = Button(buttonframe, text='Take 2', command=lambda:takeBalls(2))
    button3 = Button(buttonframe, text='Take 3', command=lambda:takeBalls(3))
    button4 = Button(buttonframe, text='New Game', command=initializeNewGame)
    button1.pack()
    button2.pack()
    button3.pack()
    button4.pack()
    buttonframe.pack(side=RIGHT)
    canvasAndButtons.pack()
    statusLabel = Label(rootWindow, text="Play Nim")
    statusLabel.pack()

def runNim(numberOfBalls):
    createGUI()
    initializeNimAndGUI(numberOfBalls)   
    rootWindow.mainloop()

So to me it seems that the program is having issues updating the graphics when I do a second game. What should happen is that, for example, i call runNim(20) and play a game with 20 balls. After the game, I need to be able to enter a number in the entry widget, click new game, and have that be the new numberOfBalls. When I do that, I get the init message back stating "Nim game initialized with 10 balls." But the GUI doesnt change, no balls appear in the GUI, and if I try to take anything it gives traceback and errors.

4
  • Have you tried e1.get()? That will read the value entered by the user in the entry box. Also, what are the traceback errors? Commented Apr 30, 2016 at 12:35
  • File "File info", line 1549, in _call_ return self.func(*args) File "File info", line 86, in initializeNewGame initializeNimAndGUI(numberofBalls) File "File info", line 102, in initalizeNimAndGUI ballSize = min(maxBallSize, int(((canvasWidth-canvasBorderBuffer)//numberOfBalls)/1.2)) Commented Apr 30, 2016 at 15:06
  • For my numberOfBalls I have e1.get(). But I've been told that returns a string, and I need an int. What do I use to return an int in that situation? Commented Apr 30, 2016 at 15:07
  • By default, an entry box takes values in the form of a string. Convert it to an integer using int() and then return. Commented May 1, 2016 at 8:45

1 Answer 1

1

I figured out my problem. When I was trying to convert the string from e1.get() into an integer, I wasn't accounting for the empty string when I first run the program. This gave me a ValueError: invalid literal for int() with base 10: ''. So I had to account for that, and now it works.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.