![]() |
|
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()
|