Projeto Jogo de Adivinhação
O computador pensa num número de 1 a 100 e você tenta adivinhar. A cada palpite, ele diz "é maior" ou "é menor". É o projeto clássico de quem está aprendendo a programar, porque junta quase tudo do Nível 1 num programa curto e divertido: decisões, laços, contadores, números aleatórios e funções.
- Comparar o palpite com o número secreto com if e else if.
- Repetir até acertar com while e contar as tentativas com ++.
- Sortear números com
randesrand(Números Aleatórios). - Limitar as tentativas com for e uma constante
#define(Constantes). - Separar uma partida numa função que devolve um valor.
- Testar um programa que sorteia números (sem depender da sorte).
O que vamos construir
Este é o jogo pronto, na máquina da Ana. Ela jogou três partidas: na primeira e na terceira, foi esperta e sempre chutou o meio do intervalo que sobrava; na segunda, chutou de 10 em 10 e perdeu.
$ ./adivinhacao === Jogo de Adivinhação === Pensei num número de 1 a 100. Você tem 7 tentativas. Tentativa 1: 50 É maior. Tentativa 2: 75 É maior. Tentativa 3: 88 É menor. Tentativa 4: 81 É maior. Tentativa 5: 84 É maior. Tentativa 6: 86 Acertou em 6 tentativa(s)! Novo recorde: 6 tentativa(s)! Jogar de novo? (s/n): s Pensei num número de 1 a 100. Você tem 7 tentativas. Tentativa 1: 90 É menor. Tentativa 2: 80 É menor. Tentativa 3: 70 É menor. Tentativa 4: 60 É menor. Tentativa 5: 55 É menor. Tentativa 6: 52 É menor. Tentativa 7: 51 É menor. Suas tentativas acabaram. O número era 1. « perdeu: o número era o menor possível Jogar de novo? (s/n): s Pensei num número de 1 a 100. Você tem 7 tentativas. Tentativa 1: 50 É maior. Tentativa 2: 75 É menor. Tentativa 3: 62 É menor. Tentativa 4: 56 Acertou em 4 tentativa(s)! Novo recorde: 4 tentativa(s)! Jogar de novo? (s/n): n Seu recorde: 4 tentativa(s). Até a próxima!
Se você rodar, os números serão outros: a cada execução o jogo sorteia um número novo. Vamos chegar lá em quatro versões:
- Um palpite contra um número fixo (
scanf,if/else if). - Repetir até acertar e contar as tentativas (
while,++). - Sortear o número (
rand,srand,time). - Limite, recorde e jogar de novo (
#define,for, uma função).
Antes de começar
Você precisa saber compilar e rodar um programa (Compilar com gcc), ler um inteiro com scanf e conhecer if e else. A pasta do projeto e o arquivo adivinhacao.c (sem acento e sem ç: nomes de arquivo com acento dão trabalho no terminal):
$ mkdir -p c/adivinhacao $ cd c/adivinhacao
Versão 1 · Um palpite contra um número fixo
Antes de sortear, vamos fazer o jogo funcionar com um número fixo: 42. Assim dá para testar sabendo a resposta. A pessoa dá um palpite e o programa diz se acertou ou para que lado errou.
#include <stdio.h>
int main(void) {
int secreto = 42; // por enquanto, o número é sempre o mesmo
int palpite = 0;
printf("=== Jogo de Adivinhação ===\n");
printf("Pensei num número de 1 a 100.\n");
printf("Seu palpite: ");
scanf("%d", &palpite);
if (palpite == secreto) {
printf("Acertou!\n");
} else if (palpite < secreto) {
printf("Errou. O número é maior.\n");
} else {
printf("Errou. O número é menor.\n");
}
return 0;
}
| Linha | O que faz |
|---|---|
int secreto = 42; | O número que a pessoa tem de adivinhar. Na versão 3, ele vai ser sorteado. |
scanf("%d", &palpite); | Lê um inteiro (%d) e guarda em palpite. O & entrega o endereço da variável (veja Entrada com scanf). |
if (palpite == secreto) | Dois sinais de igual: compara. Um só (=) guardaria 42 no palpite (veja o cenário abaixo). |
else if (palpite < secreto) | Se não acertou e o palpite é menor, o número secreto é maior. |
else | Sobrou um caso só: o palpite é maior, então o número é menor. |
$ gcc -std=c23 -Wall -Wextra adivinhacao.c -o adivinhacao $ ./adivinhacao === Jogo de Adivinhação === Pensei num número de 1 a 100. Seu palpite: 30 Errou. O número é maior. $ ./adivinhacao === Jogo de Adivinhação === Pensei num número de 1 a 100. Seu palpite: 70 Errou. O número é menor. $ ./adivinhacao === Jogo de Adivinhação === Pensei num número de 1 a 100. Seu palpite: 42 Acertou!
= só no if: todo palpite "acerta"
Este código tem um erro de propósito: if (palpite = secreto).
$ gcc -std=c23 -Wall -Wextra adivinhacao.c -o adivinhacao
adivinhacao.c: In function ‘main’:
adivinhacao.c:12:9: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
12 | if (palpite = secreto) {
| ^~~~~~~
$ ./adivinhacao
=== Jogo de Adivinhação ===
Pensei num número de 1 a 100.
Seu palpite: 30
Acertou!
O que significa: "sugiro parênteses em volta de uma atribuição usada como valor verdade". palpite = secreto guarda 42 em palpite, e o resultado da expressão é 42, que não é zero, ou seja, verdadeiro. Por isso o palpite 30 "acertou". O -Wall desconfiou e avisou.
Como consertar: para comparar, use ==. Veja Operadores de Comparação.
Missão (versão 1): o jogo só sabe dizer "Acertou!". Acrescente um else if que mostra Errou. O número é maior. quando o palpite é menor que o secreto, e um else que mostra Errou. O número é menor.. A entrada da missão é o palpite 30.
#include <stdio.h>
int main(void) {
int secreto = 42; // por enquanto, o número é sempre o mesmo
int palpite = 0;
printf("=== Jogo de Adivinhação ===\n");
printf("Pensei num número de 1 a 100.\n");
printf("Seu palpite: ");
scanf("%d", &palpite);
if (palpite == secreto) {
printf("Acertou!\n");
}
// e se errou? diga se o número é maior ou menor
return 0;
}
#include <stdio.h>
int main(void) {
int secreto = 42; // por enquanto, o número é sempre o mesmo
int palpite = 0;
printf("=== Jogo de Adivinhação ===\n");
printf("Pensei num número de 1 a 100.\n");
printf("Seu palpite: ");
scanf("%d", &palpite);
if (palpite == secreto) {
printf("Acertou!\n");
} else if (palpite < secreto) {
printf("Errou. O número é maior.\n");
} else {
printf("Errou. O número é menor.\n");
}
return 0;
}
Versão 2 · Repetir até acertar e contar as tentativas
Um palpite só é pouco. A versão 2 repete a pergunta enquanto o palpite for diferente do secreto: isso é um while. E conta quantos palpites a pessoa deu, com uma variável que começa em 0 e ganha 1 a cada volta (tentativas++, veja ++ e --).
#include <stdio.h>
int main(void) {
int secreto = 42; // por enquanto, o número é sempre o mesmo
int palpite = 0;
int tentativas = 0;
printf("=== Jogo de Adivinhação ===\n");
printf("Pensei num número de 1 a 100.\n");
while (palpite != secreto) {
printf("Seu palpite: ");
if (scanf("%d", &palpite) != 1) {
printf("\nFim de jogo: não consegui ler um número.\n");
return 1;
}
tentativas++;
if (palpite < secreto) {
printf("É maior.\n");
} else if (palpite > secreto) {
printf("É menor.\n");
}
}
printf("Acertou em %d tentativas!\n", tentativas);
return 0;
}
- int tentativas = 0;
- O contador. Começa em zero, porque ainda ninguém chutou nada.
- while (palpite != secreto)
- "Enquanto o palpite for diferente do secreto, repita."
palpitecomeça em 0, que nunca é o secreto (de 1 a 100), então o laço sempre entra na primeira vez. - if (scanf("%d", &palpite) != 1)
- O
scanfdevolve quantos valores leu. Se a pessoa digitou texto ou a entrada acabou, ele devolve 0 ouEOF, e o jogo para em vez de rodar para sempre (veja o cenário abaixo). - tentativas++;
- Mais um palpite contado.
- else if (palpite > secreto)
- Agora são três casos: menor, maior ou igual. Quando é igual, nenhum dos dois
ifmostra nada, o laço testa a condição, vê que acertou e sai. - printf("Acertou em %d tentativas!\n", tentativas);
- Fora do laço: só chega aqui quem acertou.
$ gcc -std=c23 -Wall -Wextra adivinhacao.c -o adivinhacao $ ./adivinhacao === Jogo de Adivinhação === Pensei num número de 1 a 100. Seu palpite: 50 É menor. Seu palpite: 25 É maior. Seu palpite: 37 É maior. Seu palpite: 43 É menor. Seu palpite: 40 É maior. Seu palpite: 42 Acertou em 6 tentativas!
scanf: um texto trava o jogo num laço infinito
Este código tem um erro de propósito: scanf("%d", &palpite); sem o if em volta.
$ gcc -std=c23 -Wall -Wextra adivinhacao.c -o adivinhacao $ printf 'abc\n' | timeout 3 ./adivinhacao | head -n 6 === Jogo de Adivinhação === Pensei num número de 1 a 100. Seu palpite: É maior. Seu palpite: É maior. Seu palpite: É maior. Seu palpite: É maior.
O comando "digita" abc para o jogo (printf … |), corta o programa depois de 3 segundos (timeout 3) e mostra só as 6 primeiras linhas (head -n 6); sem isso, a tela encheria sem parar.
O que aconteceu: o %d não consegue ler abc, desiste e deixa o abc na entrada. O palpite continua 0, o laço repete, o scanf tenta de novo, esbarra no mesmo abc… para sempre. No seu terminal, aperte Ctrl+C para parar.
Como consertar: confira o retorno: if (scanf("%d", &palpite) != 1), como na versão 2. Para pedir de novo em vez de encerrar, veja a versão 4 do projeto Calculadora e Validar a Entrada.
Missão (versão 2): o jogo pergunta uma vez só. Coloque o trecho que pergunta, lê, conta e compara dentro de um while (palpite != secreto) { … }. A entrada da missão é 50, 25, 37, 43, 42: o jogo deve terminar com Acertou em 5 tentativas!.
#include <stdio.h>
int main(void) {
int secreto = 42; // por enquanto, o número é sempre o mesmo
int palpite = 0;
int tentativas = 0;
printf("=== Jogo de Adivinhação ===\n");
printf("Pensei num número de 1 a 100.\n");
// repita este bloco enquanto palpite != secreto
printf("Seu palpite: ");
if (scanf("%d", &palpite) != 1) {
printf("\nFim de jogo: não consegui ler um número.\n");
return 1;
}
tentativas++;
if (palpite < secreto) {
printf("É maior.\n");
} else if (palpite > secreto) {
printf("É menor.\n");
}
printf("Acertou em %d tentativas!\n", tentativas);
return 0;
}
#include <stdio.h>
int main(void) {
int secreto = 42; // por enquanto, o número é sempre o mesmo
int palpite = 0;
int tentativas = 0;
printf("=== Jogo de Adivinhação ===\n");
printf("Pensei num número de 1 a 100.\n");
while (palpite != secreto) {
printf("Seu palpite: ");
if (scanf("%d", &palpite) != 1) {
printf("\nFim de jogo: não consegui ler um número.\n");
return 1;
}
tentativas++;
if (palpite < secreto) {
printf("É maior.\n");
} else if (palpite > secreto) {
printf("É menor.\n");
}
}
printf("Acertou em %d tentativas!\n", tentativas);
return 0;
}
Versão 3 · Sortear o número
Com o 42 fixo, o jogo perde a graça na segunda partida. Hora de deixar o computador escolher. A função rand() ("random", aleatório), do <stdlib.h>, devolve um inteiro entre 0 e RAND_MAX (no Linux, 2147483647). Para transformar isso num número de 1 a 100, usamos o resto da divisão (veja Números Aleatórios):
| Expressão | Resultado | Por quê |
|---|---|---|
rand() | de 0 a 2147483647 | Um número grande qualquer. |
rand() % 100 | de 0 a 99 | O resto da divisão por 100 sempre fica entre 0 e 99. |
rand() % 100 + 1 | de 1 a 100 | Soma 1 nos dois extremos. |
Mas tem uma pegadinha. Veja este programa, que sorteia cinco números, rodando três vezes:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
for (int i = 0; i < 5; i++) {
printf("%d ", rand() % 100 + 1);
}
printf("\n");
return 0;
}
$ gcc -std=c23 -Wall -Wextra sorteio.c -o sorteio $ ./sorteio 84 87 78 16 94 $ ./sorteio 84 87 78 16 94 $ ./sorteio 84 87 78 16 94
Os mesmos cinco números, toda vez! O rand() não é sorte de verdade: é uma conta que, a partir de um número inicial (a semente), gera uma sequência que parece aleatória. Mesma semente, mesma sequência. Sem você dizer nada, a semente é sempre 1.
A solução é trocar a semente a cada execução com srand ("seed random", semear o aleatório). E o que muda a cada execução? O relógio: time(NULL), do <time.h>, devolve quantos segundos se passaram desde 1º de janeiro de 1970.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
srand(time(NULL)); // embaralha: uma sequência nova a cada execução
int secreto = rand() % 100 + 1; // um número de 1 a 100
int palpite = 0;
int tentativas = 0;
printf("=== Jogo de Adivinhação ===\n");
printf("Pensei num número de 1 a 100.\n");
while (palpite != secreto) {
printf("Seu palpite: ");
if (scanf("%d", &palpite) != 1) {
printf("\nFim de jogo: não consegui ler um número.\n");
return 1;
}
tentativas++;
if (palpite < secreto) {
printf("É maior.\n");
} else if (palpite > secreto) {
printf("É menor.\n");
}
}
printf("Acertou em %d tentativas!\n", tentativas);
return 0;
}
- #include <stdlib.h> e <time.h>
stdlib.htrazrandesrand;time.htraztime.- srand(time(NULL));
- Usa a hora atual como semente. Chame uma vez só, no começo do programa.
- int secreto = rand() % 100 + 1;
- Sorteia o número de 1 a 100. O resto do jogo não mudou nada.
Para ganhar sempre em poucas tentativas, a Ana usa uma estratégia: chutar o meio do intervalo que ainda é possível. Começa em 50; se "é menor", o número está entre 1 e 49, e ela chuta 25; e assim por diante. A cada palpite, o intervalo cai pela metade:
$ gcc -std=c23 -Wall -Wextra adivinhacao.c -o adivinhacao $ ./adivinhacao === Jogo de Adivinhação === Pensei num número de 1 a 100. Seu palpite: 50 É menor. Seu palpite: 25 É menor. Seu palpite: 12 É maior. Seu palpite: 18 É maior. Seu palpite: 21 É maior. Seu palpite: 23 Acertou em 6 tentativas! $ ./adivinhacao === Jogo de Adivinhação === Pensei num número de 1 a 100. Seu palpite: 50 É menor. Seu palpite: 25 É menor. Seu palpite: 12 É menor. Seu palpite: 6 É maior. Seu palpite: 9 É maior. Seu palpite: 10 Acertou em 6 tentativas!
O rand() é uma conta, e cada biblioteca C usa a sua. O gcc do Linux usa a da glibc; o editor do guia usa a da wasi-libc (baseada na musl). Por isso o sorteio.c mostra 84 87 78 16 94 no terminal da Ana e outra sequência no editor. Nos dois, a sequência se repete enquanto a semente for a mesma. Moral: nunca escreva um programa que depende de quais números o rand() vai dar.
Se o número muda a cada execução, como conferir que o jogo funciona? Dois truques que os programadores usam de verdade:
- Fixar o número durante o teste, como fizemos nas versões 1 e 2. Depois, troca-se pelo sorteio.
- Escolher palpites que funcionam para qualquer número. Se a entrada for 1, 2, 3, …, 100, o jogo tem de acertar em algum momento, seja qual for o número. É o que a missão abaixo faz.
Missão (versão 3): troque o 42 fixo por um número sorteado de 1 a 100 (rand() % 100 + 1) e chame srand(time(NULL)); uma vez, no começo do main. Não esqueça os dois #include. A entrada da missão chuta 1, 2, 3… até 100, então o jogo acerta seja qual for o número sorteado. Rode duas ou três vezes e veja o número de tentativas mudar.
#include <stdio.h>
int main(void) {
int secreto = 42; // por enquanto, o número é sempre o mesmo
int palpite = 0;
int tentativas = 0;
printf("=== Jogo de Adivinhação ===\n");
printf("Pensei num número de 1 a 100.\n");
while (palpite != secreto) {
printf("Seu palpite: ");
if (scanf("%d", &palpite) != 1) {
printf("\nFim de jogo: não consegui ler um número.\n");
return 1;
}
tentativas++;
if (palpite < secreto) {
printf("É maior.\n");
} else if (palpite > secreto) {
printf("É menor.\n");
}
}
printf("Acertou em %d tentativas!\n", tentativas);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
srand(time(NULL)); // embaralha: uma sequência nova a cada execução
int secreto = rand() % 100 + 1; // um número de 1 a 100
int palpite = 0;
int tentativas = 0;
printf("=== Jogo de Adivinhação ===\n");
printf("Pensei num número de 1 a 100.\n");
while (palpite != secreto) {
printf("Seu palpite: ");
if (scanf("%d", &palpite) != 1) {
printf("\nFim de jogo: não consegui ler um número.\n");
return 1;
}
tentativas++;
if (palpite < secreto) {
printf("É maior.\n");
} else if (palpite > secreto) {
printf("É menor.\n");
}
}
printf("Acertou em %d tentativas!\n", tentativas);
return 0;
}
Versão 4 · Limite, recorde e jogar de novo
Com a estratégia do meio, dá para achar qualquer número de 1 a 100 em no máximo 7 palpites: a cada palpite errado, sobra no máximo a metade dos números (100 → 50 → 25 → 12 → 6 → 3 → 1); depois de 6 erros sobra um número só, e o 7º palpite acerta. Então a versão final dá 7 tentativas: quem chuta à toa perde. E mais duas coisas: jogar de novo sem rodar o programa outra vez, e guardar o recorde (a partida com menos tentativas).
O código de uma partida foi para uma função, jogar. Ela recebe o número secreto e devolve quantas tentativas a pessoa usou, ou 0 se perdeu. O main só cuida do que acontece entre as partidas.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_TENTATIVAS 7
// Joga uma partida. Devolve quantas tentativas a pessoa usou,
// ou 0 se ela não acertou dentro do limite.
int jogar(int secreto) {
printf("\nPensei num número de 1 a 100. Você tem %d tentativas.\n", MAX_TENTATIVAS);
for (int tentativa = 1; tentativa <= MAX_TENTATIVAS; tentativa++) {
int palpite = 0;
printf("Tentativa %d: ", tentativa);
if (scanf("%d", &palpite) != 1) {
printf("\nFim de jogo: não consegui ler um número.\n");
exit(1);
}
if (palpite == secreto) {
printf("Acertou em %d tentativa(s)!\n", tentativa);
return tentativa;
} else if (palpite < secreto) {
printf("É maior.\n");
} else {
printf("É menor.\n");
}
}
printf("Suas tentativas acabaram. O número era %d.\n", secreto);
return 0;
}
int main(void) {
srand(time(NULL));
int recorde = 0; // 0 = ainda não há recorde
char resposta = 's';
printf("=== Jogo de Adivinhação ===\n");
while (resposta == 's' || resposta == 'S') {
int secreto = rand() % 100 + 1;
int usadas = jogar(secreto);
if (usadas > 0 && (recorde == 0 || usadas < recorde)) {
recorde = usadas;
printf("Novo recorde: %d tentativa(s)!\n", recorde);
}
printf("Jogar de novo? (s/n): ");
if (scanf(" %c", &resposta) != 1) {
resposta = 'n';
}
}
if (recorde > 0) {
printf("Seu recorde: %d tentativa(s).\n", recorde);
}
printf("Até a próxima!\n");
return 0;
}
| Trecho | O que faz |
|---|---|
#define MAX_TENTATIVAS 7 | Uma constante com nome: antes de compilar, o pré-processador troca MAX_TENTATIVAS por 7 em todo o código. Para deixar o jogo mais fácil, você muda num lugar só (veja Constantes). |
int jogar(int secreto) | A função recebe o número sorteado como parâmetro e devolve um int. |
for (int tentativa = 1; tentativa <= MAX_TENTATIVAS; tentativa++) | Repete no máximo 7 vezes, com tentativa valendo 1, 2, …, 7. Aqui o for é melhor que o while: sabemos o número máximo de voltas. |
return tentativa; | Acertou: sai da função e do laço na hora, devolvendo quantas tentativas usou. |
printf("Suas tentativas acabaram…") e return 0; | Só chega aqui quem passou pelas 7 voltas sem acertar. |
exit(1); | Dentro de uma função, return só sai da função. Para encerrar o programa de qualquer lugar, use exit, do stdlib.h (veja Encerrar o Programa). |
int recorde = 0; | 0 quer dizer "ainda não tem recorde". |
usadas > 0 && (recorde == 0 || usadas < recorde) | "Ganhou e (é a primeira vitória ou usou menos tentativas que o recorde)". Os parênteses importam: veja Precedência. |
while (resposta == 's' || resposta == 'S') | Repete as partidas enquanto a resposta for s. A primeira volta sempre acontece, porque resposta começa com 's'. |
A sessão do começo da página é esta versão. Se a pessoa digitar texto, o jogo termina com uma mensagem (e o código de saída 1):
$ ./adivinhacao === Jogo de Adivinhação === Pensei num número de 1 a 100. Você tem 7 tentativas. Tentativa 1: cinquenta Fim de jogo: não consegui ler um número. $ echo $? 1
Testar o limite de tentativas parece depender da sorte: e se a entrada acertar o número sem querer? Truque: chutar 0. O secreto vai de 1 a 100, então 0 nunca acerta, e a resposta é sempre "É maior.". Sete zeros = derrota garantida, seja qual for o número sorteado.
Missão (versão 4, o limite): a função jogar repete para sempre. Troque o while (1) por um for que vai de 1 até MAX_TENTATIVAS e, depois do laço, mostre Suas tentativas acabaram. O número era N. e devolva 0. A entrada da missão chuta 0 sete vezes e responde n.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_TENTATIVAS 7
// Joga uma partida. Devolve quantas tentativas a pessoa usou,
// ou 0 se ela não acertou dentro do limite.
int jogar(int secreto) {
printf("\nPensei num número de 1 a 100. Você tem %d tentativas.\n", MAX_TENTATIVAS);
// limite as tentativas a MAX_TENTATIVAS
int tentativa = 0;
while (1) {
tentativa++;
int palpite = 0;
printf("Tentativa %d: ", tentativa);
if (scanf("%d", &palpite) != 1) {
printf("\nFim de jogo: não consegui ler um número.\n");
exit(1);
}
if (palpite == secreto) {
printf("Acertou em %d tentativa(s)!\n", tentativa);
return tentativa;
} else if (palpite < secreto) {
printf("É maior.\n");
} else {
printf("É menor.\n");
}
}
}
int main(void) {
srand(time(NULL));
int recorde = 0; // 0 = ainda não há recorde
char resposta = 's';
printf("=== Jogo de Adivinhação ===\n");
while (resposta == 's' || resposta == 'S') {
int secreto = rand() % 100 + 1;
int usadas = jogar(secreto);
if (usadas > 0 && (recorde == 0 || usadas < recorde)) {
recorde = usadas;
printf("Novo recorde: %d tentativa(s)!\n", recorde);
}
printf("Jogar de novo? (s/n): ");
if (scanf(" %c", &resposta) != 1) {
resposta = 'n';
}
}
if (recorde > 0) {
printf("Seu recorde: %d tentativa(s).\n", recorde);
}
printf("Até a próxima!\n");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_TENTATIVAS 7
// Joga uma partida. Devolve quantas tentativas a pessoa usou,
// ou 0 se ela não acertou dentro do limite.
int jogar(int secreto) {
printf("\nPensei num número de 1 a 100. Você tem %d tentativas.\n", MAX_TENTATIVAS);
for (int tentativa = 1; tentativa <= MAX_TENTATIVAS; tentativa++) {
int palpite = 0;
printf("Tentativa %d: ", tentativa);
if (scanf("%d", &palpite) != 1) {
printf("\nFim de jogo: não consegui ler um número.\n");
exit(1);
}
if (palpite == secreto) {
printf("Acertou em %d tentativa(s)!\n", tentativa);
return tentativa;
} else if (palpite < secreto) {
printf("É maior.\n");
} else {
printf("É menor.\n");
}
}
printf("Suas tentativas acabaram. O número era %d.\n", secreto);
return 0;
}
int main(void) {
srand(time(NULL));
int recorde = 0; // 0 = ainda não há recorde
char resposta = 's';
printf("=== Jogo de Adivinhação ===\n");
while (resposta == 's' || resposta == 'S') {
int secreto = rand() % 100 + 1;
int usadas = jogar(secreto);
if (usadas > 0 && (recorde == 0 || usadas < recorde)) {
recorde = usadas;
printf("Novo recorde: %d tentativa(s)!\n", recorde);
}
printf("Jogar de novo? (s/n): ");
if (scanf(" %c", &resposta) != 1) {
resposta = 'n';
}
}
if (recorde > 0) {
printf("Seu recorde: %d tentativa(s).\n", recorde);
}
printf("Até a próxima!\n");
return 0;
}
Missão (versão 4, jogar de novo): o jogo pergunta "Jogar de novo?", mas ignora a resposta. Troque o bloco { … } do main por while (resposta == 's' || resposta == 'S') { … }. A entrada perde uma partida (sete zeros), responde s, perde outra e responde n: o jogo deve mostrar "Pensei num número" duas vezes.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_TENTATIVAS 7
// Joga uma partida. Devolve quantas tentativas a pessoa usou,
// ou 0 se ela não acertou dentro do limite.
int jogar(int secreto) {
printf("\nPensei num número de 1 a 100. Você tem %d tentativas.\n", MAX_TENTATIVAS);
for (int tentativa = 1; tentativa <= MAX_TENTATIVAS; tentativa++) {
int palpite = 0;
printf("Tentativa %d: ", tentativa);
if (scanf("%d", &palpite) != 1) {
printf("\nFim de jogo: não consegui ler um número.\n");
exit(1);
}
if (palpite == secreto) {
printf("Acertou em %d tentativa(s)!\n", tentativa);
return tentativa;
} else if (palpite < secreto) {
printf("É maior.\n");
} else {
printf("É menor.\n");
}
}
printf("Suas tentativas acabaram. O número era %d.\n", secreto);
return 0;
}
int main(void) {
srand(time(NULL));
int recorde = 0; // 0 = ainda não há recorde
char resposta = 's';
printf("=== Jogo de Adivinhação ===\n");
// repita a partida enquanto a resposta for s ou S
{
int secreto = rand() % 100 + 1;
int usadas = jogar(secreto);
if (usadas > 0 && (recorde == 0 || usadas < recorde)) {
recorde = usadas;
printf("Novo recorde: %d tentativa(s)!\n", recorde);
}
printf("Jogar de novo? (s/n): ");
if (scanf(" %c", &resposta) != 1) {
resposta = 'n';
}
}
if (recorde > 0) {
printf("Seu recorde: %d tentativa(s).\n", recorde);
}
printf("Até a próxima!\n");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_TENTATIVAS 7
// Joga uma partida. Devolve quantas tentativas a pessoa usou,
// ou 0 se ela não acertou dentro do limite.
int jogar(int secreto) {
printf("\nPensei num número de 1 a 100. Você tem %d tentativas.\n", MAX_TENTATIVAS);
for (int tentativa = 1; tentativa <= MAX_TENTATIVAS; tentativa++) {
int palpite = 0;
printf("Tentativa %d: ", tentativa);
if (scanf("%d", &palpite) != 1) {
printf("\nFim de jogo: não consegui ler um número.\n");
exit(1);
}
if (palpite == secreto) {
printf("Acertou em %d tentativa(s)!\n", tentativa);
return tentativa;
} else if (palpite < secreto) {
printf("É maior.\n");
} else {
printf("É menor.\n");
}
}
printf("Suas tentativas acabaram. O número era %d.\n", secreto);
return 0;
}
int main(void) {
srand(time(NULL));
int recorde = 0; // 0 = ainda não há recorde
char resposta = 's';
printf("=== Jogo de Adivinhação ===\n");
while (resposta == 's' || resposta == 'S') {
int secreto = rand() % 100 + 1;
int usadas = jogar(secreto);
if (usadas > 0 && (recorde == 0 || usadas < recorde)) {
recorde = usadas;
printf("Novo recorde: %d tentativa(s)!\n", recorde);
}
printf("Jogar de novo? (s/n): ");
if (scanf(" %c", &resposta) != 1) {
resposta = 'n';
}
}
if (recorde > 0) {
printf("Seu recorde: %d tentativa(s).\n", recorde);
}
printf("Até a próxima!\n");
return 0;
}
O programa completo
A versão final, igual à versão 4. Compile com gcc -std=c23 -Wall -Wextra adivinhacao.c -o adivinhacao:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_TENTATIVAS 7
// Joga uma partida. Devolve quantas tentativas a pessoa usou,
// ou 0 se ela não acertou dentro do limite.
int jogar(int secreto) {
printf("\nPensei num número de 1 a 100. Você tem %d tentativas.\n", MAX_TENTATIVAS);
for (int tentativa = 1; tentativa <= MAX_TENTATIVAS; tentativa++) {
int palpite = 0;
printf("Tentativa %d: ", tentativa);
if (scanf("%d", &palpite) != 1) {
printf("\nFim de jogo: não consegui ler um número.\n");
exit(1);
}
if (palpite == secreto) {
printf("Acertou em %d tentativa(s)!\n", tentativa);
return tentativa;
} else if (palpite < secreto) {
printf("É maior.\n");
} else {
printf("É menor.\n");
}
}
printf("Suas tentativas acabaram. O número era %d.\n", secreto);
return 0;
}
int main(void) {
srand(time(NULL));
int recorde = 0; // 0 = ainda não há recorde
char resposta = 's';
printf("=== Jogo de Adivinhação ===\n");
while (resposta == 's' || resposta == 'S') {
int secreto = rand() % 100 + 1;
int usadas = jogar(secreto);
if (usadas > 0 && (recorde == 0 || usadas < recorde)) {
recorde = usadas;
printf("Novo recorde: %d tentativa(s)!\n", recorde);
}
printf("Jogar de novo? (s/n): ");
if (scanf(" %c", &resposta) != 1) {
resposta = 'n';
}
}
if (recorde > 0) {
printf("Seu recorde: %d tentativa(s).\n", recorde);
}
printf("Até a próxima!\n");
return 0;
}
O que o projeto juntou: scanf, else if, while, for, ++, && e ||, rand e srand, #define, funções e exit.
Rodando no laboratório
Uma partida a mais na máquina da Ana, só para ver o número mudar. Ela chutou o meio e precisou das 7 tentativas, por pouco:
$ gcc -std=c23 -Wall -Wextra adivinhacao.c -o adivinhacao $ ./adivinhacao === Jogo de Adivinhação === Pensei num número de 1 a 100. Você tem 7 tentativas. Tentativa 1: 50 É menor. Tentativa 2: 25 É maior. Tentativa 3: 37 É menor. Tentativa 4: 31 É maior. Tentativa 5: 34 É maior. Tentativa 6: 35 É maior. Tentativa 7: 36 Acertou em 7 tentativa(s)! Novo recorde: 7 tentativa(s)! Jogar de novo? (s/n): n Seu recorde: 7 tentativa(s). Até a próxima!
Desafios extras
- Dica de intervalo. Em vez de "É maior.", mostre o intervalo que sobrou:
Está entre 51 e 100.Guarde dois inteiros,menoremaior, e atualize a cada palpite. - Palpite fora do intervalo. Se a pessoa chutar 0 ou 150, avise
Escolha de 1 a 100.e não conte a tentativa. - Níveis. Pergunte no começo: fácil (1 a 50, 10 tentativas), médio (1 a 100, 7) ou difícil (1 a 1000, 10). A função
jogarpassa a receber o máximo e o limite como parâmetros. - Pedir de novo em vez de encerrar. Quando a pessoa digitar texto, peça o palpite de novo. Use
fgetsestrtol, como a Calculadora faz comstrtod. - Recorde guardado. Grave o recorde num arquivo
recorde.txtao sair e leia ao começar, para ele valer de um dia para o outro (veja Escrever Arquivos e Ler Arquivos).
Exercícios
1. Qual expressão sorteia um número de 1 a 6, como um dado?
2. A Ana esqueceu o srand(time(NULL)). O que acontece?
3. Por que a missão do limite chuta 0 e não, por exemplo, 50?
4. Na função jogar, o que o return tentativa; dentro do for faz?
5. Complete a linha que embaralha a sequência do rand() usando o relógio:
6. Complete o laço que dá no máximo MAX_TENTATIVAS voltas, começando em 1:
Resumo
- Teste primeiro com um número fixo; sorteie depois.
while (palpite != secreto)repete até acertar; um contador com++conta as tentativas.- Confira o retorno do
scanf: texto na entrada vira laço infinito. rand() % 100 + 1sorteia de 1 a 100;srand(time(NULL)), uma vez no começo, muda a sequência a cada execução.- Os números do
rand()mudam de uma biblioteca C para outra (gcc × editor do guia): não dependa deles. - Para testar sem depender da sorte: palpites que cobrem todos os números, ou palpites que nunca acertam (0).
Próximo projeto: Boletim de Notas.