Todas as atividades
Jogo e Combinação

Caça-Palavras

Grade de letras onde o aprendiz localiza palavras ocultas em qualquer direção. Reforça a forma escrita de termos técnicos e serve como atividade de revisão lúdica.

Conhecimento caça-palavras palavras grid word search

Experimente

Encontre os termos do oceano

Descubra a resposta de cada pista e localize a palavra na grade.

1.

Maior mamífero marinho do planeta, conhecido pelo canto que viaja quilômetros debaixo d'água.

2.

Molusco de oito tentáculos e inteligência notável, capaz de mudar de cor para se camuflar.

3.

Organismo marinho que forma recifes coloridos, abrigando grande parte da vida no oceano.

4.

Planta marinha simples, sem raízes verdadeiras, que produz boa parte do oxigênio do planeta.

5.

Corpo de água salgada que cobre a maior parte da superfície da Terra.

Código-fonte

PHP

Dados de exemplo

Cada pista tem uma pergunta e a resposta certa — a palavra em si nunca aparece na tela, só a grade e a pergunta.

1 <?php
2 $grade = [
3 ['P','I','A','N','O'],
4 ['T','E','S','B','H'],
5 ['U','R','M','C','A'],
6 ['B','G','K','F','R'],
7 ['A','L','W','N','P'],
8 ['Q','Z','Y','D','A'],
9 ];
10 $pistas = [
11 ['id' => 'p1', 'pergunta' => 'Instrumento de teclas brancas e pretas, presente em orquestras e salas de estar.', 'resposta' => 'PIANO'],
12 ['id' => 'p2', 'pergunta' => 'Instrumento de sopro grave, o maior da família dos metais.', 'resposta' => 'TUBA'],
13 ['id' => 'p3', 'pergunta' => 'Instrumento de cordas triangular, tocado com os dedos, símbolo clássico de anjos.', 'resposta' => 'HARPA'],
14 ];
15 ?>

Estrutura da questão

A grade vem primeiro; as pistas ficam abaixo dela, sem revelar a palavra — só quem souber a resposta consegue procurar a sequência certa.

1 <div class="questao" data-tipo="caca-palavras">
2
3 <div class="grade" style="grid-template-columns: repeat(<?= count($grade[0]) ?>, 40px);">
4 <?php foreach ($grade as $r => $linha): foreach ($linha as $c => $letra): ?>
5 <button type="button" class="celula" data-row="<?= $r ?>" data-col="<?= $c ?>" data-letra="<?= $letra ?>"><?= $letra ?></button>
6 <?php endforeach; endforeach; ?>
7 </div>
8
9 <p class="questao-instrucao">Descubra a resposta de cada pista e localize a palavra na grade.</p>
10
11 <div class="pistas">
12 <?php foreach ($pistas as $i => $pista): ?>
13 <div class="pista" data-resposta="<?= $pista['resposta'] ?>">
14 <p class="pista-numero"><?= $i + 1 ?>.</p>
15 <p class="pista-pergunta"><?= htmlspecialchars($pista['pergunta']) ?></p>
16 <p class="pista-resposta" hidden>Resposta: <?= $pista['resposta'] ?></p>
17 </div>
18 <?php endforeach; ?>
19 </div>

Ações da questão

Verificar, o painel de resultado e o botão de reiniciar — os dois últimos nascem ocultos.

1 <button type="button" class="questao-verificar">Verificar resposta</button>
2
3 <div class="questao-painel" hidden>
4 <p class="questao-painel-mensagem"></p>
5 </div>
6
7 <button type="button" class="questao-reset" hidden>Tentar novamente</button>
8
9 </div>
CSS

Grade

Centralizada com flexbox, largura própria por causa das colunas dinâmicas.

1 .questao {
2 display: flex;
3 flex-direction: column;
4 align-items: center;
5 }
6 .grade {
7 display: inline-grid;
8 gap: 2px;
9 margin-bottom: 16px;
10 }

Célula — estados

Cada estado troca o par cor-de-fundo/cor-de-texto inteiro, nunca só adiciona uma cor nova por cima da anterior. Uma célula só tem uma classe de estado por vez — trocar em vez de empilhar evita que a cor antiga permaneça visível por trás da nova.

1 .celula {
2 width: 40px;
3 height: 40px;
4 border: 1px solid #cbd5e1;
5 border-radius: 6px;
6 font-weight: 700;
7 font-size: 16px;
8 text-transform: uppercase;
9 cursor: pointer;
10 background: #f1f5f9;
11 color: #475569;
12 }
13 .celula:hover {
14 background: #e0e7ff;
15 color: #4338ca;
16 }
17 .celula.selecionada {
18 background: #c7d2fe;
19 color: #3730a3;
20 }
21 .celula.encontrada {
22 background: #bbf7d0;
23 color: #15803d;
24 }
25 .celula.revelada {
26 background: #fde68a;
27 color: #92400e;
28 }

Pistas

A pergunta fica visível desde o início; a resposta nasce oculta e só some o "hidden" quando a palavra é achada ou a atividade é verificada.

1 .questao-instrucao {
2 margin: 0 0 12px;
3 font-size: 13px;
4 color: #64748b;
5 }
6 .pistas {
7 width: 100%;
8 display: flex;
9 flex-direction: column;
10 gap: 8px;
11 margin-bottom: 16px;
12 }
13 .pista {
14 padding: 12px;
15 border: 1px solid #cbd5e1;
16 border-radius: 10px;
17 background: #f8fafc;
18 }
19 .pista-numero {
20 margin: 0 0 4px;
21 font-size: 12px;
22 font-weight: 700;
23 color: #4f46e5;
24 }
25 .pista-pergunta {
26 margin: 0;
27 font-size: 14px;
28 color: #475569;
29 }
30 .pista-resposta {
31 margin: 8px 0 0;
32 font-size: 14px;
33 font-weight: 600;
34 color: #059669;
35 }
36 .pista-resposta[hidden] {
37 display: none;
38 }

Ações

Botões de largura total, um de cada vez na tela.

1 .questao-verificar,
2 .questao-reset {
3 display: block;
4 width: 100%;
5 padding: 12px 16px;
6 border: none;
7 border-radius: 10px;
8 font: inherit;
9 font-weight: 600;
10 cursor: pointer;
11 }
12 .questao-verificar {
13 background: #4f46e5;
14 color: #fff;
15 }
16 .questao-reset {
17 background: #e5e7eb;
18 color: #1f2937;
19 }

Estado oculto

O atributo hidden nativo tem a mesma especificidade da regra de exibição acima — sem isto, "Tentar novamente" apareceria antes de verificar.

1 .questao-verificar[hidden],
2 .questao-reset[hidden] {
3 display: none;
4 }

Painel de resultado

Caixa de destaque com o resultado da verificação.

1 .questao-painel {
2 width: 100%;
3 margin: 16px 0;
4 padding: 16px;
5 border-radius: 12px;
6 background: #1e3a8a;
7 color: #dbeafe;
8 font-weight: 600;
9 box-sizing: border-box;
10 }
JavaScript

Encontrar os elementos da questão

Localiza a grade, as pistas e as ações.

1 document.addEventListener('DOMContentLoaded', function () {
2 document.querySelectorAll('.questao[data-tipo="caca-palavras"]').forEach(function (questao) {
3 var pistas = questao.querySelectorAll('.pista');
4 var total = pistas.length;
5 var encontradas = 0;
6 var selecionadas = [];
7 var verificar = questao.querySelector('.questao-verificar');
8 var painel = questao.querySelector('.questao-painel');
9 var mensagem = painel.querySelector('.questao-painel-mensagem');
10 var reset = questao.querySelector('.questao-reset');
11 var bloqueada = false;

Trocar o estado de uma célula

Cada célula tem só uma classe de estado por vez — sempre remove as outras antes de adicionar a nova, nunca empilha uma cor em cima da anterior.

1 var ESTADOS = ['selecionada', 'encontrada', 'revelada'];
2 function marcar(celula, estado) {
3 celula.classList.remove.apply(celula.classList, ESTADOS);
4 if (estado) celula.classList.add(estado);
5 }

Localizar uma palavra na grade

Varre a grade em 4 direções (cima, baixo, esquerda, direita) — a grade só posiciona palavras em linha reta, nunca na diagonal.

1 function localizar(palavra) {
2 var celulas = Array.prototype.slice.call(questao.querySelectorAll('.celula'));
3 var mapa = {};
4 celulas.forEach(function (c) { mapa[c.dataset.row + ':' + c.dataset.col] = c; });
5 var direcoes = [[-1,0],[0,-1],[0,1],[1,0]];
6 palavra = palavra.toUpperCase();
7 for (var i = 0; i < celulas.length; i++) {
8 for (var d = 0; d < direcoes.length; d++) {
9 var caminho = [];
10 for (var k = 0; k < palavra.length; k++) {
11 var chave = (parseInt(celulas[i].dataset.row) + direcoes[d][0] * k) + ':' + (parseInt(celulas[i].dataset.col) + direcoes[d][1] * k);
12 var atual = mapa[chave];
13 if (!atual || atual.dataset.letra.toUpperCase() !== palavra[k]) { caminho = []; break; }
14 caminho.push(atual);
15 }
16 if (caminho.length === palavra.length) return caminho;
17 }
18 }
19 return [];
20 }

Verificar

Trava a grade e revela a resposta (e a localização) de toda pista que ainda não tinha sido achada — funciona tanto clicado manualmente quanto ao completar tudo sozinho.

1 function concluir() {
2 mensagem.textContent = encontradas === total
3 ? 'Todas as palavras encontradas!'
4 : encontradas + '/' + total + ' palavras encontradas.';
5 painel.hidden = false;
6
7 pistas.forEach(function (pista) {
8 if (pista.dataset.encontrada === 'true') return;
9 pista.dataset.encontrada = 'false';
10 pista.querySelector('.pista-resposta').hidden = false;
11 localizar(pista.dataset.resposta).forEach(function (celula) { marcar(celula, 'revelada'); });
12 });
13
14 questao.querySelectorAll('.celula').forEach(function (c) { c.disabled = true; });
15 bloqueada = true;
16 verificar.hidden = true;
17 reset.hidden = false;
18 }

Clicar numa letra

Cada clique entra ou sai da seleção atual; a sequência selecionada é comparada com a resposta de cada pista a cada clique.

1 questao.querySelectorAll('.celula').forEach(function (celula) {
2 celula.addEventListener('click', function () {
3 if (bloqueada || celula.disabled) return;
4 var idx = selecionadas.indexOf(celula);
5 if (idx >= 0) { selecionadas.splice(idx, 1); marcar(celula, null); }
6 else { selecionadas.push(celula); marcar(celula, 'selecionada'); }
7
8 var sequencia = selecionadas.map(function (c) { return c.dataset.letra; }).join('').toUpperCase();
9 pistas.forEach(function (pista) {
10 if (pista.dataset.encontrada === 'true' || sequencia !== pista.dataset.resposta) return;
11 pista.dataset.encontrada = 'true';
12 pista.querySelector('.pista-resposta').hidden = false;
13 encontradas++;
14 selecionadas.forEach(function (c) { marcar(c, 'encontrada'); c.disabled = true; });
15 selecionadas = [];
16 if (encontradas === total) concluir();
17 });
18 });
19 });
20
21 verificar.addEventListener('click', concluir);

Reiniciar

Devolve a grade e as pistas ao estado inicial.

1 reset.addEventListener('click', function () {
2 bloqueada = false;
3 selecionadas = [];
4 encontradas = 0;
5 questao.querySelectorAll('.celula').forEach(function (c) { c.disabled = false; marcar(c, null); });
6 pistas.forEach(function (pista) {
7 delete pista.dataset.encontrada;
8 pista.querySelector('.pista-resposta').hidden = true;
9 });
10 painel.hidden = true;
11 verificar.hidden = false;
12 reset.hidden = true;
13 });