Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!
  • Guest, before posting your code please take these rules into consideration:
    • It is required to use our BBCode feature to display your code. While within the editor click < / > or >_ and place your code within the BB Code prompt. This helps others with finding a solution by making it easier to read and easier to copy.
    • You can also use markdown to share your code. When using markdown your code will be automatically converted to BBCode. For help with markdown check out the markdown guide.
    • Don't share a wall of code. All we want is the problem area, the code related to your issue.


    To learn more about how to use our BBCode feature, please click here.

    Thank you, Code Forum.

Bingo with tkinter and python

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:

New Threads

Latest posts

Buy us a coffee!

Back
Top Bottom