Bingo Pedagógico: um jogo de estimulação cognitiva para idosos feito com Next.js

Contexto do Projeto
Este projeto surgiu de uma demanda real da psicóloga clínica Tathiane Galvão (CRP 01/27841): desenvolver um bingo visual como ferramenta de estimulação cognitiva para idosos em sessões terapêuticas. O conceito baseia-se no bingo tradicional, substituindo números por imagens, executado diretamente no navegador sem necessidade de cadastro ou infraestrutura de servidor.
À primeira vista, os requisitos pareciam simples: gerar cartelas, sortear imagens, imprimir. No entanto, uma análise mais detalhada do contexto de uso revelou restrições importantes que influenciaram as decisões técnicas:
- Idosos frequentemente apresentam limitações visuais ou motoras
- Profissionais mediadores nem sempre possuem familiaridade com tecnologia
- Ambientes de aplicação (clínicas, centros de convivência) podem ter conectividade limitada
Estas restrições orientaram as escolhas arquiteturais do projeto.
Análise de Requisitos
O processo manual existente envolvia recorte de imagens, colagem em cartolina e sorteio físico. Embora funcional, demandava tempo considerável. A personalização temática (como uso de fotos familiares do paciente) exigia recriação completa do material.
Foram identificados quatro requisitos fundamentais:
- Geração automática de cartelas com imagens únicas
- Sistema de sorteio visual para exibição coletiva com legendas
- Funcionalidade de impressão formatada para A4
- Suporte a temas personalizados com upload de imagens
Arquitetura sem Backend
Optou-se por uma arquitetura totalmente client-side, sem banco de dados, autenticação ou servidor. Esta decisão foi motivada pelo perfil do usuário e contexto de uso.
Profissionais da saúde precisam de acesso imediato sem processos de cadastro. A dependência de conexão é inviável em ambientes com infraestrutura limitada. Interrupções de rede não podem comprometer sessões em andamento.
A persistência é implementada inteiramente no navegador. Dados de estado (cartelas geradas, progresso do sorteio) utilizam localStorage. Imagens personalizadas são armazenadas no IndexedDB, que não possui a limitação de 5 MB do localStorage e suporta armazenamento de múltiplas imagens em base64. Após o carregamento inicial, a aplicação opera completamente offline.
Persistência com localStorage
Dados leves utilizam localStorage:
export function saveGeneratedCards(key: string, cards: BingoCard[]) {
localStorage.setItem(key, JSON.stringify(cards));
}
export function getGeneratedCards(key: string): BingoCard[] {
const data = localStorage.getItem(key);
return data ? JSON.parse(data) : [];
}
Persistência com IndexedDB
Imagens personalizadas utilizam IndexedDB:
const db = await openDB('bingo-store', 1, {
upgrade(db) {
db.createObjectStore('custom-bingos');
},
});
await db.put('custom-bingos', bingoData, bingoId);
const bingo = await db.get('custom-bingos', bingoId);
Para casos de uso multiplataforma ou compartilhamento entre educadores, a aplicação oferece funcionalidade de exportação e importação. Bingos personalizados podem ser exportados como arquivos JSON, permitindo transferência entre dispositivos ou distribuição para outros profissionais.
Modalidades de Jogo
Modo Padrão
Conteúdo pré-configurado com 16 imagens distribuídas em quatro categorias: emoções, autocuidado, socialização e geral. O algoritmo de geração de cartelas 3×3 não utiliza seleção puramente aleatória, mas distribui imagens de cada categoria proporcionalmente para maximizar a variedade.
Modo Personalizado
Permite upload de imagens próprias (PNG, JPG ou WebP, limite de 5MB por arquivo). As imagens são convertidas para base64 e armazenadas no IndexedDB. A versão inicial utilizava localStorage, mas o limite de armazenamento era facilmente excedido. O IndexedDB elimina esta restrição mantendo operação offline.
O sistema requer mínimo de 9 imagens (tamanho da cartela 3×3). Recomenda-se 16 imagens para variedade adequada. Bingos criados podem ser editados posteriormente, permitindo alteração de nome ou adição de novas imagens sem necessidade de recriação completa.
Algoritmo de Geração de Cartelas Únicas
Um gerador puramente aleatório com conjunto limitado de imagens pode produzir cartelas idênticas. Para 16 imagens com seleção de 9, existem C(16,9) = 11.440 combinações possíveis, mas sem validação, repetições são prováveis.
Implementou-se cálculo do número máximo de cartelas únicas para o conjunto disponível, com validação de cada cartela gerada contra cartelas existentes:
function combination(n: number, k: number): number {
if (k > n || k < 0) return 0;
if (k === 0 || k === n) return 1;
if (k > n - k) k = n - k;
let result = 1;
for (let i = 0; i < k; i++) {
result = (result * (n - i)) / (i + 1);
}
return Math.floor(result);
}
export function getMaxUniqueCards(availableImages: BingoImage[]): number {
return combination(availableImages.length, CARD_SIZE);
}
A interface exibe o limite calculado dinamicamente. Exemplos:
- 9 imagens: 1 cartela única
- 10 imagens: 10 cartelas únicas
- 16 imagens: 11.440 cartelas únicas
O sistema permite adicionar cartelas extras a conjuntos já gerados sem invalidar cartelas anteriormente impressas. Cartelas podem ser exportadas e importadas, facilitando reutilização em sessões futuras.
Sistema de Sorteio
Projetado para uso com projetor ou TV. Ao acionar o sorteio, a imagem é exibida em tela cheia com otimização para visibilidade. Interação em qualquer área retorna ao painel de controle.
O sistema implementa persistência de estado: recarregamentos de página ou fechamentos acidentais do navegador não interrompem o jogo. O estado (IDs de imagens sorteadas) é mantido em localStorage:
const { currentImage, drawnImages, remainingCount, canDraw, draw, reset } =
useLottery(images, "bingo-standard-lottery");
Painel de Mediação Terapêutica
Interface lateral apresenta perguntas sugeridas para orientação do profissional durante a aplicação. Este recurso foi solicitado considerando que nem todos os mediadores possuem experiência com dinâmicas de estimulação cognitiva.
Funcionalidade de Impressão
A impressão é componente essencial do projeto. O uso de cartelas físicas é intencional, proporcionando experiência tátil e familiaridade com o formato tradicional do jogo.
Cartelas impressas incluem:
- Bordas pontilhadas para orientação de recorte
- Cantos retos para facilitar corte com tesoura
- Ocultação de elementos de navegação
- Formatação A4 padrão
@media print {
@page {
size: A4;
margin: 1cm;
}
}
Visualização em tela utiliza sombras e bordas arredondadas. A versão impressa é renderizada com estilo simplificado e bordas tracejadas. A propriedade printMode do componente gerencia esta alternância.
Stack Tecnológica
Next.js 16, React 19, Tailwind CSS v4, Vitest, Cypress, Biome, lucide-react, shadcn/ui.
Acesso
O projeto está disponível em bingo.rafikmoreira.dev.br. Acesso gratuito e sem restrições.