Projeto Jogo de Adivinhação
O computador pensa num número de 1 a 100 e você tenta adivinhar. A cada palpite, ele diz "mais alto" ou "mais baixo", até você acertar ou as tentativas acabarem. É um jogo pequeno, mas tem tudo o que um programa de verdade tem: um sorteio, um laço, decisões, uma conta de tentativas e a obrigação de não quebrar quando alguém digita "sete" no lugar de 7.
- Sortear números com o módulo random (
randinte a sementeseed) e usar import. - Converter o palpite com int() e comparar com < e ==.
- Repetir até acertar com while.
- Contar e limitar as tentativas com for, range(), break e o else dos laços.
- Validar o palpite com try e except e
continue. - Organizar a partida numa função que devolve um resultado com return, e guardar o recorde.
O que vamos construir
O jogo pronto, no terminal da Ana. Os números depois dos dois-pontos foram digitados por ela; o resto é o programa:
$ python3 adivinhacao.py === Jogo de Adivinhação === Pensei num número de 1 a 100. Você tem 7 tentativas. Tentativa 1/7: 50 Mais alto! Tentativa 2/7: 75 Mais baixo! Tentativa 3/7: 62 Mais alto! Tentativa 4/7: 68 Mais baixo! Tentativa 5/7: 65 Mais baixo! Tentativa 6/7: 63 Acertou em 6 tentativa(s)! Novo recorde! Seu recorde: 6 tentativa(s). Jogar de novo? (s/n): s Pensei num número de 1 a 100. Você tem 7 tentativas. Tentativa 1/7: 50 Mais baixo! Tentativa 2/7: 25 Mais baixo! Tentativa 3/7: 12 Mais baixo! Tentativa 4/7: 6 Mais alto! Tentativa 5/7: 9 Mais baixo! Tentativa 6/7: 7 Mais alto! Tentativa 7/7: 8 Acertou em 7 tentativa(s)! « 7 não bate o recorde de 6 Seu recorde: 6 tentativa(s). Jogar de novo? (s/n): s Pensei num número de 1 a 100. Você tem 7 tentativas. Tentativa 1/7: 10 Mais alto! Tentativa 2/7: 20 Mais alto! Tentativa 3/7: 30 Mais alto! Tentativa 4/7: 40 Mais baixo! Tentativa 5/7: 39 Mais baixo! Tentativa 6/7: 38 Mais baixo! Tentativa 7/7: 37 Mais baixo! Suas tentativas acabaram. O número era 36. « desta vez ela perdeu Seu recorde: 6 tentativa(s). Jogar de novo? (s/n): n Até a próxima!
Cinco versões, uma novidade em cada:
- Um sorteio, um palpite (
import random,randint,int). - Dicas até acertar (
while). - Tentativas contadas e limitadas (
for,range,break,else). - Palpite validado (
try/except,continue). - Várias partidas e recorde (
def,return,None).
Antes de começar
Este projeto usa o que você viu na Calculadora: input(), conversão, if/elif e while. Crie a pasta do jogo; o arquivo vai se chamar adivinhacao.py (sem acento e sem cedilha no nome do arquivo, que é o costume):
$ mkdir -p projetos/adivinhacao $ cd projetos/adivinhacao
Antes de tudo: sorteio e semente
O sorteio vem do módulo random ("aleatório"), que faz parte do Python: basta um import random no começo do programa. A função random.randint(1, 100) sorteia um número inteiro de 1 a 100, com o 1 e o 100 incluídos. No modo interativo:
$ python3 Python 3.14.4 (main, Aug 20 2026, 10:41:58) [GCC 15.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import random >>> random.randint(1, 100) 81 >>> random.randint(1, 100) 49 >>> random.seed(42) >>> random.randint(1, 100) 82 >>> random.randint(1, 100) 15 >>> random.seed(42) >>> random.randint(1, 100) 82 >>> exit()
Os dois primeiros sorteios deram 81 e 49 no computador da Ana; no seu, vão dar outros números, e a cada vez outros. Agora repare no random.seed(42): depois dele, o primeiro sorteio deu 82, o segundo 15, e quando a Ana chamou random.seed(42) de novo, o sorteio voltou a dar 82.
seed)
O computador não "joga dados" de verdade: ele calcula uma sequência de números que parecem aleatórios, a partir de um número inicial, a semente (em inglês, seed). Sem seed, o Python escolhe uma semente diferente a cada execução, e o jogo é imprevisível. Com random.seed(42), a semente é sempre 42, e a sequência é sempre a mesma: 82, 15, 4, 95…
Isso é ótimo para testar: se o número secreto é sempre 82, dá para conferir se o programa responde certo. Por isso, todas as missões desta página começam com random.seed(42), e o número secreto delas é sempre 82 (e, numa segunda partida, 15). No jogo de verdade, a linha do seed sai: senão a Ana decoraria a resposta.
import random random.seed(42) print(random.randint(1, 100), random.randint(1, 100), random.randint(1, 100))
$ python3 semente.py 82 15 4 $ python3 semente.py 82 15 4
Versão 1 · Um sorteio, um palpite
A versão mais simples: o programa sorteia, a pessoa dá um palpite, e o programa diz se ela acertou.
import random
secreto = random.randint(1, 100)
print("Pensei num número de 1 a 100.")
palpite = int(input("Seu palpite: "))
if palpite == secreto:
print("Acertou!")
else:
print(f"Errou! O número era {secreto}.")
- import random
- Traz o módulo
randompara o programa. Fica sempre no começo do arquivo (veja Módulos e import). - secreto = random.randint(1, 100)
- Sorteia o número e guarda na variável
secreto. Orandom.na frente diz de qual módulo vem a função. - int(input("Seu palpite: "))
- Pergunta e converte o texto em número inteiro. Aqui é
int, e nãofloat: o número secreto não tem casas decimais. - if palpite == secreto:
- Compara os dois números.
- f"Errou! O número era {secreto}."
- Quando erra, a pessoa merece saber qual era.
$ python3 adivinhacao.py Pensei num número de 1 a 100. Seu palpite: 50 Errou! O número era 81. $ python3 adivinhacao.py Pensei num número de 1 a 100. Seu palpite: 50 Errou! O número era 39.
O mesmo palpite, dois números secretos diferentes: o sorteio funciona. Mas com um palpite só, acertar é questão de sorte (uma chance em cem). A versão 2 dá dicas.
import
$ python3 adivinhacao.py
Traceback (most recent call last):
File "/home/ana/projetos/adivinhacao/adivinhacao.py", line 1, in <module>
secreto = random.randint(1, 100)
^^^^^^
NameError: name 'random' is not defined. Did you forget to import 'random'?
NameError: name 'random' is not defined = "o nome random não está definido". Sem o import random, o Python não sabe o que é random; o ^^^^^^ aponta exatamente essa palavra. E o próprio Python dá a dica: "Did you forget to import 'random'?" = "Você esqueceu de importar random?". Como consertar: import random na primeira linha.
random.py na pasta
A Ana quis testar o sorteio num arquivo à parte e o chamou de random.py, na mesma pasta do jogo (o arquivo só tinha um print("testando o sorteio")). Depois disso, o jogo parou de funcionar:
$ python3 adivinhacao.py
testando o sorteio
Traceback (most recent call last):
File "/home/ana/projetos/adivinhacao/adivinhacao.py", line 3, in <module>
secreto = random.randint(1, 100)
^^^^^^^^^^^^^^
AttributeError: module 'random' has no attribute 'randint' (consider renaming '/home/ana/projetos/adivinhacao/random.py' since it has the same name as the standard library module named 'random' and prevents importing that standard library module)
Repare no testando o sorteio logo no começo: o import random rodou o arquivo dela, e não o módulo do Python. Quando um programa faz import random, o Python procura primeiro na pasta do programa, e só depois na sua própria biblioteca. O arquivo dela não tem nenhuma função randint, daí o AttributeError ("erro de atributo": o módulo random não tem o atributo randint). A mensagem até sugere a solução: "consider renaming…" = "considere renomear o seu random.py, que tem o mesmo nome do módulo random da biblioteca padrão e impede que ele seja importado". Como consertar: dê outro nome ao arquivo de teste (teste_sorteio.py). Nunca chame um arquivo seu de random.py, math.py, csv.py…
Missão (versão 1): com a semente 42, o número secreto é 82, e a entrada da missão é justamente 82. Mesmo assim, o programa diz "Errou!". Descubra por quê (dica: o que o input() devolve?) e conserte para aparecer Acertou!.
import random
random.seed(42) # só para a missão: o número secreto é sempre 82
secreto = random.randint(1, 100)
print("Pensei num número de 1 a 100.")
palpite = input("Seu palpite: ")
if palpite == secreto:
print("Acertou!")
else:
print(f"Errou! O número era {secreto}.")
import random
random.seed(42) # só para a missão: o número secreto é sempre 82
secreto = random.randint(1, 100)
print("Pensei num número de 1 a 100.")
palpite = int(input("Seu palpite: "))
if palpite == secreto:
print("Acertou!")
else:
print(f"Errou! O número era {secreto}.")
O input() devolveu o texto "82", e o texto "82" não é igual ao número 82: para o Python, são coisas de tipos diferentes, e o == entre elas dá False, sem erro nenhum. Esse é um dos enganos mais comuns de quem começa.
Versão 2 · Dicas até acertar
Agora o jogo fica de verdade: enquanto o palpite for diferente do número secreto, o programa dá uma dica e pede outro palpite. "Enquanto" é while.
import random
secreto = random.randint(1, 100)
print("Pensei num número de 1 a 100. Tente adivinhar!")
palpite = int(input("Seu palpite: "))
while palpite != secreto:
if palpite < secreto:
print("Mais alto!")
else:
print("Mais baixo!")
palpite = int(input("Seu palpite: "))
print(f"Acertou! O número era {secreto}.")
| Linha | O que faz |
|---|---|
palpite = int(input(…)) (antes do laço) | O primeiro palpite. Ele precisa existir antes do while, porque a condição do laço usa palpite. |
while palpite != secreto: | "Enquanto o palpite for diferente do secreto". O != é "diferente de". Se a pessoa acertar de primeira, o laço nem roda. |
if palpite < secreto: | Palpite menor que o secreto: a resposta está mais para cima. |
palpite = int(input(…)) (dentro do laço) | O próximo palpite. É ele que muda a condição; sem esta linha, o laço repetiria a mesma dica para sempre (veja o cenário abaixo). |
print(f"Acertou! …") | Fora do laço: só chega aqui quando palpite != secreto ficar falso, ou seja, quando acertar. |
$ python3 adivinhacao.py Pensei num número de 1 a 100. Tente adivinhar! Seu palpite: 50 Mais alto! Seu palpite: 75 Mais alto! Seu palpite: 88 Mais baixo! Seu palpite: 81 Mais baixo! Seu palpite: 78 Mais alto! Seu palpite: 79 Mais alto! Seu palpite: 80 Acertou! O número era 80.
Repare nos palpites: 50 (o meio de 1 a 100), depois 75 (o meio de 51 a 100), depois 88… A cada dica, ela chuta o meio do que sobrou, e a quantidade de números possíveis cai pela metade: 100, 50, 25, 12, 6, 3, 1. Com essa estratégia (em programação ela se chama busca binária), 7 palpites sempre bastam para 100 números, porque 2 elevado a 7 é 128, mais que 100. É por isso que a versão 3 vai dar 7 tentativas.
int(): TypeError
Sem o int() nos dois input(), o primeiro palpite já derruba o jogo:
$ python3 adivinhacao.py
Pensei num número de 1 a 100. Tente adivinhar!
Seu palpite: 50
Traceback (most recent call last):
File "/home/ana/projetos/adivinhacao/adivinhacao.py", line 8, in <module>
if palpite < secreto:
^^^^^^^^^^^^^^^^^
TypeError: '<' not supported between instances of 'str' and 'int'
TypeError: '<' not supported between instances of 'str' and 'int' = "erro de tipo: o < não funciona entre um texto (str) e um inteiro (int)". Na versão 1, a comparação == entre texto e número só dava False, calada; o < não aceita a mistura e para o programa. Pelo menos aqui o erro aparece. Repare que o while palpite != secreto da linha 7 passou sem erro (e deu verdadeiro, porque "50" é diferente de qualquer número): o problema só apareceu na linha 8. Como consertar: int(input(…)).
Se a última linha de dentro do while (o segundo palpite = int(input(…))) sumir, o palpite nunca muda. A condição palpite != secreto continua verdadeira para sempre, e o programa fica escrevendo "Mais alto!" sem parar, sem nunca mais perguntar nada. É um laço infinito. Para interromper, aperte Ctrl+C (o Python mostra um KeyboardInterrupt). Regra prática: dentro de um while, sempre tem de haver alguma linha que mude a condição.
Missão (versão 2): o programa dá a dica, mas só aceita um palpite. Troque o if por um while palpite != secreto: que dê a dica e peça outro palpite, e deixe o Acertou! para depois do laço. A entrada da missão é 50, 75, 88, 82 (o secreto é 82).
import random
random.seed(42) # só para a missão: o número secreto é sempre 82
secreto = random.randint(1, 100)
print("Pensei num número de 1 a 100. Tente adivinhar!")
palpite = int(input("Seu palpite: "))
if palpite == secreto:
print("Acertou!")
elif palpite < secreto:
print("Mais alto!")
else:
print("Mais baixo!")
import random
random.seed(42) # só para a missão: o número secreto é sempre 82
secreto = random.randint(1, 100)
print("Pensei num número de 1 a 100. Tente adivinhar!")
palpite = int(input("Seu palpite: "))
while palpite != secreto:
if palpite < secreto:
print("Mais alto!")
else:
print("Mais baixo!")
palpite = int(input("Seu palpite: "))
print(f"Acertou! O número era {secreto}.")
Versão 3 · Tentativas contadas e limitadas
Com tentativas infinitas, ninguém perde. A versão 3 dá 7 tentativas e mostra em qual a pessoa está. Quando já se sabe quantas vezes no máximo algo vai se repetir, o laço natural é o for com range().
import random
MAXIMO = 7
secreto = random.randint(1, 100)
print(f"Pensei num número de 1 a 100. Você tem {MAXIMO} tentativas.")
for tentativa in range(1, MAXIMO + 1):
palpite = int(input(f"Tentativa {tentativa}/{MAXIMO}: "))
if palpite == secreto:
print(f"Acertou em {tentativa} tentativa(s)!")
break
elif palpite < secreto:
print("Mais alto!")
else:
print("Mais baixo!")
else:
print(f"Suas tentativas acabaram. O número era {secreto}.")
- MAXIMO = 7
- O limite num lugar só, em MAIÚSCULAS (o costume para um valor fixo). Para mudar a dificuldade, basta mudar esta linha.
- for tentativa in range(1, MAXIMO + 1):
- A variável
tentativavale 1, 2, 3… até 7. Orange(1, 8)não inclui o 8: por isso o+ 1(veja range()). - f"Tentativa {tentativa}/{MAXIMO}: "
- A pergunta mostra o número da tentativa:
Tentativa 3/7:. - break
- Acertou: sai do
forna hora, sem gastar as tentativas que sobraram. - else: (alinhado com o for)
- O
elsede um laço roda só se o laço terminar sembreak, ou seja, se as 7 tentativas passaram sem acerto. É exatamente o "perdeu". Repare na indentação: ele está na mesma coluna dofor, e não doif. Mais em else nos Laços.
Uma vitória e uma derrota no terminal da Ana. Na segunda, ela tentou ir de 10 em 10:
$ python3 adivinhacao.py Pensei num número de 1 a 100. Você tem 7 tentativas. Tentativa 1/7: 50 Mais baixo! Tentativa 2/7: 25 Mais baixo! Tentativa 3/7: 12 Mais baixo! Tentativa 4/7: 6 Mais alto! Tentativa 5/7: 9 Mais alto! Tentativa 6/7: 10 Mais alto! Tentativa 7/7: 11 Acertou em 7 tentativa(s)! « por pouco $ python3 adivinhacao.py Pensei num número de 1 a 100. Você tem 7 tentativas. Tentativa 1/7: 10 Mais alto! Tentativa 2/7: 20 Mais alto! Tentativa 3/7: 30 Mais alto! Tentativa 4/7: 40 Mais alto! Tentativa 5/7: 50 Mais alto! Tentativa 6/7: 60 Mais alto! Tentativa 7/7: 70 Mais baixo! Suas tentativas acabaram. O número era 67. « o else do for
while ou for?
A versão 2 não sabia quantas voltas ia dar ("até acertar"): while. A versão 3 sabe o máximo ("no máximo 7"): for com range, e ainda ganha o contador tentativa de graça. Dá para fazer a versão 3 com while também, com um contador manual; compare em Formas diferentes.
ValueError
$ python3 adivinhacao.py
Pensei num número de 1 a 100. Você tem 7 tentativas.
Tentativa 1/7: sete
Traceback (most recent call last):
File "/home/ana/projetos/adivinhacao/adivinhacao.py", line 8, in <module>
palpite = int(input(f"Tentativa {tentativa}/{MAXIMO}: "))
ValueError: invalid literal for int() with base 10: 'sete'
A mensagem do int() é diferente da do float(): "invalid literal for int() with base 10: 'sete'" = "texto inválido para o int() na base 10: 'sete'". A base 10 é a nossa, de algarismos de 0 a 9. O jogo inteiro acabou por causa de um palpite digitado por extenso. A versão 4 conserta.
Missão (versão 3): quando as 7 tentativas acabam sem acerto, o programa termina calado. Acrescente o else do for (alinhado com o for, não com o if) mostrando Suas tentativas acabaram. O número era 82. (use {secreto}). A entrada da missão vai de 10 em 10, de 10 a 70, e o secreto é 82: ela perde.
import random
random.seed(42) # só para a missão: o número secreto é sempre 82
MAXIMO = 7
secreto = random.randint(1, 100)
print(f"Pensei num número de 1 a 100. Você tem {MAXIMO} tentativas.")
for tentativa in range(1, MAXIMO + 1):
palpite = int(input(f"Tentativa {tentativa}/{MAXIMO}: "))
if palpite == secreto:
print(f"Acertou em {tentativa} tentativa(s)!")
break
elif palpite < secreto:
print("Mais alto!")
else:
print("Mais baixo!")
import random
random.seed(42) # só para a missão: o número secreto é sempre 82
MAXIMO = 7
secreto = random.randint(1, 100)
print(f"Pensei num número de 1 a 100. Você tem {MAXIMO} tentativas.")
for tentativa in range(1, MAXIMO + 1):
palpite = int(input(f"Tentativa {tentativa}/{MAXIMO}: "))
if palpite == secreto:
print(f"Acertou em {tentativa} tentativa(s)!")
break
elif palpite < secreto:
print("Mais alto!")
else:
print("Mais baixo!")
else:
print(f"Suas tentativas acabaram. O número era {secreto}.")
Versão 4 · Palpite validado
A leitura do palpite vira uma função, ler_palpite, que só devolve um palpite quando ele é um inteiro e está entre 1 e 100. Palpite inválido não gasta tentativa: a função simplesmente pergunta de novo.
import random
MENOR = 1
MAIOR = 100
MAXIMO = 7
def ler_palpite(pergunta):
"""Pergunta até a pessoa digitar um inteiro entre MENOR e MAIOR."""
while True:
texto = input(pergunta).strip()
try:
palpite = int(texto)
except ValueError:
print(f'"{texto}" não é um número inteiro.')
continue
if MENOR <= palpite <= MAIOR:
return palpite
print(f"O número é de {MENOR} a {MAIOR}.")
secreto = random.randint(MENOR, MAIOR)
print(f"Pensei num número de {MENOR} a {MAIOR}. Você tem {MAXIMO} tentativas.")
for tentativa in range(1, MAXIMO + 1):
palpite = ler_palpite(f"Tentativa {tentativa}/{MAXIMO}: ")
if palpite == secreto:
print(f"Acertou em {tentativa} tentativa(s)!")
break
elif palpite < secreto:
print("Mais alto!")
else:
print("Mais baixo!")
else:
print(f"Suas tentativas acabaram. O número era {secreto}.")
- MENOR = 1 e MAIOR = 100
- Os limites do sorteio também viraram constantes: o
randint, a mensagem e a validação usam os mesmos valores. Para jogar de 1 a 1000, muda-se um lugar só. - try: palpite = int(texto)
- Tenta converter. Se der
ValueError, o Python pula para oexcept. - continue
- "Continuar": volta direto para o começo do
while, pulando o resto da volta. Sem ele, o programa seguiria para oifcom uma variávelpalpiteque não foi criada (veja break e continue). - if MENOR <= palpite <= MAIOR:
- Uma comparação "encadeada":
1 <= palpite <= 100quer dizer "palpite maior ou igual a 1 e menor ou igual a 100", como na matemática. Poucas linguagens deixam escrever assim. - return palpite
- Palpite bom: devolve e sai da função (e do
while True). - print(f"O número é de …")
- Só chega aqui um inteiro fora da faixa. Depois do aviso, o
while Truepergunta de novo.
$ python3 adivinhacao.py Pensei num número de 1 a 100. Você tem 7 tentativas. Tentativa 1/7: abc "abc" não é um número inteiro. Tentativa 1/7: 150 O número é de 1 a 100. Tentativa 1/7: 7.5 "7.5" não é um número inteiro. « int() não aceita casas decimais Tentativa 1/7: 50 Mais alto! Tentativa 2/7: 75 Mais baixo! Tentativa 3/7: 62 Mais baixo! Tentativa 4/7: 56 Mais baixo! Tentativa 5/7: 53 Mais alto! Tentativa 6/7: 54 Acertou em 6 tentativa(s)!
Os três palpites inválidos ficaram todos na "Tentativa 1/7": nenhum foi contado. O for só avança quando ler_palpite devolve um palpite válido.
Missão (versão 4): a função ler_palpite ainda aceita qualquer coisa, e o abc da entrada da missão (abc, 150, 82) derruba o jogo. Escreva o corpo da função como na versão 4: while True, try/except ValueError com continue, e o teste MENOR <= palpite <= MAIOR. O resultado deve ser Acertou em 1 tentativa(s)!, porque os dois palpites inválidos não contam.
import random
random.seed(42) # só para a missão: o número secreto é sempre 82
MENOR = 1
MAIOR = 100
MAXIMO = 7
def ler_palpite(pergunta):
"""Pergunta até a pessoa digitar um inteiro entre MENOR e MAIOR."""
return int(input(pergunta))
secreto = random.randint(MENOR, MAIOR)
print(f"Pensei num número de {MENOR} a {MAIOR}. Você tem {MAXIMO} tentativas.")
for tentativa in range(1, MAXIMO + 1):
palpite = ler_palpite(f"Tentativa {tentativa}/{MAXIMO}: ")
if palpite == secreto:
print(f"Acertou em {tentativa} tentativa(s)!")
break
elif palpite < secreto:
print("Mais alto!")
else:
print("Mais baixo!")
else:
print(f"Suas tentativas acabaram. O número era {secreto}.")
import random
random.seed(42) # só para a missão: o número secreto é sempre 82
MENOR = 1
MAIOR = 100
MAXIMO = 7
def ler_palpite(pergunta):
"""Pergunta até a pessoa digitar um inteiro entre MENOR e MAIOR."""
while True:
texto = input(pergunta).strip()
try:
palpite = int(texto)
except ValueError:
print(f'"{texto}" não é um número inteiro.')
continue
if MENOR <= palpite <= MAIOR:
return palpite
print(f"O número é de {MENOR} a {MAIOR}.")
secreto = random.randint(MENOR, MAIOR)
print(f"Pensei num número de {MENOR} a {MAIOR}. Você tem {MAXIMO} tentativas.")
for tentativa in range(1, MAXIMO + 1):
palpite = ler_palpite(f"Tentativa {tentativa}/{MAXIMO}: ")
if palpite == secreto:
print(f"Acertou em {tentativa} tentativa(s)!")
break
elif palpite < secreto:
print("Mais alto!")
else:
print("Mais baixo!")
else:
print(f"Suas tentativas acabaram. O número era {secreto}.")
Versão 5 · Várias partidas e recorde
Para jogar de novo sem rodar o programa outra vez, a partida inteira vira uma função, jogar(), e o programa principal chama essa função dentro de um while True. A função devolve o resultado da partida: quantas tentativas a pessoa usou, ou None se ela perdeu. Com isso, o programa principal guarda o recorde: o menor número de tentativas numa vitória.
import random
MENOR = 1
MAIOR = 100
MAXIMO = 7
def ler_palpite(pergunta):
"""Pergunta até a pessoa digitar um inteiro entre MENOR e MAIOR."""
while True:
texto = input(pergunta).strip()
try:
palpite = int(texto)
except ValueError:
print(f'"{texto}" não é um número inteiro.')
continue
if MENOR <= palpite <= MAIOR:
return palpite
print(f"O número é de {MENOR} a {MAIOR}.")
def jogar():
"""Uma partida. Devolve quantas tentativas a pessoa usou, ou None se ela perdeu."""
secreto = random.randint(MENOR, MAIOR)
print(f"Pensei num número de {MENOR} a {MAIOR}. Você tem {MAXIMO} tentativas.")
for tentativa in range(1, MAXIMO + 1):
palpite = ler_palpite(f"Tentativa {tentativa}/{MAXIMO}: ")
if palpite == secreto:
print(f"Acertou em {tentativa} tentativa(s)!")
return tentativa
if palpite < secreto:
print("Mais alto!")
else:
print("Mais baixo!")
print(f"Suas tentativas acabaram. O número era {secreto}.")
return None
print("=== Jogo de Adivinhação ===")
recorde = None
while True:
resultado = jogar()
if resultado is not None and (recorde is None or resultado < recorde):
recorde = resultado
print("Novo recorde!")
if recorde is not None:
print(f"Seu recorde: {recorde} tentativa(s).")
if input("Jogar de novo? (s/n): ").strip().lower() != "s":
break
print("Até a próxima!")
| Peça | O que mudou |
|---|---|
def jogar(): | O que era o programa da versão 4 (sorteio, mensagem e for) foi para dentro da função. A cada chamada, um sorteio novo. |
return tentativa | No lugar do break: o return sai do for e da função de uma vez, levando o número de tentativas. |
print(…acabaram…) e return None | No lugar do else do for: se o laço terminou, é porque ninguém deu return lá dentro, ou seja, perdeu. O return None deixa isso explícito (uma função sem return já devolveria None, mas escrito fica mais claro). |
recorde = None | Antes da primeira partida, ainda não há recorde: None é o "nada ainda" (veja O Valor None). |
resultado is not None and (recorde is None or resultado < recorde) | "Ganhou, e (é o primeiro recorde ou é melhor que o antigo)". Os parênteses importam: sem eles, o and seria feito antes do or (veja Precedência). |
if input(…).strip().lower() != "s": | Pergunta e decide na mesma linha, sem guardar a resposta numa variável, porque ela só é usada ali. |
$ python3 adivinhacao.py === Jogo de Adivinhação === Pensei num número de 1 a 100. Você tem 7 tentativas. Tentativa 1/7: 50 Mais alto! Tentativa 2/7: 75 Mais baixo! Tentativa 3/7: 62 Mais alto! Tentativa 4/7: 68 Mais baixo! Tentativa 5/7: 65 Mais baixo! Tentativa 6/7: 63 Acertou em 6 tentativa(s)! Novo recorde! Seu recorde: 6 tentativa(s). Jogar de novo? (s/n): s Pensei num número de 1 a 100. Você tem 7 tentativas. Tentativa 1/7: 50 Mais baixo! Tentativa 2/7: 25 Mais baixo! Tentativa 3/7: 12 Mais baixo! Tentativa 4/7: 6 Mais alto! Tentativa 5/7: 9 Mais baixo! Tentativa 6/7: 7 Mais alto! Tentativa 7/7: 8 Acertou em 7 tentativa(s)! Seu recorde: 6 tentativa(s). Jogar de novo? (s/n): n Até a próxima!
Na primeira partida, 6 tentativas: como ainda não havia recorde, recorde is None deu verdadeiro, e veio o "Novo recorde!". Na segunda, 7 tentativas: 7 < 6 é falso, e o recorde continuou 6.
Missão (versão 5): o jogo já repete as partidas, mas nunca atualiza o recorde. No lugar do comentário, escreva o if que guarda o resultado em recorde (e mostra Novo recorde!) quando a pessoa ganhou e o resultado é o primeiro ou é menor que o recorde. Com a semente 42, a primeira partida tem o secreto 82 (a entrada acerta em 4) e a segunda tem o 15 (a entrada acerta em 1): devem aparecer Seu recorde: 4 tentativa(s). e depois Seu recorde: 1 tentativa(s).
import random
random.seed(42) # só para a missão: os secretos são 82 e depois 15
MENOR = 1
MAIOR = 100
MAXIMO = 7
def ler_palpite(pergunta):
"""Pergunta até a pessoa digitar um inteiro entre MENOR e MAIOR."""
while True:
texto = input(pergunta).strip()
try:
palpite = int(texto)
except ValueError:
print(f'"{texto}" não é um número inteiro.')
continue
if MENOR <= palpite <= MAIOR:
return palpite
print(f"O número é de {MENOR} a {MAIOR}.")
def jogar():
"""Uma partida. Devolve quantas tentativas a pessoa usou, ou None se ela perdeu."""
secreto = random.randint(MENOR, MAIOR)
print(f"Pensei num número de {MENOR} a {MAIOR}. Você tem {MAXIMO} tentativas.")
for tentativa in range(1, MAXIMO + 1):
palpite = ler_palpite(f"Tentativa {tentativa}/{MAXIMO}: ")
if palpite == secreto:
print(f"Acertou em {tentativa} tentativa(s)!")
return tentativa
if palpite < secreto:
print("Mais alto!")
else:
print("Mais baixo!")
print(f"Suas tentativas acabaram. O número era {secreto}.")
return None
print("=== Jogo de Adivinhação ===")
recorde = None
while True:
resultado = jogar()
# atualize o recorde aqui
if recorde is not None:
print(f"Seu recorde: {recorde} tentativa(s).")
if input("Jogar de novo? (s/n): ").strip().lower() != "s":
break
print("Até a próxima!")
import random
random.seed(42) # só para a missão: os secretos são 82 e depois 15
MENOR = 1
MAIOR = 100
MAXIMO = 7
def ler_palpite(pergunta):
"""Pergunta até a pessoa digitar um inteiro entre MENOR e MAIOR."""
while True:
texto = input(pergunta).strip()
try:
palpite = int(texto)
except ValueError:
print(f'"{texto}" não é um número inteiro.')
continue
if MENOR <= palpite <= MAIOR:
return palpite
print(f"O número é de {MENOR} a {MAIOR}.")
def jogar():
"""Uma partida. Devolve quantas tentativas a pessoa usou, ou None se ela perdeu."""
secreto = random.randint(MENOR, MAIOR)
print(f"Pensei num número de {MENOR} a {MAIOR}. Você tem {MAXIMO} tentativas.")
for tentativa in range(1, MAXIMO + 1):
palpite = ler_palpite(f"Tentativa {tentativa}/{MAXIMO}: ")
if palpite == secreto:
print(f"Acertou em {tentativa} tentativa(s)!")
return tentativa
if palpite < secreto:
print("Mais alto!")
else:
print("Mais baixo!")
print(f"Suas tentativas acabaram. O número era {secreto}.")
return None
print("=== Jogo de Adivinhação ===")
recorde = None
while True:
resultado = jogar()
if resultado is not None and (recorde is None or resultado < recorde):
recorde = resultado
print("Novo recorde!")
if recorde is not None:
print(f"Seu recorde: {recorde} tentativa(s).")
if input("Jogar de novo? (s/n): ").strip().lower() != "s":
break
print("Até a próxima!")
Formas diferentes de fazer
Contar as tentativas: for ou while
A versão 3 usou for com break e else. O mesmo jogo com while precisa de um contador feito à mão (abaixo, só o trecho do laço):
tentativa = 1
acertou = False
while tentativa <= MAXIMO and not acertou:
palpite = int(input(f"Tentativa {tentativa}/{MAXIMO}: "))
if palpite == secreto:
acertou = True
# … as dicas …
tentativa += 1
Funciona, mas há mais coisas para lembrar: criar o contador, somar 1 no fim de cada volta (esquecer o tentativa += 1 dá um laço infinito) e criar uma variável acertou só para sair. O for faz a contagem sozinho.
Sortear o número
$ python3 Python 3.14.4 (main, Aug 20 2026, 10:41:58) [GCC 15.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import random >>> random.seed(42) >>> random.randint(1, 100) 82 >>> random.seed(42) >>> random.randrange(1, 101) 82 >>> exit()
O randrange(1, 101) funciona como o range: o fim (101) fica de fora. Com a mesma semente, ele dá o mesmo 82 que o randint(1, 100), porque, por dentro, o randint(a, b) chama o randrange(a, b + 1).
| Forma | Quando usar |
|---|---|
for tentativa in range(1, MAXIMO + 1) com break/else | Número máximo de voltas conhecido. O contador vem pronto. |
while com contador | Quando a condição de parar é mais complicada que "no máximo N vezes". Cuidado com o contador. |
while palpite != secreto | Repetir até acontecer algo, sem limite (versão 2). |
random.randint(1, 100) | Sortear um inteiro com os dois extremos incluídos. O mais fácil de ler. |
random.randrange(1, 101) | Mesma coisa, no estilo do range (o fim fica de fora). Aceita um passo: randrange(0, 101, 10) sorteia 0, 10, 20… |
Ideias para continuar
- Níveis de dificuldade: antes de começar, pergunte "fácil, médio ou difícil" e mude
MAIOReMAXIMO(1 a 10 com 4 tentativas, 1 a 100 com 7, 1 a 1000 com 10). - Avise quando a pessoa repetir um palpite que já deu (guarde os palpites numa lista).
- Dica de "quente" e "frio": se a diferença entre o palpite e o secreto for menor que 5, diga "Está quente!" (use
abs(), veja Funções Embutidas).
Referência rápida do projeto
| Escrita | Para que serviu |
|---|---|
import random | Trazer o módulo do sorteio |
random.randint(1, 100) | Sortear um inteiro de 1 a 100 (os dois incluídos) |
random.seed(42) | Fixar a semente: o sorteio passa a dar sempre a mesma sequência (para testar) |
while palpite != secreto: | Repetir até acertar |
for tentativa in range(1, MAXIMO + 1): | Repetir no máximo MAXIMO vezes, contando |
break / else: do laço | Sair ao acertar / fazer algo só se o laço terminou sem break |
continue | Voltar ao começo do laço (palpite inválido) |
MENOR <= palpite <= MAIOR | Conferir se está na faixa |
return tentativa / return None | A partida devolve o resultado |
| Sintoma | Causa provável |
|---|---|
| Digitou o número certo e o jogo disse "Errou!" | Faltou o int(): o texto "82" não é igual ao número 82 |
TypeError: '<' not supported between instances of 'str' and 'int' | Faltou o int() e o programa comparou texto com número |
NameError: name 'random' is not defined. Did you forget to import 'random'? | Faltou o import random |
AttributeError: module 'random' has no attribute 'randint' (consider renaming …) | Há um arquivo seu chamado random.py na pasta |
ValueError: invalid literal for int() with base 10: 'sete' | Palpite que não é inteiro, sem try/except |
| A mesma dica aparece sem parar | Laço infinito: faltou pedir o novo palpite dentro do while |
| As tentativas acabam e nada aparece | Faltou o else do for (ou ele está alinhado com o if) |
Exercícios
1. O sorteio
Complete para sortear um número de 1 a 6, como um dado:
2. O range das tentativas
Complete para a variável tentativa valer 1, 2, 3, 4 e 5:
3. Pular o resto da volta
Complete a palavra que volta para o começo do laço depois de um palpite inválido:
print("Não é um número.")
4. Quando roda o else que está alinhado com o for?
5. Para que servem as missões começarem com random.seed(42)?
6. A Ana salvou um teste como random.py na pasta do jogo, e o jogo passou a dar AttributeError. Por quê?
Resumo
import randomerandom.randint(1, 100)sorteiam um inteiro de 1 a 100, com os dois extremos.random.seed(42)fixa a semente: a sequência sorteada passa a ser sempre a mesma. Ótimo para testar; no jogo de verdade, sem semente.- O texto
"82"não é igual ao número82: converta o palpite comint(). whilerepete "até acontecer";forcomrangerepete "no máximo N vezes" e já conta as voltas.- O
elsede um laço roda só quando o laço termina sembreak: é o "perdeu" do jogo. try/exceptcomcontinuepede de novo sem gastar tentativa;MENOR <= x <= MAIORconfere a faixa.- Uma função que devolve o resultado (
return tentativaouNone) deixa o programa principal cuidar do recorde. - Nunca dê a um arquivo seu o nome de um módulo do Python (
random.py).