Criando um jogo da velha (Tic Tac Toe) com Flutter

Notas de aula do professor Kleber de Oliveira Andrade

Kleber Andrade
Flutter — Comunidade BR
7 min readSep 30, 2020

--

O jogo da velha ou jogo do galo como é conhecido em Portugal, é um jogo de regras extremamente simples, que não traz grandes dificuldades para seus jogadores e é facilmente aprendido.

O seu nome Jogo da Velha originou-se na Inglaterra quando mulheres ao fim de tarde se reuniam para tomar o chá, bordar e brincar. O jogo da velha era jogado pelas senhoras de mais idade já que as mesmas não enxergavam bem, e não podiam então realizar seus bordados; a opção de diversão então era o Jogo da Velha.

Mas muita gente acredita que a origem do jogo seria ainda mais antiga, pois foram encontrados tabuleiros escavados em rochas em templos do antigo Egito, que provavelmente foram feitos por escravos há mais de 3.500 anos atrás.

Regras do Jogo da Velha

  • O tabuleiro é uma matriz de três linhas por três colunas.
  • Dois jogadores escolhem uma marcação cada um, geralmente um círculo (O) e um xis (X).
  • Os jogadores jogam alternadamente, uma marcação por vez, numa lacuna que esteja vazia.
  • O objectivo é conseguir três círculos ou três xis em linha, quer horizontal, vertical ou diagonal , e ao mesmo tempo, quando possível, impedir o adversário de ganhar na próxima jogada.
  • Quando um jogador conquista o objetivo, costuma-se riscar os três símbolos.

Se os dois jogadores jogarem sempre da melhor forma, o jogo terminará sempre em empate.

A lógica do jogo é muito simples, de modo que não é difícil deduzir ou decorar todas as possibilidades para efetuar a melhor jogada — apesar de o número total de possibilidades ser muito grande, a maioria delas é simétrica, além de que as regras são simples.

Criando o aplicativo

Abra o Visual Studio Code, e abra a paleta de comandos F1 e digite: Flutter: New Project

  • Digite o nome do projeto Flutter (tictactoe);
  • Selecione a pasta para criar o projeto Flutter;

Estrutura do projeto

Nosso projeto, seguirá o modelo MVC (Model-View-Controller) de desenvolvimento.

Criando os Modelos

Sempre que você pensar em manipulação de dados, pense em model. Ele é responsável pela leitura e escrita de dados, e também de suas validações.

Classe BoardTile

Crie a classe BoardTile (lib → models → board_tile.dart), que irá persistir as informações das células do tabuleiro. Esta classe representará uma célula do tabuleiro, para isso, vamos criar um identificador para ela, guardar uma cor (vermelho e azul) e simbolo (X e O). Quando uma célula estiver vazia, significa que esta esta habilitada para o jogador adicionar uma peça nela (enable = true).

Mais explicações sobre final, const e static

Criando Enumeradores

Um tipo de enumeração (ou tipo enum) é um tipo de valor definido por um conjunto de constantes nomeadas do tipo numérico integral subjacente. Para definir um tipo de enum enumeração, use a palavra-chave e especifique os nomes dos membros do enum.

Enumerador PlayerType

Crie o arquivo lib → enums → player_type.dart para definir os jogadores.

Enumerador WinnerType

Crie o arquivo lib → enums → winner_type.dart para definir os ganhadores

Criando Constantes

Crie o arquivo lib → core → constants.dart para definir as constantes do jogo. Entre essas constantes estão os símbolos, cores e textos.

Criando o Controle do Jogo

O responsável por receber todas as requisições do usuário.

Eu sempre gosto de observar a classe Controller como um diagrama de Caso de Uso.

O diagrama de caso de uso descreve a funcionalidade proposta para um novo sistema que será projetado, ou seja, as funcionalidades que precisamos para fazer o nosso controlador.

Para saber mais sobre o diagrama de Caso de Uso

Crie a classe GameController (lib → controllers → game_controller.dart), que servirá para definir o funcionamento do jogo. Vamos começar a classe declarando a variáveis, criando a função para inicializar os parâmetros e uma função de reset.

Utilizamos um construtor da lista chamada generate para criar 9 células. Para saber mais sobre os métodos da lista leia aqui.

Criaremos agora as funções para marcar um BoardTile com informações do jogador atual.

Focaremos agora em tentar criar as regras para verificar quem ganhou a partida.

Olhando para esse monte de IFs, é possível pensar em uma nova forma utilizando o método Any da List e uma lista das regras. Vamos reescrever o código então.

Crie a classe WinnerRules (lib → core → winner_rules.dart), que vai armazenar a tabela com as regras de vitórias.

Na classe GameController adicionaremos um método para o movimento aleatório do Bot.

Caso você tenha interesse em codificar uma inteligência artificial para este jogo, recomendo estudar o algoritmo Minimax. Veja o vídeo abaixo.

Criando as Views

Camada de interação com o usuário. Ela apenas faz a exibição dos dados.

Classe CustomDialog

Crie a classe CustomDialog (lib → widgets → custom_dialog.dart), que utilizaremos exibir exibir as mensagens de vitória, derrota ou empate do jogo.

Veja mais exemplos sobre AlertDialog clicando aqui.

Classe GamePage

Crie a classe GamePage (lib → pages → game_page.dart), que exibirá a tela do jogo. Vamos detalhes nossa tela antes de começar a codificação.

Para nossa interface, perceba que usamos o gerenciador de estado (setState). Um incrível e simples forma de gerenciar o estado com Flutter. Existem outros (MobX, BloC, GetX, etc…), mas para começar, essa forma é muito simples. Para saber mais veja este vídeo.

Tema do aplicativo

Crie um arquivo (lib → core → theme_app.dart), que definirá o tema do aplicativo.

Programa principal

Vamos atualizar o arquivo main.dart para que ele instancia a nossa view GamePage. Neste momento, também podemos definir o tema do aplicativo.

Resultado

Agora, aperte F5 para iniciar a depuração do projeto. Selecione um emulador existente ou crie um novo se for necessário.

Se seu celular estiver plugado no computador e com o modo desenvolver ativado, você poderá rodar o aplicativo direto no celular.

Conseguiu chegar até aqui? Parabéns, você acaba de criar um jogo da velha. Agora você acaba de liberar uma nova conquista!

O código completo pode ser baixado aqui.

Espero que tenham gostado, deixem seus comentários e um forte abraço!

Desafios

  1. Exibir o jogador da vez (Turno do X ou Turno do Y); Pode usar um Text para isso.
  2. Criar um placar de vitórias para cada jogador; Pode usar Text também
  3. Criar uma splash screen para o aplicativo; Utilize o plugin custom_splash.
  4. Adicionar um botão para compartilhar o aplicativo. Utilize o plugin Share.
  5. Trocar o X e Y por duas imagens (exemplo: Finn e Jake de Adventure Time) — como utilizar imagens. Entendendo como colocar imagens em um Container.

--

--

Kleber Andrade
Flutter — Comunidade BR

Expert Developer of Robot, Games, Artificial Intelligence. Languages C/C++, Python, Java and C#