View the step-by-step solution to:

import random class NimGame(): def __init__(self, numberOfBalls): self.numberOfBallsRemaining = numberOfBalls print("Nim game initialized with...

Modify nimGameWithGUI.py so that a user can interactively play Nim (NimGame.py). The provided file already works; your assignment is to improve it. 

Minimum requirement (worth 3 points out of 5): replace the Label widget that displays as "?replace?" in the GUI (and is named placeholder in the code) with an Entry widget. When the "New Game" button is pressed, the number of initial balls in the new game should be the number in the Entry widget. 

Make additional changes of your own choice to improve the game (worth 2 out of 5 points). Possibilities include:

  • whenever fewer than three balls remain, inactivate the buttons that would result in illegal moves.
  • use the status Label (statusLabel in the code) to provide more feedback to the player. For example, you could remove messages that print to the Python shell, and instead use the status label to display information such as how many balls the computer took, win/lose status ("You win!" or "Computer wins!"), etc.
  • Maintain and display a count of how many games have been won/lost by the player and the computer.
  • Modify GUI layout, colors, etc.
  • improve the graphics via one or more of:    
    •       
    • put numbers in the centers of (or underneath) the balls so it's easier for the player to quickly see how many are left,      
    • change the drawing code so that the balls appear on the screen in a more pleasing way (perhaps all at once rather than the current one-at-a-time refresh)      
    • the 1-second delay between balls removed by player and computer seems clunky. Think of a way to make that nicer.      
    • provide "fancier" win/lose status information using the canvas/graphics area rather than the status label.      
    • change ball graphics. E.g. make balls look more nicer, or lay them out differently on canvas (perhaps several rows of balls if there are a lot of them)
    • How to modify this python code to improve their function to achieve the requirements above? Please explain also. 
import random class NimGame(): def __init__(self, numberOfBalls): self.numberOfBallsRemaining = numberOfBalls print("Nim game initialized with {} balls.".format(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.") else: self.numberOfBallsRemaining = self.numberOfBallsRemaining - numberOfBalls print("You took {} balls. {} remain.".format(numberOfBalls, self.numberOfBallsRemaining)) if self.numberOfBallsRemaining == 0: print("Computer wins!") else: computerMaxBalls = min(3, self.numberOfBallsRemaining) compBallsTaken = random.randint(1,computerMaxBalls) self.numberOfBallsRemaining = self.numberOfBallsRemaining - compBallsTaken print("Computer took {} balls. {} remain.".format(compBallsTaken, self.numberOfBallsRemaining)) if self.numberOfBallsRemaining == 0: print("You win!")
Background image of page 1
# Note: if you want to use additional tkinter widgets, you will need to add their names to # the import list below from tkinter import Tk, Canvas, Frame, Button, Label, Entry, END, LEFT, RIGHT, SUNKEN from time import sleep import random # To run this code, load into Python, and execute runNim(n), where n is desired initial number # of balls, in the Python shell # # This class is just like the solution to HW 6 Q2 with three small changes related to GUI. # See comments starting with # ##. 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:
Background image of page 1
print("You win!") # global variables used for placement of balls canvasHeight = 200 canvasWidth = 610 canvasBorderBuffer = 10 maxBallSize = 100 # the values of global variables below are computed and set in initializeNimAndGUI # ballSize # halfBallSize # spaceBetweenBalls # leftmostBallXPosition # ballYPosition # 1. clear the canvas # 2. draw balls on canvas equal to number remaining in the Nim game 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() # Callback functions invoked by GUI buttons def takeBalls(numberToTake): nimGame.take(numberToTake) def initializeNewGame(): numberOfBalls = 5 # change this to read from Entry widget you add to GUI initializeNimAndGUI(numberOfBalls) ##### # 1. create a NimGame object with specified number of balls # 2. clear the graphics canvas # 3. based on number of balls, compute values ball size and spacing and set # global variable used for drawing the balls. # 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()
Background image of page 2
Show entire document
Sign up to view the entire interaction

Top Answer

Changes I picked to improve the game 1. use the status Label (statusLabel in the code) to provide more feedback to the player... View the full answer

nimGameWithGUI.py

# Note: if you want to use additional tkinter widgets, you will need to add
their names to
# the import list below
from tkinter import Tk, Canvas, Frame, Button, Label, Entry, END, LEFT, RIGHT,...

Sign up to view the full answer

Why Join Course Hero?

Course Hero has all the homework and study help you need to succeed! We’ve got course-specific notes, study guides, and practice tests along with expert tutors.

-

Educational Resources
  • -

    Study Documents

    Find the best study resources around, tagged to your specific courses. Share your own to gain free Course Hero access.

    Browse Documents
  • -

    Question & Answers

    Get one-on-one homework help from our expert tutors—available online 24/7. Ask your own questions or browse existing Q&A threads. Satisfaction guaranteed!

    Ask a Question
Ask a homework question - tutors are online