Last active
September 27, 2022 13:35
-
-
Save RomanIakovlev/5a2ab290904ae2605fe43f81106799da to your computer and use it in GitHub Desktop.
A simple lotto game in Python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
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