Acontecem coisas fantásticas nos testes como, por exemplo ter que desenhar um lindo farol como o da figura.
Quando olhamos para o problema diante de nós ele parece muito complexo. Então para melhor dominar a complexidade vamos dividir o nosso problema em sub-problemas e vamos começar por esquecer alguns detalhes. Depois, com calma, havemos de chegar ao resultado pretendido, ou mesmo superar o que era pedido!
Então, ao olhar para o desenho, o que vemos? Um farol formado por duas componentes: uma torre e uma luz no cimo da torre. Elas não são completamente independentes pois a posição da torre condiciona a posição da luz. Mas vamos esquecer isso tudo para já e pensar apenas na decomposição.
""" Farol."""
import turtle
def farol():
# torre
# luz
pass
if __name__ == '__main__':
pass
É bizarro mas este programa até pode ser executado... embora não faça nada.
Vamos agora concentrarmo-nos no desenho da torre. Uma vez mais, quando olhamos o que vemos? Elementos com a forma de
quadrados uns em cima dos outros. E que mais? Bom, o tamanho do quadrado diminui à medida que se sobe e as cores vão alternando entre o vermelho e o branco. Significa isto que se tivermos código que nos permita desenhar um quadrado, na posição da tartaruga, com um dado determinado e uma certa cor podemos ter a nova vida facilitada. Vamos então a isso e fixemos a cor vermelha.
""" Desenha um quadrado vermelho de um certo tamanho numa dada posição."""
# Prepara
turtle.fillcolor(‘red’)
turtle.begin_fill()
# Desenha quadrado
for i in range(4):
turtle.forward(tamanho)
turtle.left(90)
turtle.end_fill()
Este código funciona um pouco como um
bloco construtor. Vamos usá-lo então para desenhar a torre. Não nos custa perceber que vamos repetir um certo número de vezes o desenho do quadrado. Admitamos para já que nos esquecemos das imposições do problema e nos concentramos apenas na altura.
import turtle
def farol(altura,lado):
# torre
for i in range(altura):
# Desenha quadrado vermelho
turtle.fillcolor('red')
turtle.begin_fill()
for i in range(4):
turtle.forward(lado)
turtle.left(90)
turtle.end_fill()
# luz
pass
if __name__ == '__main__':
farol(3,50)
turtle.exitonclick()
Como se vê começam a aparecer os
parâmetros formais (altura, tamanho do lado). Usando o bloco construtor embebido num ciclo
for mandamos desenhar a torre. Mas se corrermos o código o resultado é decepcionante. Em vez de uma torre um único quadrado. Porquê? É óbvio que nos esquecemos de dizer que a posição dos sucessivos quadrado vai mudando. Como? Bom em relação ao eixo dos
xx (horizontal) é igual, mudando apenas a coordenada dos
yy por um valor igual ao lado.
Lembre-se: estamos para já a esquecer que o lado varia em comprimento em função da altura!!! Alteremos então o código.
import turtle
def farol(altura,lado, posx,posy):
# torre
vai_para(posx, posy)
for i in range(altura):
# quadrado colorido
turtle.fillcolor('red')
turtle.begin_fill()
for i in range(4):
turtle.forward(lado)
turtle.left(90)
turtle.end_fill()
vai_para(turtle.xcor(), turtle.ycor() + lado)
# luz
pass
def vai_para(posx,posy):
""" Vai para (posx, posy) sem deixar rasto."""
turtle.penup()
turtle.goto(posx,posy)
turtle.pendown()
if __name__ == '__main__':
farol(5,50,0,0)
turtle.exitonclick()
E o novo resultado:
Notar que introduzimos um sub-programa (vai_para) para colocar a tartaruga na posição desejada sem deixar rasto enquanto se movimenta. O que pode fazer uma simples alteração do código!!! Só é pena é ser tudo da mesma cor... Então é tempo de pensar um pouco nisso. Numeremos os quadrados como fazemos com as sequências: o da base é o 0, o seguinte o 1 e por aí adiante. Se queremos as cores alternadas então fixemos o vermelho para as posições pares e o branco para as ímpares. Modifiquemos o código por forma a testar se a posição é par ou é ímpar.
def farol(altura,lado, posx,posy):
# torre
vai_para(posx, posy)
for i in range(altura):
# quadrado colorido
if i % 2 == 0: # <-- par?
turtle.fillcolor('red')
else:
turtle.fillcolor('white')
turtle.begin_fill()
for i in range(4):
turtle.forward(lado)
turtle.left(90)
turtle.end_fill()
vai_para(turtle.xcor(), turtle.ycor() + lado)
# luz
pass
Façamos o boneco de novo.
Fantástico, não é? Agora ... faça-se
luz. Vamos escrever código para desenhar um semi-círculo amarelo com um dado raio, no topo da torre e acrescentar ao programa.
def farol(altura,lado, posx,posy):
# torre
vai_para(posx, posy)
for i in range(altura):
# quadrado colorido
if i % 2 == 0:
turtle.fillcolor('red')
else:
turtle.fillcolor('white')
turtle.begin_fill()
for i in range(4):
turtle.forward(lado)
turtle.left(90)
turtle.end_fill()
vai_para(turtle.xcor(), turtle.ycor() + lado)
# luz
turtle.forward(lado)
turtle.setheading(90) # <--- Atenção!
turtle.fillcolor('yellow')
turtle.begin_fill()
turtle.circle(lado/2,180)
turtle.end_fill()
Toca a executar.
Notar como foi resolvido o problema da orientação do semi-círculo.
Quase pronto. Falta o detalhe dos quadrados a decrescer de um certo valor, a que chamaremos
decremento. Pensemos um pouco. Se cada vez que subimos um degrau o lado decresce de um valor (decremento) e os quadrados têm que estar centrados, onde devemos colocar a tartaruga a cada etapa? E como mudamos o valor do lado? Em que zona do código fazemos as alterações? Não é difícil perceber que só temos que fazer avançar o valor da coordenada
xx e diminuir o tamanho do lado. Eis a nova solução.
def farol(altura,lado, posx,posy, decremento):
# torre
vai_para(posx, posy)
for i in range(altura):
# quadrado colorido
if i % 2 == 0:
turtle.fillcolor('red')
else:
turtle.fillcolor('white')
turtle.begin_fill()
for i in range(4):
turtle.forward(lado)
turtle.left(90)
turtle.end_fill()
vai_para(turtle.xcor() + decremento/2, turtle.ycor() + lado) # <-- Eureka!
lado = lado - decremento # <--- Eureka (2)
# luz
turtle.forward(lado)
turtle.setheading(90)
turtle.fillcolor('yellow')
turtle.begin_fill()
turtle.circle(lado/2,180)
turtle.end_fill()
turtle.hideturtle()
E já está!!! Fácil, não é?? Notar o aparecimento do novo parâmetro decremento e a instrução para esconder a tartaruga no final. O boneco é igual ao primeiro que mostrámos...
Vamos à
moral da história. Um problema relativamente difícil pode tornar-se mais simples dividindo-o em sub-problemas mais simples e abordando as especificações em sequência.
Muitas vezes (sempre?) quando acabamos de resolver um problema olhamos para o código e pensamos: posso melhorar o código (elegância, legibilidade,...), posso usá-lo noutros problemas? Uma modificação simples que podemos fazer é alterar o código para que as cores não sejam fixas. Uma espécie de
farol UCB.
import turtle
def farol(altura,lado, posx,posy, decremento, cor_1,cor_2,cor_3):
# torre
vai_para(posx, posy)
for i in range(altura):
# quadrado colorido
if i % 2 == 0:
turtle.fillcolor(cor_1)
else:
turtle.fillcolor(cor_2)
turtle.begin_fill()
for i in range(4):
turtle.forward(lado)
turtle.left(90)
turtle.end_fill()
vai_para(turtle.xcor() + decremento/2, turtle.ycor() + lado)
lado = lado - decremento
# luz
turtle.forward(lado)
turtle.setheading(90)
turtle.fillcolor(cor_3)
turtle.begin_fill()
turtle.circle(lado/2,180)
turtle.end_fill()
turtle.hideturtle()
def vai_para(posx,posy):
""" Vai para (posx, posy) sem deixar rasto."""
turtle.penup()
turtle.goto(posx,posy)
turtle.pendown()
if __name__ == '__main__':
farol(5,100,0,0,10,'blue', 'green', 'orange')
turtle.exitonclick()
Ei-lo:
That’s all folks!!
Sem comentários:
Enviar um comentário