Introdução
Bem-vindo a este projeto sobre a construção de um simples jogo de Quebra-Cabeça Deslizante usando JavaScript. Ao final deste guia, você terá um jogo de quebra-cabeça deslizante 3x3 funcional que poderá jogar em seu navegador. O jogo apresentará peças numeradas, um cronômetro e controles para iniciar, pausar e reiniciar o jogo.
Nenhuma experiência prévia é necessária, mas uma compreensão básica de JavaScript e HTML seria útil. Vamos mergulhar!
👀 Pré-visualização

🎯 Tarefas
Neste projeto, você aprenderá:
- Como projetar o layout do jogo em HTML
- Como escrever os estilos CSS para o jogo
- Como inicializar as variáveis do jogo em JavaScript
- Como implementar a função de movimento para lidar com os movimentos das peças
- Como determinar os movimentos possíveis das peças
- Como implementar o cronômetro do jogo
- Como controlar o fluxo do jogo com as funções de iniciar, pausar e reiniciar
- Como embaralhar as peças aleatoriamente no início ou ao reiniciar
- Como inicializar o jogo no carregamento da página
🏆 Conquistas
Após concluir este projeto, você será capaz de:
- Projetar o layout de um jogo usando HTML
- Estilizar elementos usando CSS
- Implementar a lógica do jogo usando JavaScript
- Lidar com a entrada do usuário e realizar ações com base nela
- Manipular o DOM para atualizar o estado do jogo e exibir informações
Design do Layout do Jogo em HTML
Projete o layout do jogo em index.html, conforme mencionado na análise anterior.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Puzzle</title>
<link rel="stylesheet" type="text/css" href="puzzle.css" />
<script type="text/javascript" src="puzzle.js"></script>
</head>
<body>
<div id="container">
<!-- DIV mais externa, usada para conter a estrutura interna -->
<div id="game">
<!-- Área do jogo, que é o grande bloco DIV -->
<div id="d1" onclick="move(1)">1</div>
<!-- DIVs pequenas, que são os 8 blocos pequenos. Quando clicados, a função move() é executada. O parâmetro é o número exibido, para que saibamos qual bloco foi clicado -->
<div id="d2" onclick="move(2)">2</div>
<div id="d3" onclick="move(3)">3</div>
<div id="d4" onclick="move(4)">4</div>
<div id="d5" onclick="move(5)">5</div>
<div id="d6" onclick="move(6)">6</div>
<div id="d7" onclick="move(7)">7</div>
<div id="d8" onclick="move(8)">8</div>
</div>
<div id="control">
<!-- Área de controle do jogo -->
<p>
<rowspan id="timeText">Tempo Total</rowspan>
<!-- "Total Time" -->
<rowspan id="timer"></rowspan>
</p>
<!-- Área de exibição do tempo do jogo -->
<p>
<rowspan id="start" onclick="start()">Iniciar</rowspan>
<!-- "Start" -->
<rowspan id="reset" onclick="reset()">Reiniciar</rowspan>
<!-- "Retry" -->
</p>
<!-- Área de exibição dos botões de controle -->
</div>
</div>
</body>
</html>
Escrevendo os Estilos CSS
Após concluir a estrutura do layout, é hora de embelezar nosso jogo com estilos CSS. Durante esta fase, você tem a liberdade de personalizar e projetar o jogo de acordo com sua preferência, adicionando toques e detalhes exclusivos. Você também pode introduzir mais elementos decorativos para aprimorar a estética do jogo. No entanto, uma nota importante: se você alterar o tamanho do DIV principal do jogo, certifique-se de ajustar o código JavaScript correspondente. Discutiremos isso com mais profundidade em breve.
Em puzzle.css, adicione:
* {
padding: 0;
margin: 0;
border: 0;
}
/* O '*' é um curinga, removendo os estilos padrão para todos os elementos porque alguns navegadores podem adicionar estilos padrão, o que pode criar problemas de layout. */
body {
width: 100%;
height: 100%;
}
/* Definindo a altura e largura do corpo para 100%, para que ele se adapte automaticamente de acordo com o tamanho da tela do navegador. */
#container {
position: relative;
width: 620px;
height: 450px;
margin: 0 auto;
margin-top: 100px;
border-radius: 1px;
}
/* Este é o DIV que envolve todos os elementos. Definido para 620px de largura e 450px de altura. Este tamanho pode ser aumentado, mas não diminuído. Deve ser grande o suficiente para conter todos os elementos internos. */
#game {
position: absolute;
width: 450px;
height: 450px;
border-radius: 5px;
display: inline-block;
background-color: #ffe171;
box-shadow: 0 0 10px #ffe171;
}
/* Esta é a área do jogo DIV. O tamanho é calculado com base no tamanho dos blocos menores. Aqui, os blocos são definidos para 150px por 150px, então a área do jogo é 150px*3, totalizando 450px. */
#game div {
position: absolute;
width: 149px;
height: 149px;
box-shadow: 1px 1px 2px #777;
background-color: #20a6fa;
color: white;
text-align: center;
font-size: 150px;
line-height: 150px;
cursor: pointer;
-webkit-transition: 0.3s; /* Prefixo do navegador para compatibilidade com Chrome */
-moz-transition: 0.3s; /* Para Firefox */
-ms-transition: 0.3s; /* Para IE */
-o-transition: 0.3s; /* Para Opera */
transition: 0.3s;
}
/* Isso define o tamanho dos blocos pequenos. Posicionados como absolute, as mudanças na posição não afetarão as posições de outros elementos. A largura e a altura são ambas 149px. Notavelmente, há uma box-shadow, adicionando à sua dimensão geral. A propriedade 'transition:0.3s' faz com que as mudanças apareçam como animações, então, quando a posição do bloco muda, uma animação é reproduzida automaticamente. */
#game div:hover {
color: #ffe171;
}
/* Definindo a animação de mouse hover para os blocos. Quando o mouse passa sobre um elemento, essas propriedades substituem as anteriores, e ele retorna ao original quando o mouse se afasta. Aqui, estamos mudando a cor da fonte. */
#control {
width: 150px;
height: 450px;
display: inline-block;
float: right;
}
/* Seção de controle. 'display:inline-block' permite que o elemento mantenha as propriedades de bloco sem ocupar uma linha inteira, e 'float:right' o posiciona no lado direito. */
#control rowspan {
height: 25px;
font-size: 20px;
color: #222;
margin-top: 10px;
}
/* Estilos comuns para botões na área de controle. */
#start {
display: inline-block;
font-size: 28px;
width: 100px;
height: 28px;
background-color: #20a6fa;
color: #ffe171;
text-shadow: 1px 1px 2px #ffe171;
border-radius: 5px;
box-shadow: 2px 2px 5px #4c98f5;
text-align: center;
cursor: pointer;
}
/* Estilos para o botão 'Iniciar'. 'cursor:pointer' faz com que o cursor mude para um símbolo de mão ao passar o mouse sobre ele. */
#reset {
display: inline-block;
font-size: 28px;
width: 100px;
height: 28px;
background-color: #20a6fa;
color: #ffe171;
text-shadow: 1px 1px 2px #ffe171; /* Sombra da fonte */
border-radius: 5px; /* Cantos arredondados */
box-shadow: 2px 2px 5px #4c98f5; /* Sombra da caixa */
text-align: center; /* Centralizar texto */
cursor: pointer;
}
/* Estilos para o botão 'Reiniciar'. */
#d1 {
left: 0px;
}
#d2 {
left: 150px;
}
#d3 {
left: 300px;
}
#d4 {
top: 150px;
}
#d5 {
top: 150px;
left: 150px;
}
#d6 {
top: 150px;
left: 300px;
}
#d7 {
top: 300px;
}
#d8 {
left: 150px;
top: 300px;
}
/* Posições predefinidas para cada um dos blocos em ordem. */
Ter os estilos definidos é um passo significativo. Em seguida, passaremos para a lógica JavaScript para dar vida ao nosso jogo de quebra-cabeça. É aconselhável que o estilo inicial seja feito de acordo com as instruções acima. Depois que a funcionalidade do jogo for bem compreendida, você estará livre para exibir sua criatividade e personalizar ainda mais os estilos. No entanto, fazer alterações precoces e desinformadas pode levar a falhas imprevistas.
Inicializar Variáveis do Jogo em JavaScript
Antes de adicionar a funcionalidade do jogo, inicialize as variáveis essenciais do estado do jogo.
Em puzzle.js, adicione:
// puzzle.js
var time = 0;
// Salva o tempo decorrido
var pause = true;
// Flag para indicar se o jogo está pausado, true significa que está pausado
var set_timer;
// Função do temporizador
var d = new Array(10);
// Armazena o número do pequeno DIV atualmente no grande DIV
var d_direct = new Array(
[0],
[2, 4], // O grande DIV com o número 1 pode ir para as posições 2 e 4
[1, 3, 5],
[2, 6],
[1, 5, 7],
[2, 4, 6, 8],
[3, 5, 9],
[4, 8],
[5, 7, 9],
[6, 8]
);
// Salva as possíveis posições de movimento para os grandes DIVs
var d_posXY = new Array(
[0],
[0, 0], // O primeiro número representa left, o segundo representa top. Ex: a posição do primeiro bloco é left:0px, top:0px
[150, 0],
[300, 0],
[0, 150],
[150, 150],
[300, 150],
[0, 300],
[150, 300],
[300, 300]
);
// Posição dos grandes DIVs
d[1] = 1;
d[2] = 2;
d[3] = 3;
d[4] = 4;
d[5] = 5;
d[6] = 6;
d[7] = 7;
d[8] = 8;
d[9] = 0;
// Arranjo padrão, o nono grande DIV está vazio, então é 0. Usamos 0 para representar a peça em branco.
Implementar a Função de Movimento
Crie uma função que permita que as peças se movam com base na interação do usuário.
Adicione a puzzle.js:
// puzzle.js
function move(id) {
// Função de movimento
var i = 1;
for (i = 1; i < 10; ++i) {
if (d[i] == id) break;
}
// Este loop encontra a posição do pequeno DIV dentro do grande DIV
var target_d = 0;
// Salva as possíveis posições para o pequeno DIV, 0 significa que ele não pode se mover
target_d = whereCanTo(i);
// Descobre para onde o pequeno DIV pode se mover. Se retornar 0, significa que não pode se mover, caso contrário, retorna o número da posição de destino
if (target_d != 0) {
d[i] = 0;
// Define o número do grande DIV atual como 0 porque o pequeno DIV se moveu, então o grande DIV atual está agora vazio
d[target_d] = id;
// Define o grande DIV de destino para o número do pequeno DIV clicado
document.getElementById("d" + id).style.left = d_posXY[target_d][0] + "px";
document.getElementById("d" + id).style.top = d_posXY[target_d][1] + "px";
// Finalmente, define a posição do pequeno DIV clicado para a posição do grande DIV de destino
}
var finish_flag = true;
// Flag para indicar se o jogo foi concluído, true significa que foi concluído
for (var k = 1; k < 9; ++k) {
if (d[k] != k) {
finish_flag = false;
break;
}
}
// Itera de 1, verifica cada número do grande DIV. Se eles não estiverem em ordem, o jogo não foi concluído.
if (finish_flag == true) {
if (!pause) start();
alert("Congratulations!");
}
// Se true, o jogo foi concluído. Se não estiver pausado, chama a função de pausa e exibe uma mensagem de sucesso.
}
Determinar os Movimentos Possíveis das Peças
Crie uma função para determinar para onde uma peça pode se mover com base em sua posição atual.
Adicione a puzzle.js:
// puzzle.js
function whereCanTo(cur_div) {
// Função para determinar se um determinado DIV pode se mover e para qual posição
var j = 0;
var move_flag = false;
for (j = 0; j < d_direct[cur_div].length; ++j) {
if (d[d_direct[cur_div][j]] == 0) {
move_flag = true;
break;
}
}
if (move_flag == true) {
return d_direct[cur_div][j];
} else {
return 0;
}
// Se puder se mover, retorna o número da posição de destino, caso contrário, retorna 0
}
Implementar o Cronômetro do Jogo
Adicione uma função de cronômetro para acompanhar o tempo decorrido durante o jogo.
Adicione a puzzle.js:
// puzzle.js
function timer() {
// Função do cronômetro, executa a cada segundo
time += 1;
var min = parseInt(time / 60); // Converte segundos em minutos
var sec = time % 60; // Obtém os segundos restantes
document.getElementById("timer").innerHTML =
min + " minutos " + sec + " segundos";
}
Controlar o Fluxo do Jogo
Implemente funções para iniciar, pausar ou reiniciar o jogo com base na entrada do usuário.
Adicione a puzzle.js:
// puzzle.js
function start() {
// Inicia ou pausa o jogo
if (pause) {
document.getElementById("start").innerHTML = "Pause";
pause = false;
set_timer = setInterval(timer, 1000);
} else {
document.getElementById("start").innerHTML = "Start";
pause = true;
clearInterval(set_timer);
}
}
function reset() {
// Reinicia o jogo
time = 0;
random_d();
if (pause) start();
}
Embaralhar as Peças Aleatoriamente
Crie uma função para embaralhar aleatoriamente as peças no início ou ao reiniciar.
Adicione a puzzle.js:
// puzzle.js
function random_d() {
// Embaralha aleatoriamente as peças
for (var i = 9; i > 1; --i) {
var to = parseInt(Math.random() * (i - 1) + 1);
if (d[i] != 0) {
document.getElementById("d" + d[i]).style.left = d_posXY[to][0] + "px";
document.getElementById("d" + d[i]).style.top = d_posXY[to][1] + "px";
}
if (d[to] != 0) {
document.getElementById("d" + d[to]).style.left = d_posXY[i][0] + "px";
document.getElementById("d" + d[to]).style.top = d_posXY[i][1] + "px";
}
var tem = d[to];
d[to] = d[i];
d[i] = tem;
}
}
Inicializar o Jogo ao Carregar a Página
Finalmente, certifique-se de que, quando a página da web for carregada, as peças do jogo sejam exibidas e estejam prontas para jogar.
Adicione a puzzle.js:
// puzzle.js
// Inicializa o jogo no carregamento da página
window.onload = function () {
reset();
};
Executando o Projeto
Abra
index.htmlem um navegador web.
O efeito da página é o seguinte:

Resumo
Você construiu com sucesso um jogo de Quebra-Cabeça Deslizante usando JavaScript de maneira estruturada e organizada! A divisão passo a passo deve facilitar para os aprendizes a compreensão de cada componente da lógica do jogo. Lembre-se, esta é apenas uma versão básica, e há muito espaço para aprimoramentos e recursos adicionais. Mergulhe e faça com que seja seu. Feliz codificação!



