Palavras Cruzadas
Grade com palavras ocultas que o aprendiz descobre a partir de dicas. Reforça vocabulário técnico de forma lúdica, combinando raciocínio e memorização.
Experimente
Vocabulário de Design Instrucional
1. HORIZONTAL
Modelo clássico de DI: Análise, Design, Desenvolvimento, Implementação, Avaliação
2. VERTICAL
Modelo de motivação de Keller: Atenção, Relevância, Confiança, Satisfação
3. HORIZONTAL
Sistema de gerenciamento de aprendizagem (sigla em inglês)
Código-fonte
Dados de exemplo
Cada palavra tem posição (linha/coluna), direção e uma dica. Palavras que se cruzam precisam compartilhar a mesma letra na célula onde se tocam — ADDIE e ARCS dividem o "A", ARCS e LMS dividem o "S".
| 1 |
<?php
|
| 2 |
$palavras = [
|
| 3 |
['palavra' => 'ADDIE', 'dica' => 'Modelo clássico de design instrucional: Análise, Design, Desenvolvimento, Implementação, Avaliação', 'direcao' => 'horizontal', 'linha' => 0, 'coluna' => 2],
|
| 4 |
['palavra' => 'ARCS', 'dica' => 'Modelo de motivação de Keller: Atenção, Relevância, Confiança, Satisfação', 'direcao' => 'vertical', 'linha' => 0, 'coluna' => 2],
|
| 5 |
['palavra' => 'LMS', 'dica' => 'Sistema de gerenciamento de aprendizagem (sigla em inglês)', 'direcao' => 'horizontal', 'linha' => 3, 'coluna' => 0],
|
| 6 |
];
|
Montar a grade
Calcula em qual célula cada letra cai e guarda o retângulo (linMin..linMax, colMin..colMax) realmente ocupado — desenhar só essa região, em vez de uma grade fixa inteira, evita sobra vazia empurrando o quebra-cabeça pro canto.
| 1 |
$linhas = 5;
|
| 2 |
$colunas = 8;
|
| 3 |
$grade = array_fill(0, $linhas, array_fill(0, $colunas, null));
|
| 4 |
$linMin = $linhas; $linMax = -1; $colMin = $colunas; $colMax = -1;
|
| 5 |
|
| 6 |
foreach ($palavras as $i => $p) {
|
| 7 |
$palavra = strtoupper($p['palavra']);
|
| 8 |
$lin = $p['linha'];
|
| 9 |
$col = $p['coluna'];
|
| 10 |
$dir = $p['direcao'];
|
| 11 |
for ($k = 0; $k < strlen($palavra); $k++) {
|
| 12 |
$l = $dir === 'horizontal' ? $lin : $lin + $k;
|
| 13 |
$c = $dir === 'horizontal' ? $col + $k : $col;
|
| 14 |
if ($l < $linhas && $c < $colunas) {
|
| 15 |
// Duas palavras podem começar na mesma célula (uma horizontal e
|
| 16 |
// uma vertical cruzando na primeira letra de ambas) — por isso
|
| 17 |
// os números se acumulam num array em vez de sobrescrever.
|
| 18 |
$numeros = $grade[$l][$c]['numeros'] ?? [];
|
| 19 |
if ($k === 0) $numeros[] = $i + 1;
|
| 20 |
$grade[$l][$c] = ['letra' => $palavra[$k], 'numeros' => $numeros];
|
| 21 |
$linMin = min($linMin, $l); $linMax = max($linMax, $l);
|
| 22 |
$colMin = min($colMin, $c); $colMax = max($colMax, $c);
|
| 23 |
}
|
| 24 |
}
|
| 25 |
}
|
| 26 |
$colunasVisiveis = $colMax - $colMin + 1;
|
| 27 |
?>
|
Grade
Célula com letra vira um input de uma posição só; célula sem letra é o quadrado bloqueado, sempre escuro (convenção visual de palavras cruzadas, não muda com o tema).
| 1 |
<div class="questao" data-tipo="palavras-cruzadas">
|
| 2 |
|
| 3 |
<div class="grade" style="grid-template-columns: repeat(<?= $colunasVisiveis ?>, 48px);">
|
| 4 |
<?php for ($r = $linMin; $r <= $linMax; $r++): for ($c = $colMin; $c <= $colMax; $c++): $cell = $grade[$r][$c]; ?>
|
| 5 |
<?php if ($cell): ?>
|
| 6 |
<div class="celula-casca">
|
| 7 |
<?php if (!empty($cell['numeros'])): ?><span class="numero"><?= implode(',', $cell['numeros']) ?></span><?php endif; ?>
|
| 8 |
<input type="text" maxlength="1" class="celula" data-letra="<?= $cell['letra'] ?>">
|
| 9 |
</div>
|
| 10 |
<?php else: ?>
|
| 11 |
<div class="bloqueado"></div>
|
| 12 |
<?php endif; ?>
|
| 13 |
<?php endfor; endfor; ?>
|
| 14 |
</div>
|
Pistas
Uma pista por palavra, numerada; a resposta nasce oculta e só some com o "hidden" depois de verificar.
| 1 |
<div class="pistas">
|
| 2 |
<?php foreach ($palavras as $i => $p): ?>
|
| 3 |
<div class="pista">
|
| 4 |
<p class="pista-numero"><?= $i + 1 ?>. <?= strtoupper($p['direcao']) ?></p>
|
| 5 |
<p class="pista-texto"><?= htmlspecialchars($p['dica']) ?></p>
|
| 6 |
<p class="resposta hidden">Resposta: <?= htmlspecialchars(strtoupper($p['palavra'])) ?></p>
|
| 7 |
</div>
|
| 8 |
<?php endforeach; ?>
|
| 9 |
</div>
|
Ações
Verificar, painel de resultado e 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>
|
Grade
Colunas dinâmicas via style inline — o número de colunas depende do que a atividade realmente ocupa.
| 1 |
.grade {
|
| 2 |
display: grid;
|
| 3 |
gap: 4px;
|
| 4 |
margin-bottom: 20px;
|
| 5 |
justify-content: center;
|
| 6 |
}
|
Célula de resposta
Casca quadrada com o input de uma letra centralizado dentro.
| 1 |
.celula-casca {
|
| 2 |
position: relative;
|
| 3 |
width: 48px;
|
| 4 |
height: 48px;
|
| 5 |
background: #f1f5f9;
|
| 6 |
border: 1px solid #cbd5e1;
|
| 7 |
border-radius: 4px;
|
| 8 |
display: flex;
|
| 9 |
align-items: center;
|
| 10 |
justify-content: center;
|
| 11 |
}
|
| 12 |
|
| 13 |
.celula {
|
| 14 |
width: 36px;
|
| 15 |
height: 36px;
|
| 16 |
background: transparent;
|
| 17 |
border: none;
|
| 18 |
text-align: center;
|
| 19 |
text-transform: uppercase;
|
| 20 |
font-size: 18px;
|
| 21 |
font-weight: 700;
|
| 22 |
color: #1e293b;
|
| 23 |
outline: none;
|
| 24 |
}
|
| 25 |
|
| 26 |
.celula:focus {
|
| 27 |
color: #4f46e5;
|
| 28 |
}
|
Número da pista
Pequeno rótulo no canto da célula onde uma ou mais palavras começam.
| 1 |
.numero {
|
| 2 |
position: absolute;
|
| 3 |
top: 2px;
|
| 4 |
left: 4px;
|
| 5 |
font-size: 10px;
|
| 6 |
font-weight: 700;
|
| 7 |
color: #4f46e5;
|
| 8 |
line-height: 1;
|
| 9 |
}
|
Quadrado bloqueado
Sempre escuro, nos dois temas — é a convenção visual de palavras cruzadas (quadrado sem letra é bloqueado), não a cor de fundo do card.
| 1 |
.bloqueado {
|
| 2 |
width: 48px;
|
| 3 |
height: 48px;
|
| 4 |
background: #1e293b;
|
| 5 |
}
|
Pistas
Uma caixa por palavra, com número, dica e a resposta (oculta até verificar).
| 1 |
.pistas {
|
| 2 |
display: flex;
|
| 3 |
flex-direction: column;
|
| 4 |
gap: 12px;
|
| 5 |
margin-bottom: 20px;
|
| 6 |
}
|
| 7 |
|
| 8 |
.pista {
|
| 9 |
padding: 12px;
|
| 10 |
border: 1px solid #cbd5e1;
|
| 11 |
border-radius: 10px;
|
| 12 |
background: #f8fafc;
|
| 13 |
}
|
| 14 |
|
| 15 |
.pista-numero {
|
| 16 |
margin: 0 0 4px;
|
| 17 |
font-size: 12px;
|
| 18 |
font-weight: 700;
|
| 19 |
color: #4f46e5;
|
| 20 |
}
|
| 21 |
|
| 22 |
.pista-texto {
|
| 23 |
margin: 0;
|
| 24 |
font-size: 14px;
|
| 25 |
color: #475569;
|
| 26 |
}
|
Resposta da pista
Some por padrão (classe hidden); o JS remove essa classe ao verificar.
| 1 |
.resposta {
|
| 2 |
margin: 8px 0 0;
|
| 3 |
font-size: 14px;
|
| 4 |
font-weight: 600;
|
| 5 |
color: #059669;
|
| 6 |
}
|
| 7 |
|
| 8 |
.hidden {
|
| 9 |
display: none;
|
| 10 |
}
|
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 |
|
| 13 |
.questao-verificar {
|
| 14 |
background: #4f46e5;
|
| 15 |
color: #fff;
|
| 16 |
}
|
| 17 |
|
| 18 |
.questao-reset {
|
| 19 |
background: #e5e7eb;
|
| 20 |
color: #1f2937;
|
| 21 |
}
|
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 a contagem de acertos, abaixo das pistas.
| 1 |
.questao-painel {
|
| 2 |
margin: 16px 0;
|
| 3 |
padding: 16px;
|
| 4 |
border-radius: 12px;
|
| 5 |
background: #1e3a8a;
|
| 6 |
color: #dbeafe;
|
| 7 |
font-weight: 600;
|
| 8 |
}
|
Encontrar os elementos da questão
Localiza as células, as respostas ocultas de cada pista e as ações.
| 1 |
document.addEventListener('DOMContentLoaded', function () {
|
| 2 |
document.querySelectorAll('.questao[data-tipo="palavras-cruzadas"]').forEach(function (questao) {
|
| 3 |
var celulas = questao.querySelectorAll('.celula');
|
| 4 |
var respostas = questao.querySelectorAll('.resposta');
|
| 5 |
var verificar = questao.querySelector('.questao-verificar');
|
| 6 |
var painel = questao.querySelector('.questao-painel');
|
| 7 |
var reset = questao.querySelector('.questao-reset');
|
Verificar
Tentativa única — compara cada célula com a letra esperada, trava a grade inteira e revela a resposta de cada pista separadamente (nunca uma sequência única com todas as palavras juntas).
| 1 |
verificar.addEventListener('click', function () {
|
| 2 |
var corretos = 0, total = 0;
|
| 3 |
celulas.forEach(function (c) {
|
| 4 |
total++;
|
| 5 |
var valor = (c.value || '').trim().toUpperCase();
|
| 6 |
var esperado = (c.dataset.letra || '').toUpperCase();
|
| 7 |
if (valor === esperado) corretos++;
|
| 8 |
c.disabled = true;
|
| 9 |
});
|
| 10 |
|
| 11 |
var mensagem = painel.querySelector('.questao-painel-mensagem');
|
| 12 |
mensagem.textContent = corretos === total
|
| 13 |
? 'Todas as respostas corretas!'
|
| 14 |
: corretos + '/' + total + ' letras corretas.';
|
| 15 |
painel.hidden = false;
|
| 16 |
|
| 17 |
respostas.forEach(function (r) { r.classList.remove('hidden'); });
|
| 18 |
|
| 19 |
verificar.hidden = true;
|
| 20 |
reset.hidden = false;
|
| 21 |
});
|
Reiniciar
Limpa os valores, reabilita as células e esconde as respostas de novo.
| 1 |
reset.addEventListener('click', function () {
|
| 2 |
celulas.forEach(function (c) { c.value = ''; c.disabled = false; });
|
| 3 |
respostas.forEach(function (r) { r.classList.add('hidden'); });
|
| 4 |
painel.hidden = true;
|
| 5 |
verificar.hidden = false;
|
| 6 |
reset.hidden = true;
|
| 7 |
});
|