Cursos / Jogos Digitais / Programação Estruturada / Aula
Olá! Nesta videoaula, você verá a aplicação de recursão a matrizes. Na prática, tem-se apenas uma extensão do que foi visto na primeira. Afinal de contas, matrizes são arrays, a única diferença é que seus elementos são arrays também. Mais uma vez, utilizarei exemplos para apresentar a aplicação de recursão a matrizes. Para começar, você conhecerá uma utilidade prática de matrizes.
As telas de computadores podem ser tratadas como matrizes. Isto porque cada ponto da tela tem uma coordenada x e uma coordenada y. Por exemplo, o quadrado amarelo marcado no slide (Figura 1) tem coordenadas (n,m).
É comum que nessa coordenada tenha-se três valores naturais que indicam a intensidade das cores vermelho (red em inglês), verde (green em inglês) e azul (blue em inglês). Por isso, esse é um valor RGB: R de red, G de green e B de blue.
Para facilitar o entendimento, irei simplificar a "tela": considere uma tela 10 por 10, ou seja, que tenha apenas 10 linhas e 10 colunas. No slide (Figura 2), observe no exemplo de tela que apenas o ponto (7,4) tem o valor amarelo. Todos os outros são azuis.
Você deve estar se perguntando: por que isso pode ser considerado uma matriz? Olhe novamente para o slide (Figura 3). Desta vez, coloquei os colchetes para marcar os arrays. Temos um array mais externo, delimitado com os colchetes azul-claros, cujos elementos são as linhas, os arrays mais internos.
Dessa forma, se acessarmos o elemento 7 do array tela, teremos a linha indicada pela seta no slide. Porém, esse elemento é também um array delimitado com colchetes pretos. Por isso, se você acessar o elemento 4 dessa linha, chegará ao ponto amarelo. Assim sendo, para referenciar o ponto amarelo, pode-se simplesmente usar a expressão tela[7][4]. Interessante, não é?
Vou escrever a letra L nesta tela (Figura 4).
Olhe para o slide e tente responder: o que acontece se invertermos as linhas? Ou seja, o que acontece se a linha 0 se tornar a linha 9, a linha 1 se tornar a linha 8, e assim por diante?
Veja agora!
Isso mesmo, ao inverter o array mais externo, inverte-se a imagem verticalmente.
Agora, preste atenção e responda: o que acontece se não alterarmos a ordem das linhas, mas invertermos a ordem dos elementos de cada uma das linhas individualmente?
Obviamente, se invertermos as duas primeiras linhas, não veremos efeito algum. Mas veja só o que acontece se invertermos a terceira linha.
Nada também! Isto porque a linha é simétrica. Fazendo um paralelo com strings, é como se tivéssemos um palíndromo onde a inversão da palavra é idêntica à palavra original. O mesmo acontece com a inversão da linha 3.
Porém, observe o que acontece se invertermos a ordem dos elementos da linha 4.
Notou a diferença? Vou continuar invertendo as linhas seguintes, ou seja, as linhas 5, 6 e 7.
Ao inverter a ordem dos elementos de cada uma das linhas individualmente, inverto a imagem horizontalmente. Legal, não acha?
Você aprendeu a inverter uma imagem verticalmente e horizontalmente, veja como fica o programa que faz essa inversão. Na aula de arrays, você aprendeu a invertê-los usando a função reverse e a aplicar uma mesma função a todos os elementos de um array usando a função map. Começo apresentando no exemplo uma solução que utiliza essas funções. No entanto, também irei mostrar uma implementação recursiva dessa solução. Vamos lá!
Código 1 - 14_7 Inverter Imagem.htmlPara esse exemplo fiz uma imagem com L, usando ASCII mesmo.
No JavaScript, para esse trecho do código (Linhas 2 a 13) criei um array de arrays, onde cada um deles tem a mesma quantidade de caracteres.
Caso deseje, você pode olhar o código fonte pra ver como foi criada essa imagem.
Voltando para a página, na Figura 9, tenho dois botões, um que inverte na vertical, como mostra a Figura 11, ou seja, o L sobe e desce.
E outro que inverte na horizontal, que espelha o L, como mostra a Figura 12.
Então, no meu HTML tem o "resultado" (linha 20) que eu estou escrevendo aquela imagem do L. Tem dois botões: INVERTER HORIZONTAL e INVERTER VERTICAL. O primeiro chama a função inverter_h, o segundo, a função inverter_v.
No JavaScript, vamos primeiro ver a solução mais elegante, já que temos uma, e depois apresento a solução recursiva para que você veja como podemos fazer isso de maneira recursiva.
Na linha 17, o inverter_h, inverte horizontalmente, aplicando a todos os elementos da matriz na primeira dimensão do array, onde cada elemento é um array, a função inverter. Fazendo isso, estou invertendo a imagem de maneira horizontal. Em seguida, peço para exibir a matriz na tela (linha 19). Essa função inverter nada mais é do que aplicar um reverse ao array (Linha 26).
Na linha 21, em inverter_v, inverto a matriz como um todo verticalmente. Ou seja, eu inverto a ordem dos elementos invertendo a tela de maneira vertical (linha 22).
Essa solução é a que acabamos de ver, que funciona perfeitamente na página HTML, no início do exemplo.
Agora, a gente vai passar para a versão recursiva dessa solução, nela, eu criei funções que terminam com _rec: inverter_h_rec, inverter_v_rec, tá certo?
A maneira recursiva funciona do mesmo modo na página HTML, tá certo? E como fazemos isso? Primeiro, vamos ver a inversão horizontal iterativa.
Na linha 30, para inverter horizontalmente, eu uso o inverter_h_rec. Na linha 31, para todo elemento da tela, digo que ele é o inverter_rec dele (linha 32), tá certo? Ou seja, tenho uma versão iterativa para passar em todos os elementos da tela, e vou aplicar uma inversão recursiva naquele array, tá certo?
O inverter_v_rec é a inversão recursiva dos elementos. E como faço a versão recursiva de inverter um array? Bom, para inverter um array, tenho uma variável de retorno (linha 43), e, se eu cheguei no caso base, o meu retorno é vazio, ou seja, se o a.length for igual a 0, meu retorno é vazio. Caso contrário, eu faço a inversão do resto (Linha 48) e concateno no final o primeiro elemento (linha 49).
Vejam que, na linha 48, eu faço a.slice(1), ou seja, pego o resto do array e chamo a função inverter nele (linha 48). Só depois eu pego o primeiro elemento do array e coloco no final do retorno usando o retorno.push(a[0]) (linha 49).
Já vimos uma versão iterativa para exibir a matriz, mas agora a gente vai ver uma solução recursiva. E para que a nossa imagem na página fique mais bonitinha, ou seja, apareça apenas a imagem, vou tirar os colchetes e as vírgulas entre os elementos, tá certo?
Para exibir a matriz, o que eu faço? Bom, se a matriz chegou ao final, ou seja, no caso base, se o tamanho da matriz for 0, não tenho mais nada para exibir, simplesmente tenho que minha resposta é uma string vazia (linha 61). Caso contrário, vou exibir a matriz[0], ou seja, a primeira linha e depois o resto da matriz. E como é o resto da matriz? A matriz.slice(1). Então, é uma função recursiva que vai exibir a primeira linha e vai chamar a mesma função para o resto, em seguida vai exibir a segunda linha até chegar no final, quando ela for vazia, coloca a string vazia.
Na linha 69, temos exibirLinha, que é bem parecido. Para exibir um array de maneira recursiva, se linha.length for igual a 0, tenho vazio, se não, exibo o primeiro elemento dessa linha, linha[0] (linha 75), depois chamo a função para exibir a calda do array, ou seja linha.slice(1) (Linha 76), tá certo?
Existem diversos "truques" de programação que fazem com que as imagens se movimentem na tela e, para isso, geralmente, utilizam-se funções matemáticas. Esse é um bom exemplo da importância do conhecimento matemático para a programação.
Versão 5.3 - Todos os Direitos reservados