Skip to content

Instantly share code, notes, and snippets.

@RomanIakovlev
Last active September 27, 2022 13:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RomanIakovlev/5a2ab290904ae2605fe43f81106799da to your computer and use it in GitHub Desktop.
Save RomanIakovlev/5a2ab290904ae2605fe43f81106799da to your computer and use it in GitHub Desktop.
A simple lotto game in Python
"""
A simple lotto game.
It creates random lotto tickets according to a user-defined shape, and then draws numbers at random
to check which ticket has all of its numbers matched first, becoming the winner.
"""
import random
import platform
import os
def _clr_scr():
if platform.system().lower() == 'windows':
clr_cmd = 'cls'
else:
clr_cmd = 'clear'
os.system(clr_cmd)
def _get_random_range(count, range_start, range_end):
order = list(range(range_start, range_end))
random.shuffle(order)
result = []
for _i in range(count):
if order:
result.append(order.pop())
return result
def _generate_ticket(lotto_column_sizes):
ticket = []
step = 0
for column_size in lotto_column_sizes:
column = _get_random_range(column_size, step * 10 + 1, step * 10 + 10)
column.sort()
ticket.append(column)
step += 1
return ticket
def _get_cell(cell, drawn_numbers):
if cell in drawn_numbers:
return f'│\u001b[32m{cell:^4}\u001b[0m'
else:
return f'│{cell:^4}'
def _print_tickets(tickets, lotto_column_sizes, drawn_numbers):
rows_num = max(lotto_column_sizes)
table_width = len(lotto_column_sizes) * 5 - 1
header = ''
for i, _ in enumerate(tickets):
header += f' Ticket {i+1}' + ' ' * (table_width - 3)
print(header)
print(('┌' + '─' * table_width + '┐ ') * len(tickets))
for i in range(rows_num):
line = []
for ticket in tickets:
line_items = [
curr_col[i] if i < len(curr_col) else "┈┈" for curr_col in ticket
]
line.extend([f"{_get_cell(i, drawn_numbers)}" for i in line_items])
print((('{}' * len(lotto_column_sizes) + '│ ') * len(tickets)).format(*line))
print(('└' + '─' * table_width + '┘ ') * len(tickets))
def _check_all_tickets(tickets, numbers, total_cells):
return [_game_won(ticket, numbers, total_cells) for ticket in tickets]
def _game_won(ticket, numbers, total_cells):
guessed_cell_count = 0
for num in numbers:
for column in ticket:
for cell in column:
if num == cell:
guessed_cell_count += 1
return guessed_cell_count == total_cells
def _number_in_any_ticket(number, tickets):
for ticket in tickets:
for column in ticket:
if number in column:
return True
return False
def _get_drawn_number_color(number, tickets):
if _number_in_any_ticket(number, tickets):
return '\u001b[32m'
else:
return '\u001b[31m'
def _print_game_state(tickets, lotto_column_sizes, drawn_numbers, draw_order):
_clr_scr()
_print_tickets(tickets, lotto_column_sizes, drawn_numbers)
all_numbers = [
f'{_get_drawn_number_color(num, tickets)}{num}\u001b[0m'
for num in drawn_numbers
]
print('Drawn numbers: ' + ('{}, ' * len(all_numbers)).format(*all_numbers))
print(f'Remaining numbers: {", ".join(map(str, draw_order))}')
def _generate_tickets(lotto_column_sizes):
try:
ticket_number = int(input('Enter number of playing tickets (1-3): '))
if ticket_number > 3:
ticket_number = 3
elif ticket_number < 1:
ticket_number = 1
except ValueError:
ticket_number = 3
return [_generate_ticket(lotto_column_sizes) for _ in range(ticket_number)]
def _run_main_loop(tickets, lotto_column_sizes, drawn_numbers, draw_order, total_cells):
game_over = False
numbers_to_draw = 1
while not game_over:
_print_game_state(tickets, lotto_column_sizes, drawn_numbers, draw_order)
try:
numbers_to_draw = int(
input(f'How many numbers to draw? [{numbers_to_draw}]: ')
)
except ValueError:
pass
for _ in range(min(len(draw_order), numbers_to_draw)):
drawn_numbers.append(draw_order.pop(0))
game_over = any(_check_all_tickets(tickets, drawn_numbers, total_cells))
if game_over:
break
def _print_game_result(
tickets, lotto_column_sizes, drawn_numbers, draw_order, total_cells
):
_print_game_state(tickets, lotto_column_sizes, drawn_numbers, draw_order)
ticket_stats = _check_all_tickets(tickets, drawn_numbers, total_cells)
winners = []
for i, pos in enumerate(ticket_stats):
if pos:
winners.append(f'Ticket {i+1}')
print(
f'Game over after {len(drawn_numbers)} moves, winning ticket(-s): {", ".join(winners)}'
)
def _setup_game():
column_sizes = []
column_count = 10
try:
column_count = int(input(f'How many columns in a ticket? [{column_count}]: '))
except ValueError:
pass
print('Now enter the size (height) of each column, separated by Enter: ')
for _ in range(column_count):
column_sizes.append(int(input()))
return column_sizes
def play_game():
"""
The main function that runs a single game and prints its result
"""
_clr_scr()
lotto_column_sizes = _setup_game()
total_cells = sum(lotto_column_sizes)
max_number = len(lotto_column_sizes) * 10 - 1
draw_order = _get_random_range(max_number, 1, max_number + 1)
drawn_numbers = []
tickets = _generate_tickets(lotto_column_sizes)
_run_main_loop(tickets, lotto_column_sizes, drawn_numbers, draw_order, total_cells)
_print_game_result(
tickets, lotto_column_sizes, drawn_numbers, draw_order, total_cells
)
if __name__ == "__main__":
play_game()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment