Executando verificação de segurança...
10

Gambiarra é um termo amplo, mas eu considero que é qualquer coisa que seja mal feita ou que está longe de ser a solução ideal. É uma daquelas coisas que é meio difícil explicar de forma objetiva, mas vc sabe que é quando vê.

gambiarra


No seu caso, eu não diria que é gambiarra, apenas que dá pra simplificar a lógica e melhorar alguns detalhes.

Por exemplo, vc cria um dicionário com as regras. Mas vc só usa os valores, e em nenhum momento utiliza as chaves. Além disso, elas parecem meio redundantes: toda vez que vc tem chaves do tipo "coisa 1", "coisa 2", etc, é um forte indício de que talvez só precise de uma lista (ou array) dessas "coisas".

Outro detalhe é que input sempre retorna uma string, então usar str(input()) é redundante e desnecessário.

Quanto aos loops, eu faria diferente, mas aí talvez seja gosto pessoal: eu não gosto muito dessas variáveis de controle ask e ask1. E a lógica de pedir pra digitar de novo até que o valor seja "y" ou "n" pode ser movida para uma função, isolando-a do loop principal. Algo assim:

import time

def ask(text):
    while True: # enquanto não digitar "y" ou "n", continua o loop
        answer = input(text)
        if answer in ('y', 'n'):
            return answer # return sai da função, devolvendo o valor digitado

rules = [
    "You can't talk about Fight Club",
    "You can't talk about Fight Club",
    "You can't talk about Fight Club",
    "Only one fight at a time",
    "Only two people fight at a time",
    "No shoes or shirts",
    "Fights continue until necessary",
    "First-time attendees must fight"
]

# só entra no loop se a pessoa quiser saber as regras
if ask('$ Do you want to know the rules?(y/n) ') == 'y':
    while True:
        for rule in rules:
            print(f"* {rule}")
            time.sleep(1)
        if ask('$ Did you understand the rules?(y/n) ') == 'y':
            break # se entendeu as regras, sai do while

print('# Welcome to Fight Club')

Repare na função ask: eu não preciso colocar a pergunta uma vez antes do while e outra dentro dele. Basta repeti-lo indefinidamente, até que seja digitado "y" ou "n".

Depois, posso usar essa função para ambas as perguntas (se quer saber as regras, e se entendeu). Note que nem precisa de variáveis auxiliares, posso usar o retorno da função ask diretamente (eu fiz assim porque o valor não é utilizado mais de uma vez depois disso, mas caso fosse, aí justifica usar uma variável para guardar o valor digitado).

Também mudei a lógica: eu só entro no loop que mostra as regras se a pessoa quiser vê-las. E se a pessoa entendeu as regras, posso interromper o loop.

Já a mensagem "welcome" é sempre mostrada no final, então faz mais sentido deixá-la fora do loop.


Se não quiser mudar para usar while True e break, pelo menos mude os nomes das variáveis, pois ask e ask1 não deixa muito claro o que cada uma é. Poderia ser algo como want_to_know e understood, por exemplo.

Outra opção é fazer com que a função ask retorne True ou False, já que a pergunta só admite duas respostas possíveis ("sim" ou "não"). Aí no if eu nem preciso verificar se é "y" ou "n":

import time

# retorna True se digitar "y" ou False se digitar "n"
# se não for nenhum, pede para digitar de novo
def ask(text):
    while True:
        answer = input(text)
        if answer == 'y':
            return True
        if answer == 'n':
            return False

rules = [
    "You can't talk about Fight Club",
    "You can't talk about Fight Club",
    "You can't talk about Fight Club",
    "Only one fight at a time",
    "Only two people fight at a time",
    "No shoes or shirts",
    "Fights continue until necessary",
    "First-time attendees must fight"
]

# não precisa mais comparar se é igual a "y"
if ask('$ Do you want to know the rules?(y/n) '):
    while True:
        for rule in rules:
            print(f"* {rule}")
            time.sleep(1)
        if ask('$ Did you understand the rules?(y/n) '):
            break # se entendeu as regras, sai do while

print('# Welcome to Fight Club')
Carregando publicação patrocinada...
2

Nossa mano, que aula sobre códigos bem escritos, declaração correta de variáveis, remoção de partes inúteis no código👏. Muito obrigado mesmo, me ajudou bastante agora, vou corrigir essas redundâncias no meu código e irei melhorar esse ponto do ask e dos loops que você mencionou, mandei até 2 tabcoins para você!

1

Então, eu consegui melhorar isso das variáveis e das redundâncias no código como o str(input()), mas essa parte nova da função do ask eu consigo entender, mais ou menos, de como ela funciona, mas não tenho total compreensão, isso me faz pensar se, no meu atual nível de iniciante, seria uma boa fazer isso no meu código, eu acho fica um pouco estranho uma parte de um código ser feita como um pleno e outra parte como um júnior, entende o que estou querendo dizer?

7

Qual parte exatamente vc não entendeu?

while True é um loop "infinito", já que a condição para se repetir é True (ou seja, sempre é verdadeira).

Dentro dele tem o input, e depois eu vejo se o que foi digitado é "y" ou "n": if answer in ('y', 'n'). Basicamente, ('y', 'n')é uma tupla contendo as strings 'y' e 'n', e o if verifica se answer é um dos valores desta tupla.

Claro que eu poderia ter feito if answer == 'y' or answer == 'n', também funciona. Nesse caso tanto faz um ou outro, mas se vc tivesse mais opções para verificar (digamos que 10, 20 ou até mais, por exemplo), uma tupla fica mais sucinto do que vários or. Por exemplo:

# supondo que existam 20 valores possíveis
if valor in ('valor1', 'valor2', 'valor3', .... , 'valor20'):

# o if acima é mais sucinto que:
if valor == 'valor1' or valor == 'valor2' or valor == 'valor3' ...  or valor == 'valor20':

Enfim, se entrar no if (ou seja, se digitar "y" ou "n"), ele retorna o valor que foi digitado (é o que o return faz). Um detalhe importante é que o return encerra a função (ou seja, ele também sai do while).


Enfim, se deixar assim fica mais claro?

import time

rules = [
    "You can't talk about Fight Club",
    "You can't talk about Fight Club",
    "You can't talk about Fight Club",
    "Only one fight at a time",
    "Only two people fight at a time",
    "No shoes or shirts",
    "Fights continue until necessary",
    "First-time attendees must fight"
]

while True:
    want_to_know = input('$ Do you want to know the rules?(y/n) ')
    if want_to_know == 'y' or want_to_know == 'n':
        break # sai do while

if want_to_know == 'y':
    while True:
        for rule in rules:
            print(f"* {rule}")
            time.sleep(1)
        while True:
            understood = input('$ Did you understand the rules?(y/n) ')
            if understood == 'y' or understood == 'n':
                break # sai do while referente ao understood
        if understood == 'y':
            break # se entendeu as regras, sai do while externo

print('# Welcome to Fight Club')

Agora eu removi a função e usei um while para cada pergunta. A diferença é que vez de return, eu uso break, que serve para interromper um loop. Ou seja, se digitar "y" ou "n", ele sai do while, e se digitar outra coisa, o loop continua, chamando input novamente.

É basicamente o mesmo que a função faz, a única diferença é que a função precisa retornar o valor para quem a chama, por isso ela usa return em vez de break.

Mas repare que a parte das perguntas é praticamente igual (faz a pergunta, se for "y" ou "n" para, senão pergunta de novo). E quando vc tem trechos repetitivos que fazem basicamente a mesma coisa com poucas variações, estes trechos são fortes candidatos a ficarem isolados em uma função própria.

Outro ponto é que ter um loop dentro do outro pode deixar mais confuso, ainda mais se cada um tem seu break. Isso até seria um argumento contra o break, mas eu acho que na verdade é um argumento a favor de criar a função ask :-)


Aqui talvez seja uma questão de "estilo"/gosto pessoal, mas tem gente que prefere fazer algo como:

want_to_know = None
while want_to_know != 'y' and want_to_know != 'n':
    want_to_know = input('$ Do you want to know the rules?(y/n) ')

Ou seja, primeiro eu inicializo a variável com um valor que eu sei que é inválido, só para forçar a entrada no while. Também serve, veja qual fica mais claro para você.

2

Não sei nem como te agredecer mano, que explicação bem feita, adcionou muito ao meu conhecimento, mandei o máximo de TabCoins que o site me permitiu para você, parabéns e muito obrigado👏 :)

1

Boa noite mano👋, fiquei o dia buscando entender linha por linha desse código e somente agora implementei ele com 100% de compreensão do codebase do meu projeto, por ficar buscando tanto compreender consegui encontrar até outra forma de otimização do código, e gostaria de mandar para você para uma avaliação se possível, desde já agradeço novamente pelo conhecimento passado pelos postos acima, me ajudaram muito!

def ask(text):
   while True:
    ask = input(text)
    if ask == "y":
      return True
    if ask == "n":
      return False
if ask("Do you want to know the rules?(y/n) "):
   while True:
      for rule in rules:
        print(f"* {rule}")
        time.sleep(0.5)
      understood = ask("Did you understand the rules?(y/n) ")
      if understood:
        break