📌 Como funciona
Cada exercício integra todos os tópicos estudados: classes JavaScript (herança com
extends), simulação de interfaces, tratamento de erros com try/catch, persistência com localStorage, HTML5 semântico, manipulação do DOM, querySelector, innerHTML e eventos. Clique no card para ver o enunciado. Marque com ✓ os 4 que seu grupo escolheu.
🏗️ Classes e Herança JS
🔌 Simulação de Interfaces
⚠️ try/catch e Erros
💾 localStorage
🌐 DOM, eventos e innerHTML
1
🧙
O Grimório dos Heróis
Sistema de personagens para um RPG de texto em JS
✓
▼
🗺️ Contexto
O reino de Algorithmia está ameaçado por bugs ancestrais. Você foi convocado para criar o Grimório dos Heróis — um sistema que registra e exibe os guerreiros que defenderão o reino. Cada herói tem habilidades únicas, e o sistema precisa ser robusto o suficiente para sobreviver a entradas inválidas dos recrutas desastrados.
⚙️ Parte JavaScript — O Motor do Grimório
-
>Crie a classe
Heroi com os atributos nome, nivel e pontosDeVida. No construtor, se nome estiver vazio, lance um Error com mensagem adequada. Adicione o método getStatus() que retorna uma string formatada com os dados do herói.
>Crie as subclasses Mago (tem mana; método atacar() consome 10 de mana — se não tiver, lança Error), Guerreiro (tem forca; atacar() retorna dano baseado na força) e Arqueiro (tem flechas; atacar() só funciona se flechas > 0).
>Simule uma "interface" Combatente: crie uma função verificarCombatente(obj) que recebe um objeto e verifica se ele possui os métodos atacar() e getStatus(). Se não possuir, lança um Error informando qual método está faltando.
>Crie o objeto grimorio (não precisa ser classe) com os métodos:—
adicionarHeroi(heroi): usa verificarCombatente() antes de adicionar—
salvar(): serializa o array de heróis com JSON.stringify e salva no localStorage—
carregar(): lê do localStorage, faz JSON.parse e reconstrói os objetos—
buscarPorNome(nome): retorna o herói ou lança Error se não encontrar
🌐 Parte HTML + DOM
-
>Crie um formulário com campos: nome, tipo (select: Mago/Guerreiro/Arqueiro) e nível. Ao submeter (evento
submit com preventDefault()), instancie o herói correto e chame grimorio.adicionarHeroi() dentro de um try/catch.
>Exiba cada herói cadastrado como um card gerado com innerHTML. O card deve mostrar nome, tipo, nível e status — com cor diferente por tipo (azul = Mago, vermelho = Guerreiro, verde = Arqueiro).
>Cada card deve ter um botão "⚔️ Atacar" que chama atacar() dentro de um try/catch e exibe o resultado (ou o erro) em um parágrafo abaixo do card, sem usar alert().
>Adicione os botões "💾 Salvar Grimório" e "📂 Carregar Grimório" que chamam grimorio.salvar() e grimorio.carregar() e atualizam a lista de cards na tela.
💡 Dica
Ao carregar do
localStorage, os dados vêm como objetos planos — sem os métodos das classes. Você precisa recriar as instâncias com new Mago(...), new Guerreiro(...) etc., usando o campo tipo salvo no JSON para saber qual classe usar.
class Heroi { constructor(nome, nivel, pontosDeVida) { if (!nome) throw new Error("Nome não pode ser vazio!"); this.nome = nome; this.nivel = nivel; this.pontosDeVida = pontosDeVida; this.tipo = "Heroi"; // será sobrescrito nas subclasses } getStatus() { return `${this.nome} | Nível ${this.nivel} | HP: ${this.pontosDeVida}`; } } class Mago extends Heroi { constructor(nome, nivel, pontosDeVida, mana) { super(nome, nivel, pontosDeVida); this.mana = mana; this.tipo = "Mago"; } atacar() { if (this.mana <= 0) throw new Error(`${this.nome} não tem mana!`); this.mana -= 10; return `${this.nome} lança bola de fogo! Mana: ${this.mana}`; } }
📁 Entrega
Um único arquivo
grimorio.html com todo o JavaScript no <script> e o HTML na mesma página. Teste com ao menos 3 heróis de tipos diferentes, salvando e recarregando do localStorage.
2
🎬
CinemaCode — Plataforma de Streaming
Catálogo de mídias com busca e filtro em tempo real
✓
▼
🎥 Contexto
A startup CinemaCode quer lançar uma plataforma de streaming, mas o desenvolvedor principal fugiu para as montanhas com um laptop. Você herdou o projeto pela metade e precisa terminar o catálogo, a busca e os controles de reprodução — antes que os investidores percebam.
⚙️ Parte JavaScript
-
>Crie a classe
Midia com titulo, ano e genero. Se o ano for anterior a 1888 (primeiro filme da história), lance um Error. Adicione o método getInfo() retornando uma string formatada.
>Crie as subclasses Filme (adiciona diretor e duracao em minutos), Serie (adiciona temporadas e episodiosPorTemporada — getInfo() calcula o total de episódios) e Documentario (adiciona tema).
>Simule uma interface Reproducivel: crie a função verificarReproducivel(obj) que confere se o objeto tem os métodos play(), pause() e getInfo(). Adicione esses métodos em Midia — play() muda o estado reproduzindo para true, pause() para false.
>Crie o objeto catalogo com:—
adicionar(midia): usa verificarReproducivel() e adiciona à lista—
salvar() e carregar(): persistência com localStorage—
filtrarPorGenero(genero): retorna array filtrado—
buscarPorTitulo(texto): retorna mídias cujo título contenha o texto (case insensitive)
🌐 Parte HTML + DOM
-
>Crie um formulário para cadastrar mídia (título, tipo, ano, gênero e campo extra conforme o tipo). Ao submeter, instancie a classe correta dentro de um
try/catch e adicione ao catálogo.
>Exiba as mídias em cards. Cada card deve ter botões "▶ Play" e "⏸ Pause" que alteram visualmente o card (cor de fundo, texto de status) via manipulação de classe CSS com classList.
>Adicione um campo de busca: ao digitar (evento input), filtre os cards em tempo real usando buscarPorTitulo() — oculte os que não batem com style.display = 'none'.
>Exiba um contador "X títulos encontrados" atualizado a cada busca com textContent.
💡 Dica de filtro em tempo real
Use o evento
input no campo de busca (não keyup). Ele dispara para qualquer mudança, incluindo colar texto. Percorra todos os cards com querySelectorAll e compare o texto do título com includes().
📁 Entrega
Arquivo único
cinemacode.html. Pré-cadastre ao menos 5 mídias de tipos diferentes no localStorage para demonstrar a busca funcionando.
3
🚀
Banco Intergaláctico S.A.
Sistema bancário para colônias espaciais
✓
▼
🌌 Contexto
O Banco Intergaláctico S.A. opera em 7 colônias espaciais e aceita pagamentos em créditos galácticos. O sistema antigo foi destruído por uma tempestade de meteoros. Você tem até o nascer de Kepler-442b para entregar o novo sistema — ou os colonos ficam sem acesso às suas contas.
⚙️ Parte JavaScript
-
>Crie a classe
Conta com titular, numero e saldo. No construtor, valide que o saldo inicial não é negativo — se for, lance um Error. Mantenha um array historico de strings para registrar cada transação.
>Adicione os métodos depositar(valor) e sacar(valor) na classe Conta. Lance Error para valor zero ou negativo em qualquer operação, e para saldo insuficiente no saque. Cada operação bem-sucedida deve adicionar uma entrada ao historico.
>Crie as subclasses:—
ContaCorrente: tem limiteCredito; pode sacar além do saldo até o limite (saldo pode ficar negativo até -limiteCredito)—
ContaPoupanca: tem taxaJuros; adicione o método aplicarJuros() que aumenta o saldo pela taxa e registra no histórico—
ContaGalactica: herda de ContaCorrente; tem taxaCambio (padrão 3.7); adicione depositarCreditos(creditos) que converte e deposita em reais
>Simule a interface Transacionavel: crie verificarTransacionavel(obj) que confere se o objeto tem depositar, sacar e getExtrato. Implemente getExtrato() em Conta retornando o array historico formatado.
>Crie o objeto banco com:—
abrirConta(conta): valida com verificarTransacionavel()—
buscarConta(numero): lança Error se não encontrar—
transferir(origem, destino, valor): usa buscarConta() nos dois números, faz saque e depósito dentro de um try/catch—
salvar() e carregar(): persistência com localStorage
🌐 Parte HTML + DOM
-
>Crie uma interface com três abas (Contas, Operações, Extrato) alternadas por eventos de clique que mostram/ocultam seções com
style.display.
>Na aba Contas: formulário para abrir conta (titular, número, tipo, saldo inicial) com feedback de erro inline via innerHTML.
>Na aba Operações: campos para número da conta e valor, com botões "Depositar", "Sacar" e "Transferir". Resultados exibidos em um painel de log gerado com innerHTML. Linhas de erro em vermelho, sucesso em verde.
>Na aba Extrato: campo para digitar o número da conta e botão "Ver Extrato" que gera uma tabela dinamicamente com innerHTML, mostrando cada transação do histórico.
⚠️ Atenção
Ao carregar contas do
localStorage, reconstrua as instâncias corretas com base no campo tipo salvo — os métodos das classes são perdidos na serialização JSON.
📁 Entrega
Arquivo único
banco-galactico.html. Demonstre ao menos 4 contas de tipos diferentes, uma transferência e a visualização do extrato.
4
🤖
Hospital dos Robôs
Sistema de triagem e prontuário para androides
✓
▼
🏥 Contexto
No ano 2157, robôs também adoecem. O Hospital dos Robôs de Nova Curitiba atende androides com superaquecimento, falha de memória e corrosão de articulações. Você foi contratado para desenvolver o sistema de triagem e prontuário eletrônico antes que a fila de robôs enferrujados tome conta do corredor.
⚙️ Parte JavaScript
-
>Crie a classe
Robo com id, modelo, fabricante e anoFabricacao. No construtor, valide que modelo tem ao menos 3 caracteres — caso contrário, lance um Error.
>Adicione o método diagnosticar() na classe base retornando uma string genérica. Crie as subclasses:—
AndroideServico: diagnosticar() verifica se anoFabricacao < 2140 e retorna aviso de superaquecimento; calcularCusto() retorna R$500—
RoboIndustrial: tem articulacoesDanificadas; calcularCusto() retorna 200 × articulacoesDanificadas—
RoboMedico: calcularCusto() sempre retorna R$1200; diagnosticar() sempre retorna urgência crítica
>Simule a interface Diagnosticavel com a função verificarDiagnosticavel(obj) que confere se o objeto possui diagnosticar() e calcularCusto().
>Crie o objeto hospital com:—
admitir(robo): valida com verificarDiagnosticavel()—
buscarPorId(id): lança Error se não encontrar—
realizarTriagem(): retorna array com { robo, diagnostico, custo } de cada paciente—
salvar() e carregar(): usa localStorage
🌐 Parte HTML + DOM
-
>Crie um formulário de admissão (id, modelo, fabricante, tipo, ano). Ao submeter, instancie o robô correto dentro de
try/catch e exiba um card de prontuário gerado com innerHTML.
>A cor do card deve refletir a urgência: vermelho (RoboMedico), amarelo (AndroideServico), verde (RoboIndustrial) — aplique via classList.add.
>Adicione um campo de busca por ID: ao digitar (evento input), destaque o card correspondente com borda azul e role até ele com scrollIntoView().
>Adicione evento de duplo clique (dblclick) em cada card para marcar como "Alta" — o card fica cinza com texto riscado (use classList.toggle).
💡 Dica
Para o
scrollIntoView(), primeiro remova a classe de destaque de todos os cards com querySelectorAll + forEach, depois adicione só no card encontrado. Assim apenas um card fica destacado por vez.
📁 Entrega
Arquivo único
hospital-robos.html. Demonstre admissão de ao menos 5 robôs de tipos variados, busca por ID e marcação de alta com duplo clique.
5
🪄
Escola de Magia Algorithmia
Boletim mágico com cálculo de média e situação
✓
▼
🏰 Contexto
A Escola de Magia Algorithmia tem um problemão: o livro de registros foi transformado em sapo por um aluno descuidado. Agora você precisa criar um sistema digital para gerenciar os estudantes, suas notas em Feitiçaria Básica, Poções e Transfiguração, e emitir o boletim mágico antes da festa de formatura.
⚙️ Parte JavaScript
-
>Crie a classe
Estudante com nome, matricula e um objeto notas no formato { feiticaria: 0, pocoes: 0, transfiguracao: 0 }.
>Adicione o método lancarNota(disciplina, valor): valide que valor está entre 0 e 10 (lance Error se não estiver) e que a disciplina existe no objeto notas (lance Error diferente se não existir).
>Adicione calcularMedia() que retorna a média das três notas. Crie as subclasses:—
EstudanteBolsista: getSituacao() retorna "Aprovado" se média ≥ 7.0, "Recuperação" se ≥ 5.0, "Reprovado" se abaixo—
EstudanteRegular: getSituacao() retorna "Aprovado" se média ≥ 6.0, "Recuperação" se ≥ 4.0, "Reprovado" se abaixo
>Simule a interface Avaliavel com verificarAvaliavel(obj) que confere se o objeto tem calcularMedia() e getSituacao().
>Crie o objeto secretaria com:—
matricular(estudante): valida com verificarAvaliavel()—
buscarPorMatricula(matricula): lança Error se não encontrar—
gerarRanking(): retorna o array de estudantes ordenado por média decrescente usando sort()—
salvar() e carregar(): persistência com localStorage, reconstruindo instâncias pelo campo tipo
🌐 Parte HTML + DOM
-
>Crie um formulário com nome, matrícula, tipo (Bolsista/Regular) e os três campos de nota. Ao submeter com
preventDefault(), instancie o estudante correto e lance as notas dentro de try/catch.
>Exiba o boletim de cada estudante como um card gerado com innerHTML. O card deve mostrar nome, as três notas, média e situação. Use cores para a situação: verde (Aprovado), amarelo (Recuperação), vermelho (Reprovado) via classList.add.
>Adicione um botão "🏆 Ver Ranking" que ordena os cards na tela pela média, do maior para o menor, reordenando os elementos no DOM sem recarregar a página.
>Valide os campos de nota em tempo real com evento input: se o valor digitado estiver fora de 0–10, exiba uma mensagem de erro vermelha abaixo do campo usando querySelector e textContent.
💡 Dica para reordenar no DOM
Para reordenar os cards visualmente, selecione o container pai com
querySelector, converta os filhos em array com Array.from(), ordene com sort() e reinsira cada elemento com appendChild(). O DOM atualiza automaticamente.
📁 Entrega
Arquivo único
escola-magia.html. Demonstre ao menos 6 estudantes (3 bolsistas, 3 regulares) com notas variadas, e mostre o ranking funcionando.
6
🦁
Zoológico de Criaturas Impossíveis
Gerenciador de espécies que não deveriam existir
✓
▼
🌿 Contexto
O Zoológico Digital de Criaturas Impossíveis abriga seres fantásticos: Dragões que espirram HTML, Unicórnios que depuram código e Fênix que reiniciam o sistema quando tudo dá errado. O zelador foi transformado em variável local (saiu de escopo) e você precisa assumir o controle do sistema de alimentação e exibição das criaturas.
⚙️ Parte JavaScript
-
>Crie a classe
Criatura com nome, especie e nivelFome (0 a 10). Adicione o método alimentar(comida) que reduz o nível de fome em 3 (mínimo 0) e retorna uma mensagem. Se nivelFome já for 0, lance um Error informando que a criatura está saciada.
>Crie as subclasses:—
Dragao: alimentar(comida) verifica se comida === "código compilado" — qualquer outra coisa lança Error com mensagem criativa—
Unicornio: aceita qualquer comida, mas se não for "arco-íris", o nível de fome só reduz 1 em vez de 3—
Fenix: ao ser alimentada com nivelFome === 0 lança Error "A Fênix renasceu e resetou tudo!" e zera todos os atributos para os valores iniciais
>Simule a interface Alimentavel com verificarAlimentavel(obj) que confere se o objeto tem alimentar() e getNivelFome(). Adicione getNivelFome() em Criatura retornando this.nivelFome.
>Crie o objeto zoologico com:—
adicionar(criatura): valida com verificarAlimentavel()—
alimentarTodas(comida): tenta alimentar cada criatura em um try/catch individual, registrando sucessos e erros separadamente—
listarFamintas(): retorna criaturas com nivelFome > 7—
salvar() e carregar(): usa localStorage
🌐 Parte HTML + DOM
-
>Exiba um card fixo para cada criatura (Dragão, Unicórnio e Fênix) com uma barra de fome visual — um
<div> cuja largura em % representa o nível de fome (nivelFome × 10 + "%"), atualizada via style.width.
>Adicione um campo "O que servir?" e botões "Alimentar Todas" e "Alimentar Individualmente". Ao alimentar, atualize as barras e exiba o resultado de cada criatura em um log com innerHTML — erros em vermelho, sucessos em verde.
>Adicione evento mouseover em cada card para exibir uma curiosidade sobre a criatura em um tooltip posicionado com CSS, criado e removido via innerHTML.
>Use querySelector para atualizar o título da seção "🚨 Criaturas com fome crítica: X" sempre que uma alimentação ocorrer.
⚠️ Atenção
O
alimentarTodas() não deve parar se uma criatura lançar erro — use try/catch dentro do forEach para que cada criatura seja tratada independentemente.
📁 Entrega
Arquivo único
zoologico.html. Demonstre a alimentação com comida errada para o Dragão (erro), certa para o Unicórnio (sucesso parcial) e o renascimento da Fênix.
7
🛸
Agência Espacial BugFree
Gerenciamento de missões e tripulação interestelar
✓
▼
🌠 Contexto
A Agência Espacial BugFree planeja colonizar o planeta Kotlin-9, mas o sistema de gerenciamento de missões foi escrito em COBOL por um estagiário em 1974. Você tem 3 aulas para reescrever tudo antes do lançamento. A tripulação está na sala ao lado, nervosa, comendo chips e esperando o sistema funcionar.
⚙️ Parte JavaScript
-
>Crie a classe
Astronauta com nome, codigoCracha e nivelExperiencia (1–5). Valide no construtor que o nível está nesse intervalo — lance Error caso contrário. Adicione executarFuncao() retornando uma string genérica.
>Crie as subclasses:—
Piloto: executarFuncao() retorna uma manobra calculada pelo nível de experiência—
Cientista: tem array experimentos; executarFuncao() retorna o próximo experimento da fila com shift() — se vazio, lança Error "Sem experimentos na fila!"—
Engenheiro: tem sistemaResponsavel; executarFuncao() tem 30% de chance de lançar Error "Falha no sistema: " + sistemaResponsavel (use Math.random())
>Simule a interface Tripulante com verificarTripulante(obj) que confere se tem executarFuncao() e nome.
>Crie a classe Missao com nome, destino, duracaoDias e array tripulacao. Implemente:—
adicionarTripulante(astronauta): valida com verificarTripulante() e lança Error se já houver 7 membros—
iniciar(): chama executarFuncao() de cada membro em try/catch individual, retorna array de logs—
salvar() e carregar(): usa localStorage
🌐 Parte HTML + DOM
-
>Crie um painel de missão: um formulário para adicionar tripulantes (nome, crachá, tipo, nível) e uma lista gerada com
innerHTML exibindo cada membro.
>Destaque automaticamente com fundo amarelo todos os tripulantes do tipo Engenheiro usando querySelectorAll após cada adição.
>Adicione um botão "🚀 Iniciar Missão" que chama missao.iniciar() e exibe o log de cada tripulante em um painel — erros em vermelho, sucessos em verde.
>Implemente um contador regressivo de lançamento usando setInterval: ao clicar em "🚀 Iniciar Missão", inicie uma contagem regressiva de 10 segundos exibida na tela com textContent. Ao chegar a zero, limpe o intervalo com clearInterval, mude o fundo da página para #0f172a e exiba "🚀 Missão iniciada! Boa viagem, tripulação!" com innerHTML.
💡 Dica sobre setInterval
Guarde o retorno do
setInterval em uma variável: const timer = setInterval(fn, 1000). Quando o contador chegar a zero, chame clearInterval(timer) para parar. Sem isso, o intervalo continua rodando para sempre mesmo após o zero.
📁 Entrega
Arquivo único
agencia-espacial.html. Demonstre uma missão com ao menos 5 tripulantes de tipos variados, incluindo um Engenheiro que falha sem abortar o restante da tripulação.
8
🏆
Torneio de IAs — Quem Programa Melhor?
Campeonato entre inteligências artificiais amadoras
✓
▼
🤖 Contexto
Todo ano, a universidade de Compilópolis realiza o grande Torneio de IAs: sistemas de inteligência artificial amadora competem entre si para ver qual resolve mais desafios sem entrar em loop infinito. Você foi designado para criar o sistema de inscrição, pontuação e placar — e ele precisa tratar todos os erros possíveis, porque IAs amadoras são completamente imprevisíveis.
⚙️ Parte JavaScript
-
>Crie a classe
InteligenciaArtificial com nome, versao e pontuacao (inicia em 0). Valide no construtor que nome não está vazio. Adicione resolver(desafio) e getNome().
>Crie as subclasses:—
IAOtimista: resolver() tenta sempre, mas com 40% de chance lança Error("Loop infinito detectado! Reiniciando...")—
IAPessimista: resolver() só aceita desafios com menos de 20 caracteres — senão lança Error("Desafio complexo demais. Entrando em modo pânico.")—
IAEquilibrada: resolver() sempre funciona, mas usa multiplicador = 0.5 na pontuação
>Simule a interface Competidor com verificarCompetidor(obj) que confere se o objeto tem resolver(), getNome() e a propriedade pontuacao.
>Crie o objeto torneio com:—
inscrever(ia): valida com verificarCompetidor() e lança Error se o nome já estiver inscrito—
executarRodada(desafio, pontosPorAcerto): chama resolver() de cada IA em try/catch individual — quem resolver ganha os pontos multiplicados pelo multiplicador da IA (padrão 1)—
getPlacar(): retorna o array ordenado por pontuação decrescente com sort()—
salvar() e carregar(): usa localStorage, reconstruindo instâncias pelo campo tipo
🌐 Parte HTML + DOM
-
>Crie uma tabela de placar gerada com
innerHTML: posição, nome, versão, tipo e pontuação. A linha do líder tem fundo dourado (#fef9c3) e emoji 🏆 antes do nome, aplicado via classList.
>Adicione campo "Desafio da rodada" e botão "▶ Executar Rodada". Ao clicar, chame torneio.executarRodada() e atualize a tabela completamente com innerHTML, reordenando pelo placar.
>Exiba um log da última rodada abaixo da tabela: ✅ resolveu / ❌ falhou + mensagem do erro, com cores diferentes via innerHTML.
>Formulário para inscrever nova IA (nome, versão, tipo) com validação inline: se o nome já existir, exiba erro com textContent sem usar alert().
💡 Dica de ordenação
Para ordenar o placar use:
ias.sort((a, b) => b.pontuacao - a.pontuacao). Valores negativos indicam que b vem antes de a. Compare essa abordagem com a reordenação de cards do DOM do Exercício 5 — é o mesmo conceito em contextos diferentes.
📁 Entrega
Arquivo único
torneio-ia.html. Demonstre ao menos 4 IAs de tipos diferentes, 3 rodadas com desafios variados (um curto para a IAPessimista funcionar, um longo para ela falhar) e placar final salvo no localStorage.