domingo, 17 de novembro de 2013

Olhar e ver (IV)

Hoje volto a um exemplo com o módulo turtle e com quadrados. Podem pensar que é obsessão minha, e se calhar é. Então agora é o seguinte: escrever um programa que nos permita desenhar um lindo tabuleiro, semelhante ao de xadrez (ou damas, ou,...), mas podendo ter qualquer dimensão.
A ideia é partir do zero (embora saiba que já fizemos muita coisa parecida,...). A tendência natural é começarmos a pensar como é que vou conseguir aquele efeito das cores alternadas? A minha resposta inicial a essa questão é: não vou fazer. Vou desenhar um tabuleiro com quadrados todos brancos. Depois se verá. E mais? Voltamos ao tema olhar e ver: para mim tenho linhas de quadrados, todas do mesmo comprimento!!! Então tomo a primeira decisão: vou desenhar linha a linha.
01.import turtle
02. 
03.def tabuleiro(n):
04.    """Desenha um tabuleiro tipo xadrez de ordem n."""
05.    for i in range(1,n+1):
06.        # desenha linha i
07.        pass
08.         
09.         
10.if __name__ == '__main__':
11.    tabuleiro(4)
12.    turtle.exitonclick()
Este programa fantástico não faz (quase) nada. Bem, sempre mostra uma janela em branco. Agora: o que significa desenhar uma linha? Bem, significa ... desenhar n quadrados!
01.import turtle
02. 
03.def tabuleiro(n):
04.    """Desenha um tabuleiro tipo xadrez de ordem n."""
05.    for i in range(1,n+1):
06.        # desenha linha i
07.        for j in range(1,n+1):
08.            #desenha quadrado j da linha i
09.            pass
10.         
11.         
12.if __name__ == '__main__':
13.    tabuleiro(4)
14.    turtle.exitonclick()
Mais um pequeno passo para o resultado final. E agora aparece um ponto importante: desenhar um quadrado. Precisamos dessa função. Mas não chega, pois os quadrados são desenhados em posições diferentes. E aqui temos que tomar outra decisão importante. Como controlar a posição de cada quadrado??? A ideia óbvia é fazer uma função que desenhe um quadrado numa dada posição, algo que já fizemos por diversas vezes.
01.def quadrado(posx,posy,lado):
02.    turtle.showturtle()
03.    turtle.penup()
04.    turtle.goto(posx,posy)
05.    turtle.pendown()   
06.    for i in range(4):
07.        turtle.forward(lado)
08.        turtle.left(90)
09.    turtle.hideturtle()
Agora, vamos completar o programa principal.
01.def tabuleiro(posx,posy,lado,n):
02.    """Desenha um tabuleiro tipo xadrez de ordem n."""
03.    #posição inicial
04.    turtle.penup()
05.    turtle.goto(posx,posy)
06.    turtle.pendown()    
07.    for i in range(1,n+1):
08.        # desenha linha i
09.        for j in range(1,n+1):
10.            #desenha quadrado j da linha i
11.            quadrado(turtle.xcor(), turtle.ycor(),lado)
12.            # -- posiciona para próximo
13.            turtle.setx(turtle.xcor()+lado)
Se executarmos este código o que acontece? É tudo desenhado na mesma linha!! Razão: não actualizamos as coordenadas para o início de cada linha. Vamos a isso.
01.def tabuleiro(posx,posy,lado,n):
02.    """Desenha um tabuleiro tipo xadrez de ordem n."""
03.    #posição inicial
04.    turtle.penup()
05.    turtle.goto(posx,posy)
06.    turtle.pendown()    
07.    for i in range(1,n+1):
08.        # desenha linha i
09.        for j in range(1,n+1):
10.            #desenha quadrado j da linha i
11.            quadrado(turtle.xcor(), turtle.ycor(),lado)
12.            # -- posiciona para próximo
13.            turtle.setx(turtle.xcor()+lado)
14.        # posição nova linha
15.        turtle.penup()
16.        turtle.goto(posx,turtle.ycor()+ lado)
17.        turtle.pendown()       
Notar que a posição inicial no eixo dos xx é sempre a mesma (isto não é uma pirâmide!!). Só a posição do eixo dos yy deve ser incrementada do valor do lado em cada ciclo. Executando o programa completo eis o nosso tabuleiro.
E pronto, já está! Mas, espere. E a cor?? Oops, já me esquecia. Bom vamos lá às linhas e alternar a cor entre o branco e o preto. Uma solução simples passa por associar a cor ao facto de a coluna ter um índice par ou ímpar. Mas temos que alterar também a definição do quadrado.
01.def quadrado(posx,posy,lado,cor):
02.    turtle.showturtle()
03.    turtle.penup()
04.    turtle.goto(posx,posy)
05.    turtle.pendown()
06.    turtle.fillcolor(cor)
07.    turtle.begin_fill()
08.    for i in range(4):
09.        turtle.forward(lado)
10.        turtle.left(90)
11.    turtle.end_fill()
12.    turtle.hideturtle()
Sabendo desenhar um quadrado colorido o resto já não nos incomoda muito.
01.def tabuleiro(posx,posy,lado,n):
02.    """Desenha um tabuleiro tipo xadrez de ordem n."""
03.    #posição inicial
04.    turtle.penup()
05.    turtle.goto(posx,posy)
06.    turtle.pendown()    
07.    for i in range(1,n+1):
08.        # desenha linha i
09.        for j in range(1,n+1):
10.            #desenha quadrado j da linha i
11.            if j % 2 == 0:
12.                # desenha quadrado j
13.                quadrado(turtle.xcor(),turtle.ycor(),lado,'white')
14.            else:
15.                quadrado(turtle.xcor(),turtle.ycor(),lado,'black')           
16.            # -- posiciona para próximo
17.            turtle.setx(turtle.xcor()+lado)
18.        # posição nova linha
19.        turtle.penup()
20.        turtle.goto(posx,turtle.ycor()+ lado)
21.        turtle.pendown()  
Executando o novo programa obtemos, para um tabuleiro 4X4:
Não é bem o que queremos, mas está lá perto! Não tenho dúvidas que todos já antecipavam este desfecho. Afinal, é preciso alternar a cor que começa em cada linha. Vamos então concluir o programa corrigindo essa deficiência. A solução é do tipo da anterior: em cada linha trocamos as cores. Eis o produto acabado:
01.import turtle
02. 
03.def quadrado(posx,posy,lado,cor):
04.    turtle.showturtle()
05.    turtle.penup()
06.    turtle.goto(posx,posy)
07.    turtle.pendown()
08.    turtle.fillcolor(cor)
09.    turtle.begin_fill()
10.    for i in range(4):
11.        turtle.forward(lado)
12.        turtle.left(90)
13.    turtle.end_fill()
14.    turtle.hideturtle()
15.     
16.def tabuleiro(posx,posy, lado,n,cor_1, cor_2):
17.    """Desenha um tabuleiro de xadrez."""
18.    for i in range(n):
19.        #desenha linha n
20.        # -- posiciona
21.        turtle.penup()
22.        turtle.goto(posx, i*lado)
23.        turtle.pendown()
24.        # --- escolhe cor
25.        if i % 2 == 0:
26.            primo = cor_1
27.            segundo = cor_2
28.        else:
29.            primo = cor_2
30.            segundo = cor_1
31.        # --- desenha
32.        for j in range(n):
33.            if j % 2 == 0:
34.                # desenha quadrado j
35.                quadrado(turtle.xcor(),turtle.ycor(),lado,primo)
36.            else:
37.                quadrado(turtle.xcor(),turtle.ycor(),lado,segundo)
38.            # posiciona
39.            turtle.penup()
40.            turtle.setx(turtle.xcor()+lado)
41.            turtle.pendown()
42.     
43.         
44.if __name__ == '__main__':
45.    tabuleiro(0,0,20,4, 'white','black')
46.    turtle.exitonclick()
E pronto. Agora até pode brincar usando um par de cores diversa. Mas não se esqueça da mensagem principal: se está com dificuldades em resolver o seu problema, tente resolver um semelhante mas mais simples. Depois vá melhorando a solução provisória até chegar à solução pretendida.

Sem comentários:

Enviar um comentário