Tkinter number guessing game - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: General (https://python-forum.io/forum-1.html) +--- Forum: Code sharing (https://python-forum.io/forum-5.html) +--- Thread: Tkinter number guessing game (/thread-36712.html) |
Tkinter number guessing game - menator01 - Mar-21-2022 Another number guessing game import tkinter as tk from random import randint ''' Define some global variables start is the low number end is the high number e.g. guess a number between 1 and 20 count is the number of tries ''' start, end = 1, 20 count = 5 class Window: ''' Define the class window. Set some variables for our game. Setup the layout with tkinter self.number is a random generated number self.count is the number of tries to guess the number ''' def __init__(self, parent): self.number = self.random_number() self.counter = count parent.columnconfigure(0, weight=1) parent.rowconfigure(0, weight=1) container = tk.Frame(parent) container.grid(column=0, row=0, sticky='new') container.grid_columnconfigure(0, weight=3) header = tk.Label(parent, text='Number Guessing Game') header['font'] = ('times 16 bold') header['relief'] = 'groove' header.grid(column=0, row=0, sticky='new', pady=4, ipady=4) instructions = tk.Label(parent) instructions['text'] = f'Choose a number between {start} and {end}' instructions['bg'] = 'lightyellow' instructions['relief'] = 'groove' instructions.grid(column=0, row=1, sticky='new', pady=4) self.msgbox = tk.Label(parent, anchor='w') self.msgbox['relief'] = 'groove' self.msgbox['text'] = f'Tries Left: {self.counter}' self.msgbox.grid(column=0, row=2, sticky='new', pady=8) self.entry = tk.Entry(parent) self.entry.grid(column=0, row=3, sticky='new', pady=8) btn_frame = tk.Frame(parent) btn_frame.grid(column=0, row=4, sticky='new') for i in range(2): btn_frame.grid_columnconfigure(i, weight=3, uniform='btns') self.btn = tk.Button(btn_frame) self.btn['text'] = 'Submit' self.btn['command'] = lambda: self.check(self.entry.get()) self.btn.grid(column=0, row=0, sticky='new') self.reset_btn = tk.Button(btn_frame) self.reset_btn['text'] = 'Reset' self.reset_btn['state'] = 'disabled' self.reset_btn.grid(column=1, row=0, sticky='new') msg_container = tk.Frame(parent) msg_container['relief'] = 'groove' msg_container['highlightbackground'] = 'lightgray' msg_container['highlightcolor'] = 'lightgray' msg_container['highlightthickness'] = 1 msg_container.grid(column=0, row=5, sticky='new', pady=4) msg_container.grid_columnconfigure(0, weight=0) msg_container.grid_columnconfigure(1, weight=3) self.label = tk.Label(msg_container, text='MSG:', anchor='w') self.label.grid(column=0, row=0, sticky='new') self.msg_label = tk.Label(msg_container, anchor='w') self.msg_label.grid(column=1, row=0, sticky='new') self.entry.focus() self.entry.bind('<Return>', lambda num: self.check(self.entry.get())) def random_number(self): ''' random_number is a function for generating a random number between the start and ending numbers defined above ''' number = randint(start, end) return number def check(self, guess): ''' Check does several things With a try statement we check to make sure only whole numbers are entered. If not display an error message ''' try: guess = int(guess) # Convert gues to int self.counter = self.counter - 1 # Subtract 1 from the counter self.msgbox['text'] = f'Tries Left: {self.counter}' self.entry.delete(0, tk.END) # Clear the entry if guess > end or guess < start: # Check if the guess is within bounds if self.counter > count: # If the counter > than tries, set to default tries self.counter = count else: # Counter is below default. Add 1 back due to incorrect input self.counter = self.counter + 1 # Display error self.msg_label['text'] = f'Please choose a number between {start} and {end}' self.msg_label['fg'] = 'red' self.msgbox['text'] = f'Tries Left: {self.counter}' elif guess > self.number: # Display message that the guess was too high self.msg_label['text'] = f'{guess} is too high.' self.msg_label['fg'] = 'red' elif guess < self.number: # Display message that guess was too low self.msg_label['text'] = f'{guess} is too low.' self.msg_label['fg'] = 'darkorange' else: # Display message that guess was correct self.msg_label['text'] = f'You win! {guess} is correct.' self.msg_label['fg'] = 'green' self.btn['state'] = 'disabled' self.reset_btn['state'] = 'normal' self.reset_btn['command'] = self.reset if self.counter == 0: # Number of tries has been reached. Disable submit button and enable reset self.msg_label['text'] = 'You have no tries left.' self.msg_label['fg'] = 'tomato' self.btn['state'] = 'disabled' self.reset_btn['state'] = 'normal' self.reset_btn['command'] = lambda: self.reset() except ValueError: # Display error - input is not correct self.msg_label['text'] = 'Error! Please enter only whole numbers.' self.msg_label['fg'] = 'red' self.entry.delete(0, tk.END) def reset(self): ''' Resets all the default values and generates a new random number ''' self.counter = count self.btn['state'] = 'normal' self.reset_btn['state'] = 'disabled' self.msg_label['text'] = '' self.msg_label['fg'] = 'black' self.msgbox['text'] = f'Tries Left: {count}' self.number = self.random_number() def main(): root = tk.Tk() root['padx'] = 8 root['pady'] = 5 root.geometry('400x210+250+250') root.resizable(False, False) Window(root) root.mainloop() if __name__ == '__main__': main() RE: Tkinter number guessing game - BashBedlam - Mar-21-2022 Very Nice. RE: Tkinter number guessing game - menator01 - Mar-24-2022 Version 2 Trying to use dunder methods but, still doesn't seem right. import tkinter as tk import random as rnd class Counter: def __init__(self, value): self.value = value def __sub__(self, other): return Counter(self.value - other.value) class Number: def __init__(self, number): self.number = number def __lt__(self, number): return self.number < number def __gt__(self, number): return self.number > number def __eq__(self, number): return self.number == number class Window: def __init__(self, parent): self.parent = parent self.parent.columnconfigure(0, weight=1) self.parent.rowconfigure(0, weight=1) # Set the counter self.counter = Counter(3) self.random_number = Number(rnd.randint(1, 20)) # Main container holds all other containers and widgets container = tk.Frame(self.parent) container.grid(column=0, row=0, sticky='new') container.grid_columnconfigure(0, weight=3) # line1 container holds widgets on the first row line1_container = tk.Frame(container) line1_container['relief'] = 'groove' line1_container.grid(column=0, row=1, sticky = 'new', padx=4, pady=4, ipady=4, ipadx=2) line1_container.grid_columnconfigure(0, weight=0) line1_container.grid_columnconfigure(1, weight=0) line1_container.grid_columnconfigure(2, weight=3) # line2 container holds field and button widgets line2_container = tk.Frame(container) line2_container['relief'] = 'groove' line2_container.grid(column=0, row=2, sticky='new', padx=4, pady=4, ipady=4, ipadx=2) line2_container.grid_columnconfigure(0, weight=0) line2_container.grid_columnconfigure(1, weight=3) line2_container.grid_columnconfigure(2, weight=3) line3 = tk.Label(container, text='Choose a number between 1 and 20') line3['relief'] = 'groove' line3['font'] = 'times 10 italic' line3['fg'] = 'gray' line3.grid(column=0, row=3, sticky='new', padx=4, pady=4) # entry_frame is padding for the text field # (gives the appearence of not having the text right up against the left side) self.entry_frame = tk.Frame(line2_container) self.entry_frame['relief'] = 'sunken' self.entry_frame['borderwidth'] = 1 self.entry_frame['bg'] = 'white' self.entry_frame.grid(column=0, row=0, sticky='new', padx=4, pady=4) # The header contains the game name header = tk.Label(container) header['text'] = 'Tkinter Number Guessing Game' header['font'] = 'Sans 16 bold' header['fg'] = 'darkslateblue' header['relief'] = 'groove' header.grid(column=0, row=0, sticky='new', padx=4, pady=4, ipady=4, ipadx=2) # Label for displaying number of guesses left self.guess_left = tk.Label(line1_container, anchor='w') self.guess_left['bg'] = 'lightgray' self.guess_left['relief'] = 'groove' self.guess_left['text'] = 'Guesses Left: 3' self.guess_left.grid(column=0, row=0, sticky='new', ipadx=5) # Label for message header msgbox = tk.Label(line1_container, anchor='w') msgbox['text'] = 'MSG:' msgbox['relief'] = 'groove' msgbox['bg'] = 'lightgray' msgbox.grid(column=1, row=0, sticky='new') # Label for displaying all messages self.msgtext = tk.Label(line1_container, anchor='w', padx=8) self.msgtext['text'] = 'Choose a number between 1 and 20' self.msgtext['relief'] = 'groove' self.msgtext['bg'] = 'lightgray' self.msgtext.grid(column=2, row=0, sticky='new') # Entry field for entering numbers self.entry = tk.Entry(self.entry_frame, width=4) self.entry['relief'] = 'flat' self.entry.grid(column=0, row=0, sticky='new', padx=4) self.entry.focus() self.entry.bind('<Return>', lambda num: self.check_number(self.entry.get())) # Button for submitting numbers self.submit_button = tk.Button(line2_container, text='Submit') self.submit_button['cursor'] = 'hand2' self.submit_button['command'] = lambda: self.check_number(self.entry.get()) self.submit_button.grid(column=1, row=0, sticky='new', padx=2, pady=2) # Button for resetting everything to defaults self.reset_button = tk.Button(line2_container, text='Reset') self.reset_button['state'] = 'disabled' self.reset_button['cursor'] = 'no' self.reset_button.grid(column=2, row=0, sticky='new', padx=2, pady=2) # Method for checking guess against random number def check_number(self, guess): # Set some variables count = self.counter.value fgcolor = 'red' bgcolor = 'lightyellow' # Use a try statement in check for numbers only try: guess = int(guess) # We want the guess number to be between 1 and 20 if guess > 20 or guess < 1: msg = 'Please choose a number between 1 and 20' count += 1 setattr(self.counter, 'value', count) # Guess number is within spec # Compare the numbers and set the correct message else: if guess > self.random_number: msg = f'{guess} is too high' if guess < self.random_number: msg = f'{guess} is too low' # Correct number was guessed. Enable reset button and disable # the submit button. Also set some colors and other graphic views if guess == self.random_number: self.submit_button['state'] = 'disabled' self.entry.delete(0, tk.END) self.entry['state'] = 'disabled' self.entry_frame['bg'] = 'gray95' self.submit_button['cursor'] = 'no' self.reset_button['state'] = 'normal' self.reset_button['cursor'] = 'hand2' self.reset_button['command'] = lambda: self.reset() self.reset_button.bind('<Return>', lambda num: self.reset()) self.reset_button.focus() msg = f'Great job! {guess} was the correct number' fgcolor = 'lime' bgcolor = 'darkgreen' # A character other than a number was entered. # Display a error message except ValueError: msg = 'Please enter only whole numbers' count += 1 setattr(self.counter, 'value', count) # Clear entry field self.entry.delete(0, tk.END) # If the last guess has been used, enable and disable the coreect buttons. # Also set some graphic views such as colors and cursor if count == 1: setattr(self.counter, 'value', 0) count = 0 self.entry['state'] = 'disabled' self.entry_frame['bg'] = 'gray95' self.submit_button['state'] = 'disabled' self.reset_button['state'] = 'normal' self.reset_button['command'] = lambda: self.reset() self.reset_button['cursor'] = 'hand2' self.submit_button['cursor'] = 'no' self.reset_button.focus() self.reset_button.bind('<Return>', lambda num: self.reset()) msg = msg + ' Press reset to play again.' # We still have guesses left else: count = self.counter.value - 1 setattr(self.counter, 'value', count) self.guess_left['text'] = f'Guesses Left: {count}' self.msgtext['text'] = msg self.msgtext['fg'] = fgcolor self.msgtext['bg'] = bgcolor # Method for resetting game def reset(self): self.entry['state'] = 'normal' self.entry_frame['bg'] = 'white' self.entry.focus() self.submit_button['state'] = 'normal' self.reset_button['state'] = 'disabled' setattr(self.counter, 'value', 3) self.guess_left['text'] = f'Guesses Left: {self.counter.value}' self.reset_button['cursor'] = 'no' self.submit_button['cursor'] = 'hand2' self.msgtext['text'] = f'Game has been reset' self.msgtext['fg'] = 'red' self.msgtext['bg'] = 'lightyellow' self.random_number = Number(rnd.randint(1, 20)) def main(): root = tk.Tk() root.geometry('460x160+250+250') root.resizable(False, False) Window(root) root.mainloop() if __name__ == '__main__': main() |