Aula 01 - Seguindo paredes com a mão direita
Nesse handout iremos formalizar duas grandes ideias:
- uma classe para representar o labirinto
- como representar o algoritmo senso comum de sair do labirinto seguindo as paredes
A classe Labirinto
Um primeiro passo para definirmos nossos algoritmos é definir como o labirinto será representado para nosso código. Vamos considerar um labirinto com as seguintes operações nesta atividade.
NOVO_LABIRINTO(TEXT)
- recebe um texto no formato de labirinto definido abaixo e devolve o labirinto criado.LIVRE(L, I, J)
- devolveVERDADEIRO
se a posição na linhaI
colunaJ
não é paredeSAIDA(L, I, J)
- devolveVERDADEIRO
se a posição na linhaI
colunaJ
é uma saída do labirinto (ou seja, se está na borda do labirinto e se está livre)LARGURA(L), ALTURA(L)
- devolve a largura/altura do labirinto
Usaremos o seguinte formato de texto para a criação do labirinto
- cada linha contém somente caracteres
'.'
(livre) ou'#'
(parede) - todas as linhas contém o mesmo número de caracteres
Iremos representar o labirinto como um array boolean casas[][]
em que a posição casas[i][j]
contém true
se a casa é parede e false
caso contrário. Veja o item da classe no PrairieLearn deste módulo para uma descrição mais completa da implementação.
Algoritmo de Seguir Paredes
Ao longo das próximas aulas iremos criar várias versões do algoritmo ENCONTRA_SAIDA(L, I, J, CAMINHO)
onde
L
é um labirintoI, J
é a posição inicialCAMINHO
é um array que será preenchido com as posições do labirinto até a saída
A primeira ideia que estudaremos para a criação de um algoritmo é simples:
para sair do labirinto basta colocar a mão direita na parede mais próxima e seguir sempre com essa mão na parede. Eventualmente chegamos na saída.
Exercício 1
Resposta
Essa ideia faz o contorno das paredes do labirinto, passando por todas as paredes tocáveis. Eventualmente chegamos na parede da casa da saída, se houver um caminho.
Exercício 2
Para implementar esse algoritmo precisamos definir algumas coisas:
- estado: quais variáveis representam o andamento do algoritmo.
- critério de parada: quando decidimos que chegamos no fim?
Uma boa maneira de entender esses pontos é simular a ideia em alguns cenários simples. Vamos lá
Exercício 3
Exercício 4
Exercício 5
Agora já conseguimos observar algumas coisas:
- a próxima posição parece depender da posição atual e da anterior
- somente saber a posição atual não é suficiente para saber a próxima posição
Vamos agora continuar nossa exploração dessa ideia:
Exercício 6
Exercício 7
Vamos agora para um caso difícil:
Exercício 8
Resposta
Nossa ideia diz que a mão direita deve passar por todas paredes e que sempre seguimos em frente. Logo, a opção "Anda para baixo, mantém mão na mesma parede" não pode ocorrer: foi invertido o sentido sem trocar a mão de parede.
A opção "fica no mesmo lugar, mas muda mão para parede da esquerda" pulou uma parede e mudou direto para a da esquerda.
Gostaríamos de seguir reto, mas não é possível pois há uma parede na frente. Logo, devemos mudar a mão de parede, virando para a esquerda e colocando a mão na parede de cima.
Exercício 9
Resposta
As posições I,J
atuais mais a parede usada como referência para a mão direita. Podemos representar essa parede como uma direção dentre CIMA, BAIXO, ESQUERDA, DIREITA
.
Exercício 10
Resposta
Faça o exercício abaixo e revise sua resposta usando o botão "Editar"
Exercício 11
Resposta
Nos casos em que não há uma saída alcançável, precisamos verificar se voltamos ao ponto inicial com a mão na mesma parede. Ou seja, irá acontecer um loop infinito, pois o algoritmo progride sempre igual dado o mesmo estado inicial.
Com essas simulações já é possível criar um algoritmo que implemente essa ideia. Faremos a seguinte sequência iterativa:
- design de uma versão inicial do algoritmo
- simulação de uma iteração com um exemplo de cenário
- revisão do algoritmo, caso ocorram erros
Exercício 12
Resposta
Esse é parte da APS ;)
Exercício 13
Exercício 14
Exercício 15
Agora é hora de partir para implementação. Veja o item deste algoritmo no PrairieLearn deste módulo para uma descrição mais completa da implementação.