import turtle def grelha_1(dim, lado): """ Solução básica.""" # verticais turtle.setheading(90) for i in range(dim+1): # posiciona turtle.penup() turtle.goto(i * lado,0) turtle.pendown() # desenha turtle.forward(dim*lado) # horizontais turtle.setheading(0) for i in range(dim+1): # posiciona turtle.penup() turtle.goto(0,i*lado) turtle.pendown() # desenha turtle.forward(dim*lado) turtle.hideturtle()Como se pode ver as linhas são desenhadas em separado e cada tipo de linha (verticais ou horizontais) é desenhada no interior de um ciclo. A parte relevante em cada ciclo é o posicionamento da tartaruga para desenhar a linha. Fazemos isso através de um goto.
Uma primeira alteração possível é considerar a possibilidade de controlar a localização do canto inferior esquerdo. Vejamos como se pode fazer.
def grelha_2(dim, lado,pos_x,pos_y): """ Controlando a posição do canto inferior esquerdo.""" # verticais turtle.setheading(90) for i in range(dim+1): # posiciona turtle.penup() turtle.goto(pos_x + i * lado,pos_y) turtle.pendown() # desenha turtle.forward(dim*lado) # horizontais turtle.setheading(0) for i in range(dim+1): # posiciona turtle.penup() turtle.goto(pos_x,pos_y+i*lado) turtle.pendown() # desenha turtle.forward(dim*lado) turtle.hideturtle()Como se notará a alteração é mínima, e traduz-se a colocar o valor das coordenadas do canto inferior esquerdo no sítio certo.
Suponhamos agora que nos pedem uma solução em que seja também possível controlar a orientação do quadrado. Esta questão já obriga a uma ginástica adicional, mas a questão central mantém-se a mesma: definir os pontos em que se iniciam as linhas. Eis uma solução, não muito elegante, mas que funciona…
def grelha_4(dim, lado,pos_x,pos_y,orient): """ Controlando a posição e a orientação. """ # verticais for i in range(dim+1): # posiciona turtle.penup() turtle.goto(pos_x,pos_y) turtle.setheading(orient) turtle.forward(i*lado) turtle.setheading(90+orient) turtle.pendown() # desenha turtle.forward(dim*lado) # horizontais for i in range(dim+1): # posiciona turtle.penup() turtle.goto(pos_x,pos_y) turtle.setheading(90+orient) turtle.forward(i*lado) turtle.setheading(orient) turtle.pendown() # desenha turtle.forward(dim*lado) turtle.hideturtle()Outras alterações poderiam ser feitas, como seja mudar a espessura das linhas ou a sua cor. Mas o que não nos agrada é a legibilidade do código. Afinal o nosso ponto de partida foi considerar o desenho da grelha com base no conceito de linha, mas esse conceito está explicitamente ausente nas soluções acima. Vamos remediar a situação definindo uma função que nos permite desenhar uma linha, com uma dada posição inicial uma orientação e um dado comprimento. Não é difícil.
def linha(pos_x,pos_y, orient, tam): # posiciona turtle.penup() turtle.goto(pos_x,pos_y) turtle.setheading(orient) turtle.pendown() # desenha turtle.forward(tam) turtle.hideturtle()Na posse desta nova construção (abstracção), podemos refazer as soluções acima apresentadas. Comecemos pela básica:
def grelha_5(dim, lado): """ Solução básica.""" # horizontais for i in range(dim+1): linha(0,i*lado,0,dim*lado) # verticais for i in range(dim+1): linha(i*lado,0,90,dim*lado) turtle.hideturtle()O leitor concordará que corresponde de modo mais claro à forma como enunciámos a solução. Passemos à posição.
def grelha_6(dim, lado,pos_x,pos_y): """ Solução com controlo da posição do canto inferior esquerdo.""" # horizontais for i in range(dim+1): linha(pos_x,pos_y+i*lado,0,dim*lado) # verticais for i in range(dim+1): linha(pos_x+i*lado,pos_y,90,dim*lado) turtle.hideturtle()Elementar, não acha? Finalmente a orientação. Aqui decidimos usar um pouco dos nossos conhecimentos de trignometria, para definir as novas posições de início das linhas. Na posse deste conhecimento a solução vem, finalmente, como:
import math def grelha_7(dim, lado,pos_x,pos_y,orient): """ Solução com controlo da posição do canto inferior esquerdo e a orientação.""" deg_rad = math.pi/180 # horizontais for i in range(dim+1): linha(pos_x+i*lado*math.cos((orient+90)* deg_rad),pos_y+ i*lado*math.sin((orient+90)* deg_rad),orient,dim*lado) # verticais for i in range(dim+1): linha(pos_x+i*lado*math.cos(orient * deg_rad),pos_y+ i*lado*math.sin(orient * deg_rad),90+orient,dim*lado) turtle.hideturtle()Chegados a este ponto podemos achar que o trabalho está feito e, por isso, podemos passar a outro problema. Mas… e se alguém nos pedir a nossa solução para criar um tabuleiro de xadrez? Precisamos colorir as células, mas como fazer? A dificuldade reside no facto de termos olhado para a grelha não como uma grelha, isto é formada por células justapostas, mas como linhas que se cruzam. E precisamos partir de novo à aventura: criar a dita grelha formada por quadrados. Mas aprendemos algo com o caso anterior, a saber: usar abstração para criar primitivas é positivo.
Para começar precisamos de uma primitiva para desenhar um quadrado:
def quadrado(pos_x, pos_y, lado, orient): # posiciona turtle.penup() turtle.goto(pos_x,pos_y) turtle.setheading(orient) turtle.pendown() # desenha for i in range(4): turtle.forward(lado) turtle.lt(90) turtle.hideturtle()E vamos percorrer de novo a nossa via sacra. Primeiro a versão básica:
def grelha_8(dim, lado): """ Solução básica.""" # Por linhas for i in range(dim): # linha i for j in range(dim): quadrado(j*lado,i*lado,lado,0) turtle.hideturtle()Não muito diferente, certo? Só que agora temos uma perspectiva matricial, pelo que precisamos de um ciclo dentro de outro ciclo. Controlar a posição é trivial:
def grelha_9(dim, lado, pos_x, pos_y): """ Solução com controlo da posição do canto inferior esquerdo.""" # Por linhas for i in range(dim): # linha i for j in range(dim): quadrado(pos_x+j*lado,pos_y+i*lado,lado,0) turtle.hideturtle()A quatro da orientação pede um pouco mais de atenção como na versão anterior, mas a lógica é semelhante: trata-se de definir os pontos iniciais para cada quadrado:
def grelha_10(dim, lado, pos_x, pos_y, orient): """ Solução com controlo da posição do canto inferior esquerdo e da orientação.""" deg_rad = math.pi/180 # Por linhas for i in range(dim): # linha i p_x = pos_x+i*lado*math.cos((orient+90)*deg_rad) p_y = pos_y+i*lado*math.sin((orient+90)*deg_rad) for j in range(dim): quadrado(p_x,p_y,lado,orient) p_x = p_x+lado*math.cos(orient*deg_rad) p_y = p_y+lado * math.sin(orient*deg_rad) turtle.hideturtle()Notar que nesta solução o ciclo interior apenas controla o número de vezes que desenhamos um quadrado numa linha.
. Agora sim podemos dar o trabalho por encerrado!!! Mas, espere aí, ouço-o dizer, a passagem para o ponto de vista das células quadradas não era para termos mais graus de liberdade, nomeadamente em relação à cor dos quadrados??? É verdade sim senhor. Então vamos a isso. A solução mais simples consistirá em poder desenhar quadrados coloridos…
def quadrado_cor(pos_x, pos_y, lado, orient,cor): # cor turtle.color(cor) # posiciona turtle.penup() turtle.goto(pos_x,pos_y) turtle.setheading(orient) turtle.pendown() # desenha turtle.begin_fill() for i in range(4): turtle.forward(lado) turtle.lt(90) turtle.end_fill() turtle.hideturtle()E agora eis o nosso tabuleiro bi-color:
def grelha_11(dim, lado, pos_x, pos_y, orient): """ Solução com controlo da posição do canto inferior esquerdo e da orientação.""" deg_rad = math.pi/180 # Por linhas for i in range(dim): # linha i p_x = pos_x+i*lado*math.cos((orient+90)*deg_rad) p_y = pos_y+i*lado*math.sin((orient+90)*deg_rad) for j in range(dim): if (i+j)%2 == 0: quadrado_cor(p_x,p_y,lado,orient,'black') else: quadrado_cor(p_x,p_y,lado,orient,'gray') p_x = p_x+lado*math.cos(orient*deg_rad) p_y = p_y+lado * math.sin(orient*deg_rad) turtle.hideturtle()Veja apenas como conseguimos o efeito das cores alternadas… Experimente o código e aprecie o resultado. Se quiser outro tipo de tabuleiros coloridos é só adaptar. Agora é mesmo a sua vez de fazer alguma coisa. Eu vou descansar um pouco!
Sem comentários:
Enviar um comentário