menator01
Gold Coder
Latest project finished. Could be optimized some.
Python:
import tkinter as tk
from random import choice, choices
from itertools import groupby
class Window():
def __init__(self, parent):
parent.columnconfigure(0, weight=1)
parent.rowconfigure(0, weight=0)
parent.rowconfigure(1, weight=1)
parent.configure(padx=5, pady=5)
self.parent = parent
self.letters = ['B','I','N','G','O']
header_frame = tk.Frame(parent)
header_frame.grid(column=0, row=0, sticky='new')
for index in range(len(self.letters)):
header_frame.grid_columnconfigure(index, weight=3, uniform='header')
for index, letter in enumerate(self.letters):
header = tk.Label(header_frame, text=letter, bg='#0000ff', fg='#ffffff')
header.grid(column=index, row=0, sticky='new', padx=1, pady=1)
header.configure(font=(None, 50, 'bold'))
self.card = tk.Frame(parent)
self.card.grid(column=0, row=1, sticky='news')
for index in range(len(self.letters)):
self.card.grid_columnconfigure(index, weight=3, uniform='columns')
self.card.grid_rowconfigure(index, weight=3, uniform='rows')
self.labels = []
index = 0
for col in range(5):
for row in range(5):
label = tk.Label(self.card)
label.configure(
highlightbackground = '#000000',
highlightcolor = '#000000',
highlightthickness = 1,
font = (None, 30, 'normal')
)
self.labels.append(label)
self.labels[index].grid(column=col, row=row, sticky='news', padx=0.5, pady=0.5)
index += 1
self.label = tk.Label(parent, text='Messages:', anchor='w', padx=10)
self.label.grid(column=0, row=2, sticky='new', padx=2, pady=4)
self.label.configure(font=(None, 18, 'normal'),
highlightbackground = '#555555',
highlightcolor = '#555555',
highlightthickness = 1)
btnframe = tk.Frame(parent)
btnframe.grid(column=0, row=3, sticky='news', pady=5)
btnframe.grid_columnconfigure(0, weight=3, uniform='button')
btnframe.grid_columnconfigure(1, weight=3, uniform='button')
self.drawbtn = tk.Button(btnframe, text='Draw', cursor='hand1', font=(None, 16, 'normal'))
self.drawbtn.grid(column=0, row=3, pady=10)
self.closebtn = tk.Button(btnframe, text='Exit', command=parent.destroy, cursor='hand1', font=(None, 16, 'normal'))
self.closebtn.grid(column=1, row=3, padx=5, pady=5)
self.closebtn.configure(activebackground='#ff0000', activeforeground='#ffffff', bg='tomato')
class Controller():
def __init__(self, window):
self.window = window
# Our list of bingo numbers - North American bingo uses 75 numbers
self.bingo_numbers = [f'{letter}{number}' for number in range(1,76) for letter in self.window.letters]
self.bingo_numbers_copy = self.bingo_numbers[:]
# Group by letter
self.grouped_numbers = {}
for word in self.bingo_numbers:
self.grouped_numbers.setdefault(word[0], []).append(word)
self.grouped_numbers = list(self.grouped_numbers.values())
# Get 5 from each list
card_nums = []
for index, item in enumerate(self.grouped_numbers):
card_nums.append(choices(self.grouped_numbers[index], k=5))
# List to hold bingo card numbers
self.card = []
for items in card_nums:
for item in items:
self.card.append(item)
# Bind the draw button to draw meyhod
self.window.drawbtn.configure(command=self.draw)
# Populate the bingo card
self.populate()
def populate(self):
''' Method for populating the bingo card '''
for index, label in enumerate(self.window.labels):
if len(self.card) > 0:
choose = self.card.pop(0)
if self.window.labels[index].grid_info().get('column') == 2 and self.window.labels[index].grid_info().get('row') == 2:
self.window.labels[index].configure(text='Free Space', bg='skyblue', font=(None, 18, 'bold'), wraplength=100)
else:
self.window.labels[index].configure(text=choose[1:], bg='#ffffff')
def draw(self):
''' Method for drawing a random item from bingo numbers '''
choose = choice(self.bingo_numbers_copy)
# Remove item from list so not drawn again
self.bingo_numbers_copy.remove(choose)
# Display drawn number
self.window.label.configure(text=f'Messages: ( {choose} ) was drawn')
# Do the comparison
self.compare(choose)
self.check()
def compare(self, choose):
''' Method for comparing drawn number with card numbers
Highlights background of matched numbers '''
# Need this for column numbers
header = list('BINGO')
# Grab the letter and text of drawn number
letter, number = choose[:1], choose[1:]
# Convert number to int
number = int(number)
# Loop through the card and get some info
for index, item in enumerate(self.window.labels):
# Get the text of the label
text = self.window.labels[index].cget('text')
# Get the column of the label
column = self.window.labels[index].grid_info().get('column')
# Compare text and column number to drawn number and column
# Highlight background
try:
if int(text) == number and header[column] == letter:
self.window.labels[index].configure(bg='skyblue')
except ValueError:
pass
def check(self):
# List of possible bingo
bingo = [
[(i,0) for i in range(5)],
[(i,1) for i in range(5)],
[(i,2) for i in range(5)],
[(i,3) for i in range(5)],
[(i,4) for i in range(5)],
[(0,i) for i in range(5)],
[(1,i) for i in range(5)],
[(2,i) for i in range(5)],
[(3,i) for i in range(5)],
[(4,i) for i in range(5)],
[(0,0),(1,1),(2,2),(3,3),(4,4)],
[(0,4),(1,3),(2,2),(3,1),(4,0)]
]
# Define some groups
groups = []
column_groups = {}
row_groups = {}
diag_groups = {}
# Grab all highlighted squares and add to group
squares = self.window.labels
for index, square in enumerate(squares):
cols = squares[index].grid_info().get('column')
rows = squares[index].grid_info().get('row')
if squares[index]['bg'] == 'skyblue':
groups.append((cols, rows))
# Group all highlighted squares by column
for sublist in groups:
key = sublist[0]
value = (sublist[0], sublist[1])
if key not in column_groups:
column_groups[key] = []
column_groups[key].append(value)
column_groups = list(column_groups.values())
# Sort for human readibility
column_groups = sorted(column_groups)
# Group all highlighted squares by rows
for sublist in groups:
key = sublist[1]
value = (sublist[1], sublist[0])
if key not in row_groups:
row_groups[key] = []
row_groups[key].append(value)
row_groups = list(row_groups.values())
# Sorted for human readibility
row_groups = sorted(row_groups)
diag1 = []
diag2 = []
for group in groups:
col, row = group
if col == 0 and row == 0:
diag1.append((col,row))
if col == 1 and row == 1:
diag1.append((col,row))
if col == 2 and row == 2:
diag1.append((col,row))
if col == 3 and row == 3:
diag1.append((col,row))
if col == 4 and row == 4:
diag1.append((col,row))
if col == 0 and row == 4:
diag2.append((col,row))
if col == 1 and row == 3:
diag2.append((col,row))
if col == 2 and row == 2:
diag2.append((col,row))
if col == 3 and row == 1:
diag2.append((col,row))
if col == 4 and row == 0:
diag2.append((col,row))
diags = [diag1, diag2]
allgroups = [diags, column_groups, row_groups]
for groups in allgroups:
for group in groups:
if group in bingo:
self.window.drawbtn.configure(command=self.reset, text='Reset')
self.window.label.configure(text=f'Messages: Bingo!')
def reset(self):
self.window.drawbtn.configure(command=self.draw, text='Draw')
self.window.label.configure(text='Messages')
self.bingo_numbers_copy = self.bingo_numbers[:]
# Get 5 from each list
card_nums = []
for index, item in enumerate(self.grouped_numbers):
card_nums.append(choices(self.grouped_numbers[index], k=5))
# List to hold bingo card numbers
self.card = []
for items in card_nums:
for item in items:
self.card.append(item)
self.populate()
if __name__ == '__main__':
root = tk.Tk()
root.title('BINGO')
root.geometry('500x600')
controller = Controller(Window(root))
root.mainloop()
Last edited: