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.
import turtle

def tabuleiro(n):
    """Desenha um tabuleiro tipo xadrez de ordem n."""
    for i in range(1,n+1):
        # desenha linha i
        pass
        
        
if __name__ == '__main__':
    tabuleiro(4)
    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!
import turtle

def tabuleiro(n):
    """Desenha um tabuleiro tipo xadrez de ordem n."""
    for i in range(1,n+1):
        # desenha linha i
        for j in range(1,n+1):
            #desenha quadrado j da linha i
            pass
        
        
if __name__ == '__main__':
    tabuleiro(4)
    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.
def quadrado(posx,posy,lado):
    turtle.showturtle()
    turtle.penup()
    turtle.goto(posx,posy)
    turtle.pendown()    
    for i in range(4):
        turtle.forward(lado)
        turtle.left(90)
    turtle.hideturtle()
Agora, vamos completar o programa principal.
def tabuleiro(posx,posy,lado,n):
    """Desenha um tabuleiro tipo xadrez de ordem n."""
    #posição inicial
    turtle.penup()
    turtle.goto(posx,posy)
    turtle.pendown()     
    for i in range(1,n+1):
        # desenha linha i
        for j in range(1,n+1):
            #desenha quadrado j da linha i
            quadrado(turtle.xcor(), turtle.ycor(),lado)
            # -- posiciona para próximo
            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.
def tabuleiro(posx,posy,lado,n):
    """Desenha um tabuleiro tipo xadrez de ordem n."""
    #posição inicial
    turtle.penup()
    turtle.goto(posx,posy)
    turtle.pendown()     
    for i in range(1,n+1):
        # desenha linha i
        for j in range(1,n+1):
            #desenha quadrado j da linha i
            quadrado(turtle.xcor(), turtle.ycor(),lado)
            # -- posiciona para próximo
            turtle.setx(turtle.xcor()+lado)
        # posição nova linha
        turtle.penup()
        turtle.goto(posx,turtle.ycor()+ lado)
        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.
def quadrado(posx,posy,lado,cor):
    turtle.showturtle()
    turtle.penup()
    turtle.goto(posx,posy)
    turtle.pendown()
    turtle.fillcolor(cor)
    turtle.begin_fill()
    for i in range(4):
        turtle.forward(lado)
        turtle.left(90)
    turtle.end_fill()
    turtle.hideturtle()
Sabendo desenhar um quadrado colorido o resto já não nos incomoda muito.
def tabuleiro(posx,posy,lado,n):
    """Desenha um tabuleiro tipo xadrez de ordem n."""
    #posição inicial
    turtle.penup()
    turtle.goto(posx,posy)
    turtle.pendown()     
    for i in range(1,n+1):
        # desenha linha i
        for j in range(1,n+1):
            #desenha quadrado j da linha i
            if j % 2 == 0:
                # desenha quadrado j
                quadrado(turtle.xcor(),turtle.ycor(),lado,'white')
            else:
                quadrado(turtle.xcor(),turtle.ycor(),lado,'black')            
            # -- posiciona para próximo
            turtle.setx(turtle.xcor()+lado)
        # posição nova linha
        turtle.penup()
        turtle.goto(posx,turtle.ycor()+ lado)
        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:
import turtle

def quadrado(posx,posy,lado,cor):
    turtle.showturtle()
    turtle.penup()
    turtle.goto(posx,posy)
    turtle.pendown()
    turtle.fillcolor(cor)
    turtle.begin_fill()
    for i in range(4):
        turtle.forward(lado)
        turtle.left(90)
    turtle.end_fill()
    turtle.hideturtle()
    
def tabuleiro(posx,posy, lado,n,cor_1, cor_2):
    """Desenha um tabuleiro de xadrez."""
    for i in range(n):
        #desenha linha n
        # -- posiciona
        turtle.penup()
        turtle.goto(posx, i*lado)
        turtle.pendown()
        # --- escolhe cor
        if i % 2 == 0:
            primo = cor_1
            segundo = cor_2
        else:
            primo = cor_2
            segundo = cor_1
        # --- desenha
        for j in range(n):
            if j % 2 == 0:
                # desenha quadrado j
                quadrado(turtle.xcor(),turtle.ycor(),lado,primo)
            else:
                quadrado(turtle.xcor(),turtle.ycor(),lado,segundo)
            # posiciona
            turtle.penup()
            turtle.setx(turtle.xcor()+lado)
            turtle.pendown()
    
        
if __name__ == '__main__':
    tabuleiro(0,0,20,4, 'white','black')
    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