-1

I am attempting to make a Yahtzee game that works entirely, from rolling dice to keeping track of score, using tkinter to create a GUI. Code as follows:

from random import randint
from tkinter import *
import tkinter as tk

numbers = [0,0,0,0,0] # for storing numbers obtained after each roll

a = tk.Tk()
a.title('Yahtzee')

def Home():
    # not shown: clears the window, then adds a frame

    # not shown: checkbuttons so user can choose which dice to not roll

    # not shown: labels to display "rolled" numbers

    bRoll = tk.Button(a,text='Roll Dice',command=rollDice(5))
    bRoll.pack()
    bExit = tk.Button(a,text='Quit',command=Exit())
    bExit.pack()

    a.mainloop()

def rollDice(n):
    z = 0
    for x in range(1,n+1):
        y = randint(1,6)
        numbers[z] = y
        z=z+1
    Home()

def Clear(): # clears any widgets in the tkinter window for the next screen
    # not shown


def Exit(): # closes the program 
    a.destroy()

Home()

I have run into a problem, however: when I run the program, I get these two errors over and over until a recursion error stops the program:

File "C:\Users\skor8\Desktop\Python\YahtzeeAlt.py", line 32, in Home
    bRoll = tk.Button(a,text='Roll Dice',command=rollDice(5))
  File "C:\Users\skor8\Desktop\Python\YahtzeeAlt.py", line 45, in rollDice
    Home()

I can tell what's happening, the functions keep calling each other. Problem is, they are calling each other without the button in Home being pressed. I just don't know how to fix this.

Any ideas?

McJohnalds
  • 85
  • 6

2 Answers2

1

Your button command functions are being called during button construction. Since this happens in Home(), rollDice() in particular is recursively calling Home().

You should read this article - it explains how to pass command= functions to a button constructor without calling them. Basically you need to change these two lines of code...

    bRoll = tk.Button(a,text='Roll Dice',command=rollDice(5))
    ...
    bExit = tk.Button(a,text='Quit',command=Exit())

to be...

    bRoll = tk.Button(a,text='Roll Dice',command=lambda: rollDice(5))
    ...
    bExit = tk.Button(a,text='Quit',command=Exit)

Here is my version of your code. I prefer to subclass Window. Hopefully this will get you on your way. Good luck!

""" yahtzee.py - A Yahtzee-like game.
"""

import sys
import tkinter
import random

class Window(tkinter.Tk):
    def __init__(self, master=None):
        tkinter.Tk.__init__(self, master)
        self.bind('<Escape>', self.escape)

    def escape(self, event):
        self.withdraw()
        sys.exit()


def randint(m, n):
    return random.randrange(m, n)

class Yahtzee(Window):
    def __init__(self, master=None):
        Window.__init__(self, master)
        self.title('Yahtzee')

        f = tkinter.Frame(self)
        f.pack()

        num1 = tkinter.IntVar()
        tkinter.Checkbutton(f, text='#1', variable=num1).grid(row=1,column=1)
        num2 = tkinter.IntVar()
        tkinter.Checkbutton(f, text='#2', variable=num2).grid(row=2,column=1)
        num3 = tkinter.IntVar()
        tkinter.Checkbutton(f, text='#3', variable=num3).grid(row=3,column=1)
        num4 = tkinter.IntVar()
        tkinter.Checkbutton(f, text='#4', variable=num4).grid(row=4,column=1)
        num5 = tkinter.IntVar()
        tkinter.Checkbutton(f, text='#5', variable=num5).grid(row=5,column=1)

        self.numbers = [ 1, 2, 3, 4, 5 ]

        tkinter.Label(f, text=str(self.numbers[0])).grid(row=1,column=2)
        tkinter.Label(f, text=str(self.numbers[1])).grid(row=2,column=2)
        tkinter.Label(f, text=str(self.numbers[2])).grid(row=3,column=2)
        tkinter.Label(f, text=str(self.numbers[3])).grid(row=4,column=2)
        tkinter.Label(f, text=str(self.numbers[4])).grid(row=5,column=2)

        bRoll = tkinter.Button(self, text='Roll Dice', command=lambda: self.rollDice(5))
        bRoll.pack()
        bExit = tkinter.Button(self, text='Quit',command=self.Exit)
        bExit.pack()

    def rollDice(self, n):
        z = 0
        for x in range(1,n+1):
            y = randint(1,6)
            self.numbers[z] = y
            z=z+1
        ### Home()

    def Clear(self): # clears any widgets in the tkinter window for the next screen
        for widget in self.winfo_children():
            widget.destroy()

    def Exit(self): # closes the program 
        self.escape(None)


def main():
    yahtzee = Yahtzee()
    yahtzee.mainloop()
    return 0

if __name__ == '__main__':
    sys.exit(main())
Rusty Widebottom
  • 985
  • 2
  • 5
  • 14
0

Try not to copy and paste the entire code. Try to provide a small amount of code as possible since understanding other peoples code is very hard.