Projeto Jogo da Adivinhação
O computador pensa num número e você tenta adivinhar. A cada palpite, ele diz se o número secreto é maior ou menor. É o jogo clássico de quem aprende a programar, porque usa um pouco de tudo: sorteio, repetição, decisões, contagem e, na versão final, níveis de dificuldade feitos com enum e um recorde.
- Sortear números com Random.
- Decidir com if, else if, else e repetir com while e do-while.
- Contar tentativas e usar constantes (final).
- Validar números inteiros com
hasNextInt. - Criar um enum com atributos e construtor.
- Guardar o melhor resultado (recorde) entre partidas.
O que vamos construir
O jogo pronto, com três partidas da Ana (ela é boa nisso: sempre chuta o meio do intervalo que sobrou):
$ java Adivinhacao.java === Jogo da Adivinhação === 1 = FACIL (1 a 10, 4 tentativas) 2 = MEDIO (1 a 50, 6 tentativas) 3 = DIFICIL (1 a 100, 7 tentativas) Nível: 3 Pensei num número de 1 a 100. Você tem 7 tentativas. Palpite: 50 É menor que 50. Palpite: 25 É maior que 25. Palpite: 37 É maior que 37. Palpite: 43 É maior que 43. Palpite: 46 É maior que 46. Palpite: 48 É menor que 48. Palpite: 47 Acertou em 7 tentativa(s)! Novo recorde: 7 tentativa(s)! Jogar de novo? (s/n): s 1 = FACIL (1 a 10, 4 tentativas) 2 = MEDIO (1 a 50, 6 tentativas) 3 = DIFICIL (1 a 100, 7 tentativas) Nível: 1 Pensei num número de 1 a 10. Você tem 4 tentativas. Palpite: 5 É maior que 5. Palpite: 8 É menor que 8. Palpite: 6 É maior que 6. Palpite: 7 Acertou em 4 tentativa(s)! Novo recorde: 4 tentativa(s)! « melhor que 7: virou o recorde Jogar de novo? (s/n): s 1 = FACIL (1 a 10, 4 tentativas) 2 = MEDIO (1 a 50, 6 tentativas) 3 = DIFICIL (1 a 100, 7 tentativas) Nível: 2 Pensei num número de 1 a 50. Você tem 6 tentativas. Palpite: 25 É maior que 25. Palpite: 38 É maior que 38. Palpite: 44 É menor que 44. Palpite: 41 É maior que 41. Palpite: 42 É maior que 42. Palpite: 43 Acertou em 6 tentativa(s)! « 6 não bate 4: o recorde fica Jogar de novo? (s/n): n Seu recorde: 4 tentativa(s). Até a próxima!
Como o número é sorteado, cada vez que você rodar o jogo vai ver números diferentes. As etapas:
- Sortear e dar um palpite (
Random,if/else). - Repetir até acertar (
while, contador). - Limitar as tentativas (constantes, condição composta).
- Métodos e validação (
jogar,lerInteiro,hasNextInt). - Níveis de dificuldade (
enumcom atributos). - Jogar de novo e recorde (
do-while).
Antes de começar
Este projeto usa o que você viu no projeto da Calculadora (Scanner, métodos, validação) e acrescenta Números Aleatórios e Enums. No seu computador:
$ mkdir -p java/adivinhacao $ cd java/adivinhacao
new Random(7)
Um jogo de sorteio não pode ser conferido automaticamente: cada execução sorteia outro número. Por isso, nas caixas Experimente, o Random recebe uma semente (seed): new Random(7). Com a mesma semente, o Java sorteia sempre a mesma sequência; com a semente 7, o primeiro nextInt(100) + 1 é sempre 37. No seu computador, use new Random(), sem número, para o jogo ser de verdade. A explicação completa está em Números Aleatórios.
Etapa 1 · Sortear e dar um palpite
Primeiro, o mínimo: sortear um número de 1 a 100, ler um palpite e dizer se acertou, se o secreto é maior ou menor. No fim, para conferir, o programa revela o número.
import java.util.Random;
import java.util.Scanner;
public class Adivinhacao {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
Random sorteio = new Random();
int secreto = sorteio.nextInt(100) + 1;
System.out.println("Pensei num número de 1 a 100.");
System.out.print("Palpite: ");
int palpite = entrada.nextInt();
if (palpite == secreto) {
System.out.println("Acertou!");
} else if (palpite < secreto) {
System.out.println("É maior que " + palpite + ".");
} else {
System.out.println("É menor que " + palpite + ".");
}
System.out.println("O número era " + secreto + ".");
}
}
| Linha | O que faz |
|---|---|
import java.util.Random; | A classe Random (aleatório) também mora em java.util. |
Random sorteio = new Random(); | Cria o "sorteador". Sem semente, cada execução dá números diferentes. |
sorteio.nextInt(100) | Sorteia um int de 0 a 99: o número entre parênteses é o limite, que não entra. |
+ 1 | Desloca o intervalo para 1 a 100. |
entrada.nextInt() | Lê um número inteiro digitado. |
if … else if … else | Três caminhos: igual, menor, maior. Só um deles roda (if, else if, else). |
$ java Adivinhacao.java Pensei num número de 1 a 100. Palpite: 50 É maior que 50. O número era 91. $ java Adivinhacao.java Pensei num número de 1 a 100. Palpite: 50 É menor que 50. O número era 22. « outro sorteio, outro número
Repare na lógica da dica: se o palpite (50) é menor que o secreto (91), a dica é "É maior que 50", porque a pessoa precisa subir.
Missão (etapa 1): escreva o if / else if / else que compara palpite com secreto e mostra Acertou!, É maior que 50. ou É menor que 50. (use a variável palpite no texto). Com a semente 7, o secreto é 37 e o palpite da missão é 50.
import java.util.Random;
import java.util.Scanner;
public class Adivinhacao {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
Random sorteio = new Random(7); // semente 7: sorteia sempre o mesmo número
int secreto = sorteio.nextInt(100) + 1;
System.out.println("Pensei num número de 1 a 100.");
System.out.print("Palpite: ");
int palpite = entrada.nextInt();
// compare o palpite com o secreto e mostre a dica
System.out.println("O número era " + secreto + ".");
}
}
import java.util.Random;
import java.util.Scanner;
public class Adivinhacao {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
Random sorteio = new Random(7); // semente 7: sorteia sempre o mesmo número
int secreto = sorteio.nextInt(100) + 1;
System.out.println("Pensei num número de 1 a 100.");
System.out.print("Palpite: ");
int palpite = entrada.nextInt();
if (palpite == secreto) {
System.out.println("Acertou!");
} else if (palpite < secreto) {
System.out.println("É maior que " + palpite + ".");
} else {
System.out.println("É menor que " + palpite + ".");
}
System.out.println("O número era " + secreto + ".");
}
}
Etapa 2 · Repetir até acertar
Um palpite só não é jogo. Agora o programa repete a pergunta enquanto o palpite for diferente do secreto, e conta quantas tentativas a pessoa usou.
import java.util.Random;
import java.util.Scanner;
public class Adivinhacao {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
Random sorteio = new Random();
int secreto = sorteio.nextInt(100) + 1;
System.out.println("Pensei num número de 1 a 100.");
int tentativas = 0;
int palpite = 0;
while (palpite != secreto) {
System.out.print("Palpite: ");
palpite = entrada.nextInt();
tentativas++;
if (palpite < secreto) {
System.out.println("É maior que " + palpite + ".");
} else if (palpite > secreto) {
System.out.println("É menor que " + palpite + ".");
}
}
System.out.println("Acertou em " + tentativas + " tentativa(s)!");
}
}
- int tentativas = 0;
- O contador: começa em zero, antes do laço.
- int palpite = 0;
- O palpite precisa existir antes do
while, porque a condição usa ele. Começa em 0, que nunca é o secreto (o sorteio vai de 1 a 100), então o laço roda pelo menos uma vez. - while (palpite != secreto)
- "Enquanto o palpite for diferente do secreto, repita."
!=é "diferente" (operadores de comparação). - tentativas++;
- Soma 1 ao contador a cada volta.
- println("Acertou em " …)
- Fica depois do laço: só chega aqui quem acertou.
$ java Adivinhacao.java Pensei num número de 1 a 100. Palpite: 50 É menor que 50. Palpite: 25 É maior que 25. Palpite: 37 É menor que 37. Palpite: 31 É menor que 31. Palpite: 28 Acertou em 5 tentativa(s)!
Chutar sempre o meio do que sobrou corta as possibilidades pela metade a cada palpite: 100 → 50 → 25 → 12 → 6 → 3 → 1. Por isso, de 1 a 100, 7 palpites sempre bastam. Guarde esse número: ele vai virar o limite da próxima etapa.
Missão (etapa 2): transforme o palpite único num laço while que repete até acertar e conte as tentativas. No fim, mostre Acertou em 3 tentativa(s)! (com a semente 7 e os palpites 50, 25, 37 da missão).
import java.util.Random;
import java.util.Scanner;
public class Adivinhacao {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
Random sorteio = new Random(7); // semente 7: sorteia sempre o mesmo número
int secreto = sorteio.nextInt(100) + 1;
System.out.println("Pensei num número de 1 a 100.");
System.out.print("Palpite: ");
int palpite = entrada.nextInt();
if (palpite == secreto) {
System.out.println("Acertou!");
} else if (palpite < secreto) {
System.out.println("É maior que " + palpite + ".");
} else {
System.out.println("É menor que " + palpite + ".");
}
System.out.println("O número era " + secreto + ".");
}
}
import java.util.Random;
import java.util.Scanner;
public class Adivinhacao {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
Random sorteio = new Random(7); // semente 7: sorteia sempre o mesmo número
int secreto = sorteio.nextInt(100) + 1;
System.out.println("Pensei num número de 1 a 100.");
int tentativas = 0;
int palpite = 0;
while (palpite != secreto) {
System.out.print("Palpite: ");
palpite = entrada.nextInt();
tentativas++;
if (palpite < secreto) {
System.out.println("É maior que " + palpite + ".");
} else if (palpite > secreto) {
System.out.println("É menor que " + palpite + ".");
}
}
System.out.println("Acertou em " + tentativas + " tentativa(s)!");
}
}
Etapa 3 · Limitar as tentativas
Sem limite não há como perder, e jogo sem derrota não tem graça. Vamos dar 7 tentativas. Os números 100 e 7 viram constantes: valores com nome, que não mudam.
import java.util.Random;
import java.util.Scanner;
public class Adivinhacao {
static final int MAXIMO = 100;
static final int MAX_TENTATIVAS = 7;
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
Random sorteio = new Random();
int secreto = sorteio.nextInt(MAXIMO) + 1;
System.out.println("Pensei num número de 1 a " + MAXIMO + ". Você tem " + MAX_TENTATIVAS + " tentativas.");
int tentativas = 0;
boolean acertou = false;
while (!acertou && tentativas < MAX_TENTATIVAS) {
System.out.print("Palpite: ");
int palpite = entrada.nextInt();
tentativas++;
if (palpite == secreto) {
acertou = true;
} else if (palpite < secreto) {
System.out.println("É maior que " + palpite + ".");
} else {
System.out.println("É menor que " + palpite + ".");
}
}
if (acertou) {
System.out.println("Acertou em " + tentativas + " tentativa(s)!");
} else {
System.out.println("Acabaram as tentativas. O número era " + secreto + ".");
}
}
}
- static final int MAX_TENTATIVAS = 7;
final= "final, não muda mais";static= da classe. Por costume, constantes têm nome em MAIÚSCULAS com_(veja Constantes). Mudar a dificuldade agora é mudar uma linha só.- boolean acertou = false;
- Uma "bandeira" que diz se a pessoa já acertou.
- while (!acertou && tentativas < MAX_TENTATIVAS)
- Continua enquanto não acertou e ainda tem tentativas. Basta uma das duas ficar falsa para o laço parar.
- if (acertou) … else …
- Depois do laço, a bandeira diz por que ele parou: vitória ou fim das tentativas.
$ java Adivinhacao.java Pensei num número de 1 a 100. Você tem 7 tentativas. Palpite: 10 É maior que 10. Palpite: 20 É maior que 20. Palpite: 30 É maior que 30. Palpite: 40 É maior que 40. Palpite: 60 É menor que 60. Palpite: 70 « a dica dizia "menor que 60", mas a Ana se distraiu É menor que 70. Palpite: 80 É menor que 80. Acabaram as tentativas. O número era 50.
Missão (etapa 3): crie a constante MAX_TENTATIVAS com o valor 7 e faça o jogo parar quando ela acabar, mostrando Acabaram as tentativas. O número era 37. A entrada da missão tem sete palpites errados.
import java.util.Random;
import java.util.Scanner;
public class Adivinhacao {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
Random sorteio = new Random(7); // semente 7: sorteia sempre o mesmo número
int secreto = sorteio.nextInt(100) + 1;
System.out.println("Pensei num número de 1 a 100.");
int tentativas = 0;
int palpite = 0;
while (palpite != secreto) {
System.out.print("Palpite: ");
palpite = entrada.nextInt();
tentativas++;
if (palpite < secreto) {
System.out.println("É maior que " + palpite + ".");
} else if (palpite > secreto) {
System.out.println("É menor que " + palpite + ".");
}
}
System.out.println("Acertou em " + tentativas + " tentativa(s)!");
}
}
import java.util.Random;
import java.util.Scanner;
public class Adivinhacao {
static final int MAXIMO = 100;
static final int MAX_TENTATIVAS = 7;
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
Random sorteio = new Random(7); // semente 7: sorteia sempre o mesmo número
int secreto = sorteio.nextInt(MAXIMO) + 1;
System.out.println("Pensei num número de 1 a " + MAXIMO + ". Você tem " + MAX_TENTATIVAS + " tentativas.");
int tentativas = 0;
boolean acertou = false;
while (!acertou && tentativas < MAX_TENTATIVAS) {
System.out.print("Palpite: ");
int palpite = entrada.nextInt();
tentativas++;
if (palpite == secreto) {
acertou = true;
} else if (palpite < secreto) {
System.out.println("É maior que " + palpite + ".");
} else {
System.out.println("É menor que " + palpite + ".");
}
}
if (acertou) {
System.out.println("Acertou em " + tentativas + " tentativa(s)!");
} else {
System.out.println("Acabaram as tentativas. O número era " + secreto + ".");
}
}
}
Etapa 4 · Métodos e validação
Como na calculadora, o main cresceu. Separamos a partida no método jogar e a leitura no método lerInteiro, que recusa o que não for número inteiro. De quebra, o while com bandeira vira um for com return, que fica mais curto:
import java.util.Random;
import java.util.Scanner;
public class Adivinhacao {
static final int MAXIMO = 100;
static final int MAX_TENTATIVAS = 7;
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
Random sorteio = new Random();
System.out.println("=== Jogo da Adivinhação ===");
int resultado = jogar(entrada, sorteio);
if (resultado == 0) {
System.out.println("Fica para a próxima!");
}
}
static int jogar(Scanner entrada, Random sorteio) {
int secreto = sorteio.nextInt(MAXIMO) + 1;
System.out.println("Pensei num número de 1 a " + MAXIMO + ". Você tem " + MAX_TENTATIVAS + " tentativas.");
for (int tentativas = 1; tentativas <= MAX_TENTATIVAS; tentativas++) {
int palpite = lerInteiro(entrada, "Palpite: ");
if (palpite == secreto) {
System.out.println("Acertou em " + tentativas + " tentativa(s)!");
return tentativas;
} else if (palpite < secreto) {
System.out.println("É maior que " + palpite + ".");
} else {
System.out.println("É menor que " + palpite + ".");
}
}
System.out.println("Acabaram as tentativas. O número era " + secreto + ".");
return 0;
}
static int lerInteiro(Scanner entrada, String pergunta) {
System.out.print(pergunta);
while (!entrada.hasNextInt()) {
System.out.println("\"" + entrada.next() + "\" não é um número inteiro.");
System.out.print(pergunta);
}
return entrada.nextInt();
}
}
| Mudança | Por quê |
|---|---|
static int jogar(…) devolve um int | Devolve quantas tentativas foram usadas para acertar, ou 0 se a pessoa perdeu. Na etapa 6 esse número vira o recorde. |
for (int tentativas = 1; tentativas <= MAX_TENTATIVAS; tentativas++) | Conta de 1 a 7 sozinho (for). A variável tentativas já é o número da tentativa atual. |
return tentativas; dentro do if | Acertou: sai do método na hora, sem precisar de bandeira nem de break. |
Depois do for: "Acabaram…" e return 0; | Só chega aqui quem usou as 7 tentativas sem acertar. |
hasNextInt() em lerInteiro | Confere se há um inteiro esperando; se não, descarta a palavra com next() e pergunta de novo. |
$ java Adivinhacao.java === Jogo da Adivinhação === Pensei num número de 1 a 100. Você tem 7 tentativas. Palpite: cinquenta "cinquenta" não é um número inteiro. Palpite: 50 É menor que 50. Palpite: 25 É menor que 25. Palpite: 12 É maior que 12. Palpite: 18 É menor que 18. Palpite: 15 É maior que 15. Palpite: 16 Acertou em 6 tentativa(s)!
Repare que "cinquenta" não gastou uma tentativa: o for só avança depois que lerInteiro devolve um número.
Missão (etapa 4): rode como está: com "cinquenta" na entrada, o jogo quebra com InputMismatchException. Conserte o método lerInteiro com hasNextInt() para mostrar "cinquenta" não é um número inteiro. e perguntar de novo.
import java.util.Random;
import java.util.Scanner;
public class Adivinhacao {
static final int MAXIMO = 100;
static final int MAX_TENTATIVAS = 7;
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
Random sorteio = new Random(7); // semente 7: sorteia sempre o mesmo número
System.out.println("=== Jogo da Adivinhação ===");
int resultado = jogar(entrada, sorteio);
if (resultado == 0) {
System.out.println("Fica para a próxima!");
}
}
static int jogar(Scanner entrada, Random sorteio) {
int secreto = sorteio.nextInt(MAXIMO) + 1;
System.out.println("Pensei num número de 1 a " + MAXIMO + ". Você tem " + MAX_TENTATIVAS + " tentativas.");
for (int tentativas = 1; tentativas <= MAX_TENTATIVAS; tentativas++) {
int palpite = lerInteiro(entrada, "Palpite: ");
if (palpite == secreto) {
System.out.println("Acertou em " + tentativas + " tentativa(s)!");
return tentativas;
} else if (palpite < secreto) {
System.out.println("É maior que " + palpite + ".");
} else {
System.out.println("É menor que " + palpite + ".");
}
}
System.out.println("Acabaram as tentativas. O número era " + secreto + ".");
return 0;
}
static int lerInteiro(Scanner entrada, String pergunta) {
System.out.print(pergunta);
return entrada.nextInt();
}
}
import java.util.Random;
import java.util.Scanner;
public class Adivinhacao {
static final int MAXIMO = 100;
static final int MAX_TENTATIVAS = 7;
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
Random sorteio = new Random(7); // semente 7: sorteia sempre o mesmo número
System.out.println("=== Jogo da Adivinhação ===");
int resultado = jogar(entrada, sorteio);
if (resultado == 0) {
System.out.println("Fica para a próxima!");
}
}
static int jogar(Scanner entrada, Random sorteio) {
int secreto = sorteio.nextInt(MAXIMO) + 1;
System.out.println("Pensei num número de 1 a " + MAXIMO + ". Você tem " + MAX_TENTATIVAS + " tentativas.");
for (int tentativas = 1; tentativas <= MAX_TENTATIVAS; tentativas++) {
int palpite = lerInteiro(entrada, "Palpite: ");
if (palpite == secreto) {
System.out.println("Acertou em " + tentativas + " tentativa(s)!");
return tentativas;
} else if (palpite < secreto) {
System.out.println("É maior que " + palpite + ".");
} else {
System.out.println("É menor que " + palpite + ".");
}
}
System.out.println("Acabaram as tentativas. O número era " + secreto + ".");
return 0;
}
static int lerInteiro(Scanner entrada, String pergunta) {
System.out.print(pergunta);
while (!entrada.hasNextInt()) {
System.out.println("\"" + entrada.next() + "\" não é um número inteiro.");
System.out.print(pergunta);
}
return entrada.nextInt();
}
}
Etapa 5 · Níveis de dificuldade com enum
Agora queremos três níveis: fácil (1 a 10), médio (1 a 50) e difícil (1 a 100), cada um com o seu número de tentativas. Poderíamos usar ints soltos (1, 2, 3) e um monte de if, mas o Java tem algo melhor: o enum (de enumeration, "enumeração", uma lista fechada de opções). Cada nível vira uma constante que carrega os seus próprios dados:
enum Nivel {
FACIL(10, 4),
MEDIO(50, 6),
DIFICIL(100, 7);
final int maximo;
final int tentativas;
Nivel(int maximo, int tentativas) {
this.maximo = maximo;
this.tentativas = tentativas;
}
}
- enum Nivel { … }
- Um tipo novo,
Nivel, que só pode ter os valores listados. Ele fica dentro da classeAdivinhacao, como um "enum interno". - FACIL(10, 4)
- Uma constante do enum. Os números entre parênteses vão para o construtor: máximo 10, 4 tentativas.
- final int maximo;
- Atributos: cada nível guarda o seu máximo e as suas tentativas.
- Nivel(int maximo, int tentativas)
- O construtor, chamado uma vez para cada constante.
this.maximoé o atributo;maximosozinho é o parâmetro (veja this).
Com o enum, o resto do programa pede o nível e passa ele para o jogar, que troca MAXIMO por nivel.maximo e MAX_TENTATIVAS por nivel.tentativas. O método que mostra o menu e lê a escolha:
static Nivel escolherNivel(Scanner entrada) {
Nivel[] niveis = Nivel.values();
for (int i = 0; i < niveis.length; i++) {
Nivel n = niveis[i];
System.out.println((i + 1) + " = " + n + " (1 a " + n.maximo + ", " + n.tentativas + " tentativas)");
}
int escolha = lerInteiro(entrada, "Nível: ");
while (escolha < 1 || escolha > niveis.length) {
System.out.println("Escolha de 1 a " + niveis.length + ".");
escolha = lerInteiro(entrada, "Nível: ");
}
return niveis[escolha - 1];
}
| Trecho | O que faz |
|---|---|
Nivel.values() | Devolve um array com todas as constantes, na ordem em que foram escritas: [FACIL, MEDIO, DIFICIL]. |
" = " + n | Um enum vira texto com o próprio nome: FACIL. |
escolha < 1 || escolha > niveis.length | "Menor que 1 ou maior que 3": fora do menu, pergunta de novo. |
niveis[escolha - 1] | A pessoa digita 1, 2 ou 3; o array começa no índice 0. Por isso o - 1. |
O programa completo desta etapa está na caixa Experimente logo abaixo.
$ java Adivinhacao.java === Jogo da Adivinhação === 1 = FACIL (1 a 10, 4 tentativas) 2 = MEDIO (1 a 50, 6 tentativas) 3 = DIFICIL (1 a 100, 7 tentativas) Nível: 4 Escolha de 1 a 3. Nível: 1 Pensei num número de 1 a 10. Você tem 4 tentativas. Palpite: 5 É maior que 5. Palpite: 8 É menor que 8. Palpite: 6 É maior que 6. Palpite: 7 Acertou em 4 tentativa(s)!
O menu foi montado a partir do enum: se você acrescentar um nível na lista, ele aparece no menu sem mudar mais nada.
valueOf
Outra forma de escolher o nível é a pessoa digitar o nome, e o programa converter com Nivel.valueOf(texto). Funciona com MEDIO, mas o nome tem que ser idêntico, maiúsculas incluídas:
$ java Adivinhacao.java Nível (FACIL, MEDIO, DIFICIL): MEDIO Você escolheu MEDIO $ java Adivinhacao.java Nível (FACIL, MEDIO, DIFICIL): facil Exception in thread "main" java.lang.IllegalArgumentException: No enum constant Adivinhacao.Nivel.facil at java.base/java.lang.Enum.valueOf(Enum.java:293) at Adivinhacao$Nivel.valueOf(Adivinhacao.java:4) at Adivinhacao.main(Adivinhacao.java:9)
"Não existe constante facil no enum Adivinhacao.Nivel." O Adivinhacao$Nivel é o nome interno do enum que mora dentro da classe. Para aceitar minúsculas, converta antes: Nivel.valueOf(texto.toUpperCase()). Mesmo assim, "fácil" (com acento) ainda falharia; por isso o menu com números é mais seguro.
Missão (etapa 5): acrescente o nível IMPOSSIVEL, de 1 a 1000, com 10 tentativas. Só o enum muda: o menu deve mostrar 4 = IMPOSSIVEL (1 a 1000, 10 tentativas) sozinho. A entrada da missão escolhe o nível 4.
import java.util.Random;
import java.util.Scanner;
public class Adivinhacao {
enum Nivel {
FACIL(10, 4),
MEDIO(50, 6),
DIFICIL(100, 7);
final int maximo;
final int tentativas;
Nivel(int maximo, int tentativas) {
this.maximo = maximo;
this.tentativas = tentativas;
}
}
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
Random sorteio = new Random(7); // semente 7: sorteia sempre o mesmo número
System.out.println("=== Jogo da Adivinhação ===");
Nivel nivel = escolherNivel(entrada);
int resultado = jogar(entrada, sorteio, nivel);
if (resultado == 0) {
System.out.println("Fica para a próxima!");
}
}
static Nivel escolherNivel(Scanner entrada) {
Nivel[] niveis = Nivel.values();
for (int i = 0; i < niveis.length; i++) {
Nivel n = niveis[i];
System.out.println((i + 1) + " = " + n + " (1 a " + n.maximo + ", " + n.tentativas + " tentativas)");
}
int escolha = lerInteiro(entrada, "Nível: ");
while (escolha < 1 || escolha > niveis.length) {
System.out.println("Escolha de 1 a " + niveis.length + ".");
escolha = lerInteiro(entrada, "Nível: ");
}
return niveis[escolha - 1];
}
static int jogar(Scanner entrada, Random sorteio, Nivel nivel) {
int secreto = sorteio.nextInt(nivel.maximo) + 1;
System.out.println("Pensei num número de 1 a " + nivel.maximo + ". Você tem " + nivel.tentativas + " tentativas.");
for (int tentativas = 1; tentativas <= nivel.tentativas; tentativas++) {
int palpite = lerInteiro(entrada, "Palpite: ");
if (palpite == secreto) {
System.out.println("Acertou em " + tentativas + " tentativa(s)!");
return tentativas;
} else if (palpite < secreto) {
System.out.println("É maior que " + palpite + ".");
} else {
System.out.println("É menor que " + palpite + ".");
}
}
System.out.println("Acabaram as tentativas. O número era " + secreto + ".");
return 0;
}
static int lerInteiro(Scanner entrada, String pergunta) {
System.out.print(pergunta);
while (!entrada.hasNextInt()) {
System.out.println("\"" + entrada.next() + "\" não é um número inteiro.");
System.out.print(pergunta);
}
return entrada.nextInt();
}
}
import java.util.Random;
import java.util.Scanner;
public class Adivinhacao {
enum Nivel {
FACIL(10, 4),
MEDIO(50, 6),
DIFICIL(100, 7),
IMPOSSIVEL(1000, 10);
final int maximo;
final int tentativas;
Nivel(int maximo, int tentativas) {
this.maximo = maximo;
this.tentativas = tentativas;
}
}
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
Random sorteio = new Random(7); // semente 7: sorteia sempre o mesmo número
System.out.println("=== Jogo da Adivinhação ===");
Nivel nivel = escolherNivel(entrada);
int resultado = jogar(entrada, sorteio, nivel);
if (resultado == 0) {
System.out.println("Fica para a próxima!");
}
}
static Nivel escolherNivel(Scanner entrada) {
Nivel[] niveis = Nivel.values();
for (int i = 0; i < niveis.length; i++) {
Nivel n = niveis[i];
System.out.println((i + 1) + " = " + n + " (1 a " + n.maximo + ", " + n.tentativas + " tentativas)");
}
int escolha = lerInteiro(entrada, "Nível: ");
while (escolha < 1 || escolha > niveis.length) {
System.out.println("Escolha de 1 a " + niveis.length + ".");
escolha = lerInteiro(entrada, "Nível: ");
}
return niveis[escolha - 1];
}
static int jogar(Scanner entrada, Random sorteio, Nivel nivel) {
int secreto = sorteio.nextInt(nivel.maximo) + 1;
System.out.println("Pensei num número de 1 a " + nivel.maximo + ". Você tem " + nivel.tentativas + " tentativas.");
for (int tentativas = 1; tentativas <= nivel.tentativas; tentativas++) {
int palpite = lerInteiro(entrada, "Palpite: ");
if (palpite == secreto) {
System.out.println("Acertou em " + tentativas + " tentativa(s)!");
return tentativas;
} else if (palpite < secreto) {
System.out.println("É maior que " + palpite + ".");
} else {
System.out.println("É menor que " + palpite + ".");
}
}
System.out.println("Acabaram as tentativas. O número era " + secreto + ".");
return 0;
}
static int lerInteiro(Scanner entrada, String pergunta) {
System.out.print(pergunta);
while (!entrada.hasNextInt()) {
System.out.println("\"" + entrada.next() + "\" não é um número inteiro.");
System.out.print(pergunta);
}
return entrada.nextInt();
}
}
Etapa 6 · Jogar de novo e recorde
A última etapa deixa a pessoa jogar várias partidas e guarda o recorde: o menor número de tentativas numa vitória. Como queremos jogar pelo menos uma vez antes de perguntar "de novo?", o laço certo é o do-while, que testa a condição no fim. Só o main muda:
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
Random sorteio = new Random();
int recorde = 0; // 0 = ainda não há recorde
System.out.println("=== Jogo da Adivinhação ===");
String resposta;
do {
Nivel nivel = escolherNivel(entrada);
int resultado = jogar(entrada, sorteio, nivel);
if (resultado > 0 && (recorde == 0 || resultado < recorde)) {
recorde = resultado;
System.out.println("Novo recorde: " + recorde + " tentativa(s)!");
}
System.out.print("Jogar de novo? (s/n): ");
resposta = entrada.next();
} while (resposta.equalsIgnoreCase("s"));
if (recorde == 0) {
System.out.println("Sem recorde desta vez. Até a próxima!");
} else {
System.out.println("Seu recorde: " + recorde + " tentativa(s). Até a próxima!");
}
}
- int recorde = 0;
- Fica fora do laço, senão seria zerado a cada partida. O 0 quer dizer "ainda não tem recorde".
- String resposta;
- Declarada antes do
do, porque a condição dowhile, lá no fim, precisa enxergá-la (escopo). - do { … } while (…);
- Roda o bloco primeiro e só depois pergunta se repete. Note o
;depois dowhile(while e do-while). - resultado > 0 && (recorde == 0 || resultado < recorde)
- "Ganhou e (é a primeira vitória ou foi melhor que o recorde)". Os parênteses são obrigatórios: sem eles, o
&&seria feito antes do||(precedência). - equalsIgnoreCase("s")
- Compara ignorando maiúsculas:
seSvalem.
A sessão completa está em "O que vamos construir", no começo da página.
Missão (etapa 6): coloque a escolha do nível e a partida dentro de um do-while que pergunta Jogar de novo? (s/n): , guarde o recorde e mostre Seu recorde: 1 tentativa(s). Até a próxima! no fim. A entrada da missão joga duas partidas no nível fácil, as duas acertadas no primeiro palpite.
import java.util.Random;
import java.util.Scanner;
public class Adivinhacao {
enum Nivel {
FACIL(10, 4),
MEDIO(50, 6),
DIFICIL(100, 7);
final int maximo;
final int tentativas;
Nivel(int maximo, int tentativas) {
this.maximo = maximo;
this.tentativas = tentativas;
}
}
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
Random sorteio = new Random(7); // semente 7: sorteia sempre o mesmo número
System.out.println("=== Jogo da Adivinhação ===");
Nivel nivel = escolherNivel(entrada);
int resultado = jogar(entrada, sorteio, nivel);
if (resultado == 0) {
System.out.println("Fica para a próxima!");
}
}
static Nivel escolherNivel(Scanner entrada) {
Nivel[] niveis = Nivel.values();
for (int i = 0; i < niveis.length; i++) {
Nivel n = niveis[i];
System.out.println((i + 1) + " = " + n + " (1 a " + n.maximo + ", " + n.tentativas + " tentativas)");
}
int escolha = lerInteiro(entrada, "Nível: ");
while (escolha < 1 || escolha > niveis.length) {
System.out.println("Escolha de 1 a " + niveis.length + ".");
escolha = lerInteiro(entrada, "Nível: ");
}
return niveis[escolha - 1];
}
static int jogar(Scanner entrada, Random sorteio, Nivel nivel) {
int secreto = sorteio.nextInt(nivel.maximo) + 1;
System.out.println("Pensei num número de 1 a " + nivel.maximo + ". Você tem " + nivel.tentativas + " tentativas.");
for (int tentativas = 1; tentativas <= nivel.tentativas; tentativas++) {
int palpite = lerInteiro(entrada, "Palpite: ");
if (palpite == secreto) {
System.out.println("Acertou em " + tentativas + " tentativa(s)!");
return tentativas;
} else if (palpite < secreto) {
System.out.println("É maior que " + palpite + ".");
} else {
System.out.println("É menor que " + palpite + ".");
}
}
System.out.println("Acabaram as tentativas. O número era " + secreto + ".");
return 0;
}
static int lerInteiro(Scanner entrada, String pergunta) {
System.out.print(pergunta);
while (!entrada.hasNextInt()) {
System.out.println("\"" + entrada.next() + "\" não é um número inteiro.");
System.out.print(pergunta);
}
return entrada.nextInt();
}
}
import java.util.Random;
import java.util.Scanner;
public class Adivinhacao {
enum Nivel {
FACIL(10, 4),
MEDIO(50, 6),
DIFICIL(100, 7);
final int maximo;
final int tentativas;
Nivel(int maximo, int tentativas) {
this.maximo = maximo;
this.tentativas = tentativas;
}
}
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
Random sorteio = new Random(7); // semente 7: sorteia sempre o mesmo número
int recorde = 0; // 0 = ainda não há recorde
System.out.println("=== Jogo da Adivinhação ===");
String resposta;
do {
Nivel nivel = escolherNivel(entrada);
int resultado = jogar(entrada, sorteio, nivel);
if (resultado > 0 && (recorde == 0 || resultado < recorde)) {
recorde = resultado;
System.out.println("Novo recorde: " + recorde + " tentativa(s)!");
}
System.out.print("Jogar de novo? (s/n): ");
resposta = entrada.next();
} while (resposta.equalsIgnoreCase("s"));
if (recorde == 0) {
System.out.println("Sem recorde desta vez. Até a próxima!");
} else {
System.out.println("Seu recorde: " + recorde + " tentativa(s). Até a próxima!");
}
}
static Nivel escolherNivel(Scanner entrada) {
Nivel[] niveis = Nivel.values();
for (int i = 0; i < niveis.length; i++) {
Nivel n = niveis[i];
System.out.println((i + 1) + " = " + n + " (1 a " + n.maximo + ", " + n.tentativas + " tentativas)");
}
int escolha = lerInteiro(entrada, "Nível: ");
while (escolha < 1 || escolha > niveis.length) {
System.out.println("Escolha de 1 a " + niveis.length + ".");
escolha = lerInteiro(entrada, "Nível: ");
}
return niveis[escolha - 1];
}
static int jogar(Scanner entrada, Random sorteio, Nivel nivel) {
int secreto = sorteio.nextInt(nivel.maximo) + 1;
System.out.println("Pensei num número de 1 a " + nivel.maximo + ". Você tem " + nivel.tentativas + " tentativas.");
for (int tentativas = 1; tentativas <= nivel.tentativas; tentativas++) {
int palpite = lerInteiro(entrada, "Palpite: ");
if (palpite == secreto) {
System.out.println("Acertou em " + tentativas + " tentativa(s)!");
return tentativas;
} else if (palpite < secreto) {
System.out.println("É maior que " + palpite + ".");
} else {
System.out.println("É menor que " + palpite + ".");
}
}
System.out.println("Acabaram as tentativas. O número era " + secreto + ".");
return 0;
}
static int lerInteiro(Scanner entrada, String pergunta) {
System.out.print(pergunta);
while (!entrada.hasNextInt()) {
System.out.println("\"" + entrada.next() + "\" não é um número inteiro.");
System.out.print(pergunta);
}
return entrada.nextInt();
}
}
O código completo
import java.util.Random;
import java.util.Scanner;
public class Adivinhacao {
enum Nivel {
FACIL(10, 4),
MEDIO(50, 6),
DIFICIL(100, 7);
final int maximo;
final int tentativas;
Nivel(int maximo, int tentativas) {
this.maximo = maximo;
this.tentativas = tentativas;
}
}
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
Random sorteio = new Random();
int recorde = 0; // 0 = ainda não há recorde
System.out.println("=== Jogo da Adivinhação ===");
String resposta;
do {
Nivel nivel = escolherNivel(entrada);
int resultado = jogar(entrada, sorteio, nivel);
if (resultado > 0 && (recorde == 0 || resultado < recorde)) {
recorde = resultado;
System.out.println("Novo recorde: " + recorde + " tentativa(s)!");
}
System.out.print("Jogar de novo? (s/n): ");
resposta = entrada.next();
} while (resposta.equalsIgnoreCase("s"));
if (recorde == 0) {
System.out.println("Sem recorde desta vez. Até a próxima!");
} else {
System.out.println("Seu recorde: " + recorde + " tentativa(s). Até a próxima!");
}
}
static Nivel escolherNivel(Scanner entrada) {
Nivel[] niveis = Nivel.values();
for (int i = 0; i < niveis.length; i++) {
Nivel n = niveis[i];
System.out.println((i + 1) + " = " + n + " (1 a " + n.maximo + ", " + n.tentativas + " tentativas)");
}
int escolha = lerInteiro(entrada, "Nível: ");
while (escolha < 1 || escolha > niveis.length) {
System.out.println("Escolha de 1 a " + niveis.length + ".");
escolha = lerInteiro(entrada, "Nível: ");
}
return niveis[escolha - 1];
}
static int jogar(Scanner entrada, Random sorteio, Nivel nivel) {
int secreto = sorteio.nextInt(nivel.maximo) + 1;
System.out.println("Pensei num número de 1 a " + nivel.maximo + ". Você tem " + nivel.tentativas + " tentativas.");
for (int tentativas = 1; tentativas <= nivel.tentativas; tentativas++) {
int palpite = lerInteiro(entrada, "Palpite: ");
if (palpite == secreto) {
System.out.println("Acertou em " + tentativas + " tentativa(s)!");
return tentativas;
} else if (palpite < secreto) {
System.out.println("É maior que " + palpite + ".");
} else {
System.out.println("É menor que " + palpite + ".");
}
}
System.out.println("Acabaram as tentativas. O número era " + secreto + ".");
return 0;
}
static int lerInteiro(Scanner entrada, String pergunta) {
System.out.print(pergunta);
while (!entrada.hasNextInt()) {
System.out.println("\"" + entrada.next() + "\" não é um número inteiro.");
System.out.print(pergunta);
}
return entrada.nextInt();
}
}
Desafios extras
- Recorde por nível. Guarde um recorde para cada nível. Dica: um array
int[] recordes = new int[Nivel.values().length]e o índicenivel.ordinal()(a posição da constante no enum). - Recorde que sobrevive. Salve o recorde num arquivo
recorde.txtao sair e leia ao começar, comFiles.writeStringeFiles.readString(Ler e Escrever Arquivos). O próximo projeto faz isso com uma lista inteira. - Dica quente/frio. Se o palpite estiver a 5 ou menos do secreto, mostre "Está quente!" (use
Math.abs(palpite - secreto), veja Math). - Palpite repetido. Avise se a pessoa repetir um palpite e não conte a tentativa.
- Inverta os papéis. Você pensa no número e o computador adivinha com busca binária, perguntando "maior, menor ou acertou?".
Desafio 3 no editor: no método jogar, depois da dica "maior/menor", mostre Está quente! quando a diferença entre o palpite e o secreto for 5 ou menos. Com a semente 7 e o nível difícil, o secreto é 37: o palpite 40 deve mostrar a mensagem.
import java.util.Random;
import java.util.Scanner;
public class Adivinhacao {
enum Nivel {
FACIL(10, 4),
MEDIO(50, 6),
DIFICIL(100, 7);
final int maximo;
final int tentativas;
Nivel(int maximo, int tentativas) {
this.maximo = maximo;
this.tentativas = tentativas;
}
}
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
Random sorteio = new Random(7); // semente 7: sorteia sempre o mesmo número
int recorde = 0; // 0 = ainda não há recorde
System.out.println("=== Jogo da Adivinhação ===");
String resposta;
do {
Nivel nivel = escolherNivel(entrada);
int resultado = jogar(entrada, sorteio, nivel);
if (resultado > 0 && (recorde == 0 || resultado < recorde)) {
recorde = resultado;
System.out.println("Novo recorde: " + recorde + " tentativa(s)!");
}
System.out.print("Jogar de novo? (s/n): ");
resposta = entrada.next();
} while (resposta.equalsIgnoreCase("s"));
if (recorde == 0) {
System.out.println("Sem recorde desta vez. Até a próxima!");
} else {
System.out.println("Seu recorde: " + recorde + " tentativa(s). Até a próxima!");
}
}
static Nivel escolherNivel(Scanner entrada) {
Nivel[] niveis = Nivel.values();
for (int i = 0; i < niveis.length; i++) {
Nivel n = niveis[i];
System.out.println((i + 1) + " = " + n + " (1 a " + n.maximo + ", " + n.tentativas + " tentativas)");
}
int escolha = lerInteiro(entrada, "Nível: ");
while (escolha < 1 || escolha > niveis.length) {
System.out.println("Escolha de 1 a " + niveis.length + ".");
escolha = lerInteiro(entrada, "Nível: ");
}
return niveis[escolha - 1];
}
static int jogar(Scanner entrada, Random sorteio, Nivel nivel) {
int secreto = sorteio.nextInt(nivel.maximo) + 1;
System.out.println("Pensei num número de 1 a " + nivel.maximo + ". Você tem " + nivel.tentativas + " tentativas.");
for (int tentativas = 1; tentativas <= nivel.tentativas; tentativas++) {
int palpite = lerInteiro(entrada, "Palpite: ");
if (palpite == secreto) {
System.out.println("Acertou em " + tentativas + " tentativa(s)!");
return tentativas;
} else if (palpite < secreto) {
System.out.println("É maior que " + palpite + ".");
} else {
System.out.println("É menor que " + palpite + ".");
}
}
System.out.println("Acabaram as tentativas. O número era " + secreto + ".");
return 0;
}
static int lerInteiro(Scanner entrada, String pergunta) {
System.out.print(pergunta);
while (!entrada.hasNextInt()) {
System.out.println("\"" + entrada.next() + "\" não é um número inteiro.");
System.out.print(pergunta);
}
return entrada.nextInt();
}
}
import java.util.Random;
import java.util.Scanner;
public class Adivinhacao {
enum Nivel {
FACIL(10, 4),
MEDIO(50, 6),
DIFICIL(100, 7);
final int maximo;
final int tentativas;
Nivel(int maximo, int tentativas) {
this.maximo = maximo;
this.tentativas = tentativas;
}
}
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
Random sorteio = new Random(7); // semente 7: sorteia sempre o mesmo número
int recorde = 0; // 0 = ainda não há recorde
System.out.println("=== Jogo da Adivinhação ===");
String resposta;
do {
Nivel nivel = escolherNivel(entrada);
int resultado = jogar(entrada, sorteio, nivel);
if (resultado > 0 && (recorde == 0 || resultado < recorde)) {
recorde = resultado;
System.out.println("Novo recorde: " + recorde + " tentativa(s)!");
}
System.out.print("Jogar de novo? (s/n): ");
resposta = entrada.next();
} while (resposta.equalsIgnoreCase("s"));
if (recorde == 0) {
System.out.println("Sem recorde desta vez. Até a próxima!");
} else {
System.out.println("Seu recorde: " + recorde + " tentativa(s). Até a próxima!");
}
}
static Nivel escolherNivel(Scanner entrada) {
Nivel[] niveis = Nivel.values();
for (int i = 0; i < niveis.length; i++) {
Nivel n = niveis[i];
System.out.println((i + 1) + " = " + n + " (1 a " + n.maximo + ", " + n.tentativas + " tentativas)");
}
int escolha = lerInteiro(entrada, "Nível: ");
while (escolha < 1 || escolha > niveis.length) {
System.out.println("Escolha de 1 a " + niveis.length + ".");
escolha = lerInteiro(entrada, "Nível: ");
}
return niveis[escolha - 1];
}
static int jogar(Scanner entrada, Random sorteio, Nivel nivel) {
int secreto = sorteio.nextInt(nivel.maximo) + 1;
System.out.println("Pensei num número de 1 a " + nivel.maximo + ". Você tem " + nivel.tentativas + " tentativas.");
for (int tentativas = 1; tentativas <= nivel.tentativas; tentativas++) {
int palpite = lerInteiro(entrada, "Palpite: ");
if (palpite == secreto) {
System.out.println("Acertou em " + tentativas + " tentativa(s)!");
return tentativas;
} else if (palpite < secreto) {
System.out.println("É maior que " + palpite + ".");
} else {
System.out.println("É menor que " + palpite + ".");
}
if (Math.abs(palpite - secreto) <= 5) {
System.out.println("Está quente!");
}
}
System.out.println("Acabaram as tentativas. O número era " + secreto + ".");
return 0;
}
static int lerInteiro(Scanner entrada, String pergunta) {
System.out.print(pergunta);
while (!entrada.hasNextInt()) {
System.out.println("\"" + entrada.next() + "\" não é um número inteiro.");
System.out.print(pergunta);
}
return entrada.nextInt();
}
}
Exercícios
1. Quais valores sorteio.nextInt(10) pode devolver?
2. Por que o jogo usa do-while para "Jogar de novo?" e não while?
3. O que Nivel.values() devolve?
4. Com a mesma semente, new Random(7) sorteia…
Complete para sortear um número de 1 a 50:
Resumo
nextInt(n)sorteia de 0 a n-1; some 1 para começar em 1. Uma semente fixa repete a sequência.whilerepete enquanto a condição for verdadeira; um contador com++conta as voltas.- Constantes
static finaldão nome aos números mágicos. hasNextInt()valida a entrada; um método que devolve "tentativas ou 0" informa vitória e derrota.- Um
enumpode ter atributos e construtor;values()lista as constantes. do-whileroda pelo menos uma vez: perfeito para "jogar de novo?".
Próximo projeto: Agenda de Contatos, com records, listas e arquivos.