Python Forum
General Coding - Bingo Generator
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
General Coding - Bingo Generator
#3
I was intrigued by your project and thought I would give it a spin as well. This is what I have as of now.
Problem - getting the row number from the bingo card for comparison.

Todo:
  • Detect when there is a bingo
  • End game when there is a bingo
  • Create button to reset game
  • Grab all highlighted squares
  • Group highlighted squares by columns and rows
  • Group highlighted squares by diagonals


Updated code by the strike through on todo
Any help on getting diagonals would be great.


Finished. A working bingo game in tkinter.
Code could be optimized a little. Especially the part at getting the diagonals. (Lots of if)

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()

Attached Files

Thumbnail(s)
   
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags
Download my project scripts


Reply


Messages In This Thread
General Coding - Bingo Generator - by Playpatterns - Nov-04-2024, 02:24 PM
RE: General Coding - Bingo Generator - by menator01 - Nov-05-2024, 11:34 PM
RE: General Coding - Bingo Generator - by menator01 - Nov-06-2024, 02:56 PM
RE: General Coding - Bingo Generator - by menator01 - Nov-06-2024, 08:22 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  coding a loot generator matt1984 1 1,275 Aug-16-2023, 05:08 AM
Last Post: Pedroski55
  General Coding Help biswajitmaity 2 2,376 Aug-25-2021, 03:04 PM
Last Post: jefsummers
  General coding Ellimann 2 3,052 Aug-25-2020, 05:43 AM
Last Post: buran
  General coding help prathmesh 1 2,429 Apr-01-2020, 01:23 PM
Last Post: buran
  general coding error karai 1 3,098 Mar-21-2018, 06:36 AM
Last Post: Gribouillis
  receive from a generator, send to a generator Skaperen 9 7,218 Feb-05-2018, 06:26 AM
Last Post: Skaperen

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020