Voltar ao Sumário
Quarto
Um jogo para discutir Algoritmos.
O aplicativo de hoje apresenta mais alguns recursos do App Inventor, mas sua aplicação prática é servir para a discussão sobre algoritmos. Não que haja algoritmos complexos no aplicativo, mas seu uso, depois de pronto, vai servir para ilustrar alguns conceitos.
Preparação - Definição do Problema
O jogo proposto é bem simples: Você vai criar um modelo que representa um quarto com uma única porta. Dentro desse quarto, é colocada uma pessoa em posição aleatória, virada para uma das paredes. O objetivo é ajudar a pessoa a sair do quarto usando uma sequência de comandos, que só podem ser: virar à esquerda, avançar um passo e virar à direita. Os comandos de virar só podem ser emitidos se a pessoa, ao virar, vai poder dar um passo à frente, e o comando de avançar só pode ser emitido se a pessoa tem espaço adiante para dar o passo. O jogo termina quando a pessoa está de frente para a porta de saída, e basta dar um passo para sair do quarto.
Para aumentar a dificuldade do jogo, pode-se apagar/acender a luz do quarto. No escuro, não se vê nada. As únicas informações disponíveis são se existe espaço à frente e de cada lado. Uma última ação é necessária: reiniciar o jogo.
Este é um problema geométrico, que demanda uma representação gráfica. É preciso determinar as dimensões do quarto e posição da porta. Para a pessoa, é preciso guardar a posição (coordenadas x e y) e orientação (um ângulo, que pode valer 0, 90°, 180° ou 270°). Na tela, vai ser necessário desenhar as paredes, a posição da porta, e representar a pessoa na posição e orientação adequada. Todas as ações podem ser representadas por botões. Os botões de virar e de avançar só estarão ativados se a ação for possível. O de acender/apagar a Luz pode ser um único botão, que muda o estado a cada vez que é pressionado. O botão Reiniciar move a pessoa para uma nova posição na tela.
No App Inventor, os componentes necessários para implementar este jogo são Botões, já bem conhecidos, uma Pintura, que já foi utilizada no aplicativo Desenho, e um SpriteImagem. Este último é um componente novo, muito utilizado em jogos de ação, que permite que uma pequena imagem seja posicionada e orientada na tela de Pintura, e deslocada com comandos simples. No texto, algumas vezes esse componente é chamado simplesmente de sprite.
Criando o App
Para criar o aplicativo, navegue para o site do App Inventor (http://appinventor.mit.edu), clique em Create Apps e faça Login com sua conta no Google. Quando o App Inventor iniciar, escolha a opção de menu Projetos/Iniciar novo projeto... (troque a língua para Português do Brasil).
Um diálogo vai solicitar o nome do projeto. Escolha um nome e clique no botão Ok (nome sugerido: Quarto).
O aplicativo vai ter uma única tela, Screen1. Mude o título da tela para o nome do seu aplicativo. Para isso, role o painel Propriedades até visualizar a caixa de texto Título. Troque o valor para o nome do app (Quarto).
Diagramação (Designer)
Veja uma possível diagramação da tela:
Nas propriedades de Screen1, escolha o Alinhamento Horizontal ao centro.
Crie os seguintes os componentes para seu aplicativo:
- Uma Pintura com Largura de 95 percentual e Altura de Preencher principal;
- Um SpriteImagem com a imagem de uma pessoa (desenhe ou procure na Internet);
- Uma Organização Horizontal, abaixo da Pintura, onde vão ficar os Botões;
- Cinco Botões, para representar os movimentos (btEsquerda, btAvancar e btDireita), o acionamento da luz (btLuz) e a ação de reiniciar (btReiniciar).
Blocos de Programação
Neste ponto, você tem todos os componentes de que vai precisar. É hora de criar o programa. Clique no botão Blocos que está no canto superior direito da tela para passar para a tela do Editor de Blocos.
Crie um procedimento com nome PrepararTela. Ele será usado na inicialização da tela, e sempre que btReiniciar for ativado.
Segue a descrição do procedimento por partes, por ele ser extenso:
No início do procedimento, use um bloco inicializar local. Neste bloco, renomeie a variável para meio_passo. Esse será o tamanho da metade de um passo dentro do quarto que você vai construir. O bloco se ... então ... senão serve para definir o valor de meio_passo. O teste verifica o que é menor - a altura ou a largura de Pintura1. O menor valor, dividido por 16, será utilizado como meio_passo, ou seja, o quarto terá dimensões de 8 x 8 passos. Os blocos que você vai precisar estão nos grupos Variáveis, Matemática e no componente Pintura1. Note que o bloco quociente de, no grupo Matemática, está com o nome módulo de. Arraste o bloco para a área de blocos, e clique no triângulo para mudar o tipo de bloco.
Logo após calcular meio_passo, você pode definir o valor da variável global tamanho_passo para o dobro desse valor. Veja abaixo os blocos que definem a variável e que tratam a inicialização da tela e o botão btReiniciar:
De volta a PrepararTela, a sequência de blocos após a iniciação de tamanho_passo limpa Pintura1, define a espessura do traço e define diversas propriedades do componente SpriteImagem1. Até que tudo esteja desenhado, o sprite não será visível. A Altura e Largura são definidas como tamanho_passo. Para a direção, você vai utilizar um novo tipo de bloco do grupo Matemática - inteiro aleatório. Este bloco sorteia automaticamente um número no intervalo indicado. No caso, o número terá valores entre 0 e 3, inclusive. Este número multiplicado por 90° será a direção inicial do sprite na tela, onde 0 é olhando para a direita, 90° para cima e assim por diante.
Definida a orientação do sprite, é preciso definir a posição. Você vai usar o bloco inteiro aleatório novamente, para escolher a quantos passos (de 1 a 7) na horizontal e quantos na vertical a pessoa está da porta, que fica na posição com x = 1 e y = 1.
O conjunto de blocos com esses cálculos está truncado e o detalhe das contas está destacado abaixo, porque o conjunto é muito largo para mostrar em uma única imagem.
Agora é hora de desenhar as paredes do quarto. O componente Pintura1 tem um procedimento DrawShape que desenha uma forma fechada qualquer, a partir de uma lista de pontos, estes, por sua vez, também listas de dois elementos, x e y. O quarto é um quadrado de 8 x 8 passos. A posição inicial é (0, 0), e a posição diagonalmente oposta é (8, 8). Para desenhar as paredes no centro da primeira e última posição, você deve desenhar um quadrado com diagonal de (0,5, 0,5) a (7,5, 7,5). Para não ter que trabalhar com frações, dobre os valores, e utilize a variável meio_passo. No início do quadrado, será deixada uma pequena abertura, para representar a porta.
Depois de desenhar as paredes, o sprite é tornado visível. Para finallizar, é preciso descobrir que botões de movimento devem ser ativados. Isto é delegado a outro procedimento - HabilitarBotoes - que será visto em seguida.
Toda vez que um movimento é realizado, o sprite muda de posição ou orientação. Para evitar movimentos inválidos, antes de permitir um novo movimento, é necessário calcular que botões podem ser ativados, e desativar os demais. Isto precisa ser executado em diversas partes do programa, e, portanto, os comandos devem ser agrupados em um novo procedimento - HabilitarBotoes. A lógica é simples, mas são necessários muitos testes. Por isso, o procedimento é longo. Basicamente: se o sprite está a menos de um passo de uma parede e de frente para a mesma, não pode avançar. Se está de lado para a mesma parede, não pode virar para este lado. É isso que o conjunto faz para cada uma das 4 paredes, e 4 direções.
Um dos testes é muito comprido, e foi destacado para melhor visualização:
Os conjuntos internos são bem parecidos, diferindo apenas nas coordenadas, limites e direções testados. Um deles, no entanto, para a direção de 90°, é especial: Neste caso, se tanto a coordenada x quanto a y estiverem no limite inferior, a pessoa representada por SpriteImagem1 está em frente à porta, a um passo de sair da sala. Neste caso, para sinalizar o fim do jogo, os três botões são desativados.
O aplicativo está quase pronto. Falta tratar os outros botões:
Quando btLuz é ativado, a visibilidade do sprite muda. Basta negar a visibilidade anterior:
Para os botões de direção, basta somar 90° à direção para virar à esquerda, e subtrair para virar à direita. Mas aqui surge uma propriedade dos ângulos: Como um ponteiro de relógio, que ao passar de 59 minutos volta ao zero, ao somar 1° a 359° o resultado, 360°, é o mesmo que 0°. No caso do programa, o ângulo está mudando de 90° a cada vez. Pela mesma propriedade, ao somar 90° a 270°, o valor deve voltar a 0°, e ao subtrair 90° de 0°, o ângulo passa a ser 270°. Veja como ficou o código:
Já para o botão avançar, a direção de Spriteimagem1 determina que coordenada deve ser alterada (x ou y), e se deve diminuir ou aumentar. A variação é sempre igual a tamanho_passo.
Seu código está pronto. Você pode compilar e instalar o .apk em um dispositivo, ou usar o emulador.
Usando o Jogo para Discutir Algoritmos
Você já deve ter percebido que este jogo é muito simples, e só se torna um pouco mais interessante com a luz apagada. Como foi mencionado no início do artigo, ele será útil para uma discussão sobre Algoritmos. Acompanhe as atividades propostas a seguir:
1) Inicie (ou reinicie) o jogo, e sem apagar a luz, ative os botões de direção e de avançar para levar a pessoa até a saída do quarto.
2) Reinicie o jogo, mas agora, escreva antes no papel a sequência de teclas a ativar. Verifique se a sequência, executada exatamente como foi anotada, funciona para levar a pessoa até a saída. Essa sequência de instruções é como um programa para um computador, ou um algoritmo*. Mas esse programa só funciona para a posição e orientação em que a pessoa estava no início da execução.
3) Você consegue pensar em uma solução que funcione para qualquer posição inicial? Desenvolva um algoritmo e teste até que ele funcione para diversas posições iniciais (obtidas ao pressionar o botão Reiniciar). Você pode utilizar comandos do tipo repetir ação enquanto condição, se condição então ação e ação, onde ação pode ser vire à esquerda, avance ou vire à esquerda, e condição pode ser existe espaço adiante, existe espaço à esquerda e existe espaço à direita.
4) Quando tiver um algoritmo funcionando, anotado em uma folha de papel, experimente reiniciando o jogo e apagando a luz. Funcionou?
* Um Algoritmo é uma sequência finita de instruções precisas e sem ambiguidade que pode ser executada por uma máquina para resolver um problema.
Implementando o Algoritmo em Código
Você tem agora um desafio pela frente: Como exercício, adicione um botão ao jogo: btSair. Modifique o código para que, ao ser pressionado o botão, o sprite representando a pessoa saia da sala de forma automática. Você vai ter que codificar o algoritmo que criou no ítem 3 e testou no ítem 4 da lista acima. Seguem algumas sugestões que vão ajudá-lo:
Você vai precisar criar procedimentos com os códigos utilizados no tratamento dos botões de ação, para poder reutilizar no seu algoritmo (VirarEsquerda, Avancar e VirarDireita).
Nos tratamentos dos botões, simplesmente acione os procedimentos para onde você moveu o código. Para evitar que os movimentos levem o sprite a posições inválidas, é melhor testar se o botão correspondente está ativado, e, portanto, se o movimento é válido. Veja abaixo as modificações necessárias:
Você vai ter que alterar a diagramação para acrescentar o novo botão. Aproveite, e adicione um novo componente, um Temporizador. Desmarque a propriedade Ativado. A explicação sobre ele vem em seguida.
Um computador é muito rápido, e se você deixá-lo resolver o problema de mover o sprite para sair do quarto na sua velocidade, muito provavelmente você só vai ver o resultado final, com a pessoa em frente à porta de saída. Para acompanhar a solução passo a passo, você vai ter que impor um ritmo bem mais lento, só permitindo ao programa executar um passo do algoritmo a cada intervalo de tempo que você possa acompanhar. Para isso será utilizado o Temporizador.
Este componente dispara eventos quando Temporizador1.disparo em intervalos de tempo (em milissegundos) determinados pela propriedade Intervalo. Como o valor dessa propriedade é 1000, os disparos vão ocorrer a cada segundo.
É muito provável que o seu algoritmo tenha sido desenvolvido utilizando um paradigma imperativo, com sequências de instruções, sendo algumas delas agrupadas em blocos de repetições, ou condicionais. Para utilizar o Temporizador, você vai ter que modificar a solução para um paradigma orientado a eventos, onde o evento é um disparo do temporizador. Nesse paradigma, algumas das repetições desaparecem, porque sua função é exercida pelos disparos do Temporizador. Se você acompanhou a oficina de Robótica utilizando o Arduino, você já utilizou esse paradigma.
O tratamento do botão btSair é muito simples: basta ativar Temporizador1, e deixar que o tratamento dos disparos mova o sprite em direção à saída. Se você tiver que criar variáveis globais para controlar o seu algoritmo, elas devem ser iniciadas no tratamento de btSair. Veja abaixo uma amostra do código de quando Temporizador1.disparo. já preenchida com alguns blocos, mas com a lógica incompleta (você vai completar).
Antes de completar o código no bloco de Disparo, é aconselhável fazer uma modificação no procedimento PrepararTela. Toda vez que você ativar o botão Reiniciar, o procedimento é acionado, e você deve desativar Temporizador1, voltando ao modo manual do jogo.
A modificação é bem simples. Veja abaixo:
Agora é sua vez. Complete o código de quando Temporizador1.disparo, compile e teste o jogo.
Veja aqui o projeto já construído: http://ai2.appinventor.mit.edu/?galleryId=5843488403226624
Distribuído sob a licença: Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) : https://creativecommons.org/licenses/by-sa/3.0/deed.pt_BR
















Nenhum comentário:
Postar um comentário