Python: Prática de Ramificações e Laços
Última atualização: 2026-09-22
Aprendemos muita teoria — agora é hora de construir alguns projetos reais. Esta é uma lição prática. Usando if statements, for loops, while loops, break, continue e outros conceitos que aprendemos, vamos construir quatro programas completos passo a passo.
Para cada projeto, analisaremos os requisitos, escreveremos o código e discutiremos possíveis melhorias.
1. Projeto 1: Jogo de Adivinhação de Números (Melhorado)
Na Lição 08, escrevemos um jogo básico de adivinhação. Agora vamos melhorá-lo com seleção de dificuldade, limites de tentativas e um recurso de "jogar novamente."
(1) Requisitos
1. Jogador seleciona dificuldade: Fácil (1-50, ilimitado), Normal (1-100, 10 tentativas), Difícil (1-200, 7 tentativas)
2. Sistema gera aleatoriamente um número alvo
3. Após cada palpite, dica "muito alto" ou "muito baixo" e exibe tentativas restantes
4. Após acertar ou esgotar tentativas, pergunte "jogar novamente?"
5. Digite q para sair
(2) Código Completo (⭐⭐⭐)
▶ Exemplo: Jogo de Adivinhação de Números
import random
print("=" * 30)
print("Jogo de Adivinhação (Melhorado)")
print("=" * 30)
while True: # Laço externo: controla "jogar novamente"
# Seleciona dificuldade
print("\nSelecione a dificuldade:")
print("1. Fácil (1~50, ilimitado)")
print("2. Normal (1~100, 10 tentativas)")
print("3. Difícil (1~200, 7 tentativas)")
choice = input("Digite 1/2/3: ")
if choice == "1":
max_num = 50
max_attempts = float("inf") # Ilimitado
elif choice == "2":
max_num = 100
max_attempts = 10
elif choice == "3":
max_num = 200
max_attempts = 7
else:
print("Escolha inválida, usando Normal como padrão")
max_num = 100
max_attempts = 10
# Gera número alvo
target = random.randint(1, max_num)
attempts = 0
print(f"\nNúmero gerado entre 1~{max_num}. Comece a adivinhar!")
# Laço interno: lógica principal do jogo
while True:
# Verifica se as tentativas acabaram
if attempts >= max_attempts:
print(f"\nTentativas esgotadas! A resposta era {target}")
break
# Obtém palpite do jogador
guess_str = input(f"{max_attempts - attempts} tentativas restantes, digite seu palpite: ")
if guess_str.lower() == "q":
print("Saindo do jogo.")
max_attempts = -1 # Flag para notificar laço externo
break
# Valida entrada
if not guess_str.isdigit():
print("Por favor, digite um número válido!")
continue
guess = int(guess_str)
attempts += 1
# Verifica palpite
if guess < target:
print("Muito baixo, tente mais alto!")
elif guess > target:
print("Muito alto, tente mais baixo!")
else:
print(f"\nParabéns! A resposta era {target}!")
print(f"Você acertou em {attempts} tentativas.")
break
# Verifica se devemos sair completamente
if max_attempts == -1: # Jogador digitou q
break
# Pergunta por outra rodada
again = input("\nJogar novamente? (s/n): ")
if again.lower() != "s":
print("Obrigado por jogar, até logo!")
break
Destaque de design: O laço externo controla "jogar novamente," o laço interno controla o "processo de adivinhação." A flag
max_attempts = -1resolve o problema de sair de ambos os laços quando o jogador digita q. Uma abordagem mais elegante seria encapsular a lógica do jogo em uma função e usarreturnpara sair de uma vez.
2. Projeto 2: Tabuada de Multiplicação (Múltiplos Estilos)
Na Lição 08, imprimimos uma tabuada padrão. Um bom programador deve ser capaz de controlar flexivelmente estruturas de laço para exibir qualquer estilo.
(1) Estilo 1: Triângulo Inferior Padrão (⭐⭐)
▶ Exemplo: Triângulo Inferior Padrão
▶ ExperimenteSaída:
=== Triângulo Inferior Padrão ===
(2) Estilo 2: Retângulo Completo (⭐⭐)
▶ Exemplo: Retângulo Completo
▶ ExperimenteSaída:
=== Retângulo Completo ===
(3) Estilo 3: Triângulo Superior (⭐⭐⭐)
▶ Exemplo: Triângulo Superior
▶ ExperimenteSaída:
=== Triângulo Superior ===
1x1=1 1x2=2 1x3=3 ... 1x9=9
2x2=4 2x3=6 ... 2x9=18
3x3=9 ... 3x9=27
...
9x9=81
Insight principal: O desafio do triângulo superior é o "alinhamento de espaços" — cada linha precisa de
(i-1) * 2caracteres de tabulação de indentação. Isso usa dois laços internos: o primeiro imprime espaços, o segundo imprime as fórmulas.
3. Projeto 3: Calculadora Simples (Melhorada)
Nos exercícios da Lição 08, escrevemos uma calculadora básica. Agora vamos fazer uma versão melhorada suportando operações contínuas com histórico.
(1) Requisitos
1. Começa com resultado atual = 0
2. Usuário digita: operador número, ex.: "+ 5"
3. Operadores suportados: + - * / ** // % clear exit
4. clear redefine o resultado para 0
5. exit sai do programa
6. Após cada operação, mostre o resultado atual e o histórico
(2) Código Completo (⭐⭐⭐)
▶ Exemplo: Calculadora Melhorada
print("=" * 40)
print("Calculadora Melhorada")
print("Formato: operador número, ex.: + 5")
print("Suportados: + - * / ** // %")
print("Comandos especiais: clear reset exit quit")
print("=" * 40)
result = 0.0
history = [] # Armazena histórico de operações
while True:
# Exibe resultado atual
print(f"\nResultado atual: {result}")
# Obtém entrada do usuário
cmd = input(">>> ").strip()
# Trata comandos especiais
if cmd.lower() in ("exit", "quit"):
print("Obrigado por usar!")
break
if cmd.lower() == "clear":
result = 0.0
history.clear()
print("Redefinido para 0")
continue
# Analisa comandos de operação regulares
parts = cmd.split()
if len(parts) != 2:
print("Formato inválido! Digite: operador número")
continue
op, num_str = parts
# Valida número
if not num_str.replace(".", "").isdigit() or num_str.count(".") > 1:
print("Número inválido!")
continue
num = float(num_str)
# Executa operação
old_result = result
if op == "+":
result += num
elif op == "-":
result -= num
elif op == "*":
result *= num
elif op == "/":
if num == 0:
print("Erro: Não é possível dividir por zero!")
continue
result /= num
elif op == "**":
result **= num
elif op == "//":
if num == 0:
print("Erro: Não é possível dividir por zero!")
continue
result //= num
elif op == "%":
if num == 0:
print("Erro: Não é possível dividir por zero!")
continue
result %= num
else:
print(f"Operador inválido: {op}")
continue
# Registra histórico
history.append(f"{old_result} {op} {num} = {result}")
# Exibe resultado
print(f"= {result}")
# Mostra últimas 3 entradas do histórico
if len(history) >= 1:
print("--- Histórico Recente ---")
for item in history[-3:]:
print(f" {item}")
Execução de exemplo:
>>> + 10
= 10.0
--- Histórico Recente ---
0.0 + 10.0 = 10.0
>>> * 3
= 30.0
--- Histórico Recente ---
0.0 + 10.0 = 10.0
10.0 * 3.0 = 30.0
>>> / 0
Erro: Não é possível dividir por zero!
>>> clear
Redefinido para 0
Mentalidade de programação: Este exemplo mostra a interação clássica de laços e condições —
while Truemantém o programa em execução,if-elif-elselida com várias entradas,continuepula entrada inválida, ebreaksai normalmente.
4. Projeto 4: Localizador de Números Primos
Permita que o usuário insira um intervalo, exiba todos os números primos dentro desse intervalo e os conte.
(1) Requisitos
1. Usuário insere valores inicial e final
2. Programa exibe todos os primos nesse intervalo
3. Exibe 10 por linha, alinhados
4. Mostra a contagem total de primos
(2) Código Completo (⭐⭐⭐)
▶ Exemplo: Localizador de Números Primos
print("Localizador de Números Primos")
print("Digite um intervalo, e eu encontrarei todos os primos.")
# Obtém intervalo
start_str = input("Valor inicial (>=2): ")
end_str = input("Valor final: ")
# Valida entrada
if not (start_str.isdigit() and end_str.isdigit()):
print("Por favor, digite números inteiros positivos válidos!")
else:
start = int(start_str)
end = int(end_str)
if start < 2:
start = 2
print("Valor inicial ajustado para 2 (primos começam em 2)")
if start > end:
print("Valor inicial não pode ser maior que o value final!")
else:
primes = [] # Armazena primos encontrados
# Verifica cada número no intervalo
for num in range(start, end + 1):
# Verifica se num é primo
is_prime = True
for i in range(2, int(num ** 0.5) + 1):
if num % i == 0:
is_prime = False
break
if is_prime:
primes.append(num)
# Exibe resultados
print(f"\nEncontrados {len(primes)} primos entre {start} e {end}:")
for i, prime in enumerate(primes, 1):
print(f"{prime:5d}", end="")
if i % 10 == 0: # Nova linha a cada 10
print()
print() # Nova linha final
Exemplo de saída:
Valor inicial (>=2): 50
Valor final: 200
Encontrados 34 primos entre 50 e 200:
53 59 61 67 71 73 79 83 89 97
101 103 107 109 113 127 131 137 139 149
151 157 163 167 173 179 181 191 193 197
199
Dica de otimização: Ao verificar se um número é primo, você não precisa dividir até
num-1— apenas atésqrt(num). Senumtem um fator maior quesqrt(num), ele deve ter um fator pareado menor quesqrt(num). Esta otimização é muito eficaz para grandes intervalos (100.000+).
5. Projeto 5: IMC + Verificador de Força de Senha
Este projeto reúne operadores aritméticos, operadores de comparação, operadores lógicos, condicionais e métodos de string para resolver dois problemas comuns do mundo real.
(1) Parte 1: Índice de Massa Corporal (IMC) (⭐⭐)
IMC (Índice de Massa Corporal) é uma medida internacionalmente usada de gordura corporal. A fórmula é simples:
IMC = peso(kg) / altura(m)^2
▶ Exemplo: Calculadora de IMC
▶ ExperimenteSaída:
=== Índice de Massa Corporal ===
Peso: 68 kg
Altura: 1.75 m
IMC: 22.2
Categoria: Normal
Dica: Comparações encadeadas como
18.5 <= bmi < 24são muito mais limpas quebmi >= 18.5 and bmi < 24.
(2) Parte 2: Verificador de Força de Senha (⭐⭐⭐)
Escreva um programa para determinar se a senha de um usuário é segura. A força da senha depende do seu comprimento e dos tipos de caracteres que contém.
▶ Exemplo: Verificador de Força de Senha
▶ ExperimenteSaída:
=== Verificador de Força de Senha ===
Senha: Py3#thon
Comprimento: 8
Contém dígito: True
Contém letra: True
Contém caractere especial: True
Força da senha: Média
Detalhes:
len()obtém o comprimento da string,isdigit()verifica dígitos,isalpha()verifica letras,isalnum()verifica se apenas letras e dígitos (retornaFalsese houver caracteres especiais — negado comnotse torna "contém caractere especial"). Estes métodos serão abordados sistematicamente na lição de strings.
6. Erros Comuns de Ramificação/Laço
Todo mundo comete erros ao escrever código, especialmente iniciantes em laços. Aqui estão as armadilhas mais típicas.
(1) Erro 1: Laço Infinito — Esquecer de Atualizar a Variável de Condição
# Errado
n = 1
while n <= 10:
print(n)
# esqueceu n += 1 — nunca termina
# Correto
n = 1
while n <= 10:
print(n)
n += 1
(2) Erro 2: Confundir = com ==
# Errado
if score = 100: # Isto é atribuição, não comparação!
print("Perfeito!")
# Correto
if score == 100:
print("Perfeito!")
(3) Erro 3: Modificar uma Lista Durante a Iteração
# Errado — deletar durante iteração causa pulos
numbers = [1, 2, 3, 4, 5]
for num in numbers:
if num % 2 == 0:
numbers.remove(num)
print(numbers) # Pode não ser o que você espera
# Correto — crie uma nova lista
numbers = [1, 2, 3, 4, 5]
odd_numbers = [num for num in numbers if num % 2 != 0]
print(odd_numbers)
(4) Erro 4: Entender Errado o Valor Final de range()
# Errado: esperando range(5) exibir 1 2 3 4 5
for i in range(5):
print(i) # Saída real: 0 1 2 3 4
# Correto
for i in range(1, 6):
print(i) # Saída: 1 2 3 4 5
7. Casos de Uso Comuns
| Cenário | Técnica de Laço/Ramificação | Descrição |
|---|---|---|
| Processamento de dados (filtragem, limpeza) | for + continue |
Pular dados inválidos |
| Menu de interação com usuário | while True + break |
Mostrar menu repetidamente até sair |
| Carregamento paginado | while + condição |
Até não haver mais dados |
| Busca/pesquisa | for + break + else |
Parar ao encontrar; else se não encontrado |
| Processamento em lote de arquivos | for + lógica aninhada |
Iterar cada arquivo em um diretório |
| Laço principal de jogo | while True + tratamento de eventos |
Renderização contínua e resposta a entrada |
❓ Perguntas Frequentes
False? 2) O corpo do laço modifica a variável de condição? 3) while True tem um break correspondente? Adicionar print() para exibir valores-chave de variáveis é a maneira mais eficaz de depurar laços infinitos.range() ou iterar sobre uma lista?range() retorna uma sequência preguiçosa sem gerar todos os números de uma vez. range(1000000) usa quase nenhuma memória, enquanto list(range(1000000)) usa muita. Para grandes contagens de iteração, use range() diretamente para melhor eficiência de memória.📖 Resumo
- Jogo de Adivinhação Melhorado: Laço externo para "jogar novamente," laço interno para "adivinhar," use
while True+breakpara gerenciamento de saída de laço multinível - Estilos de Tabuada: Controle os limites do
range()do laço interno para exibir triângulo inferior, triângulo superior, retângulo e mais - Calculadora Melhorada:
continuepara pular entrada inválida, lista para armazenar histórico,split()para analisar entrada do usuário - Localizador de Números Primos: Otimize para verificar até
sqrt(num)para eficiência;enumerate(primos, 1)para saída numerada - Dicas de Depuração: Três elementos para verificação de laço infinito, distinga
=de==, não modifique listas durante iteração
📝 Exercícios
⭐: Números Narcisistas
Um "número narcisista" é um número de 3 dígitos onde a soma dos cubos de seus dígitos é igual ao próprio número. Por exemplo: 153 = 1^3 + 5^3 + 3^3.
Use um laço for para encontrar todos os números narcisistas (existem 4).
Dica: Use range(100, 1000) para iterar todos os números de 3 dígitos; use // e % para extrair dígitos das centenas, dezenas e unidades.
⭐⭐: Imprimir um Losango
Aceite um número ímpar n do usuário, depois exiba um losango feito de * no console.
Exemplo (n=5):
*
***
*****
***
*
Dica: Um losango tem metade superior e inferior. Para a metade superior, faça laço i de 1 a n//2 + 1, diminuindo espaços e aumentando asteriscos.
⭐⭐⭐: Sistema de Gerenciamento de Notas de Alunos
Escreva um programa que implemente os seguintes recursos:
1. Insira notas dos alunos (digite q para parar)
2. Calcule total, média, nota mais alta e mais baixa
3. Conte alunos em cada faixa: 90-100 (Excelente), 80-89 (Bom), 70-79 (Médio), 60-69 (Aprovado), <60 (Reprovado)
4. Exiba notas ordenadas da mais alta para a mais baixa
Requisitos:
- Use laço
while Truepara coletar notas - Use uma lista para armazenar notas
- Use laço
forpara contar faixas de notas - Use
sorted(..., reverse=True)para ordenação
Este projeto aplica de forma abrangente laços, listas, ordenação e estatísticas. Completá-lo significa que você realmente domina o fluxo de controle básico do Python.