terça-feira, 24 de novembro de 2009

Problema 7.2

O enunciado do problema diz o seguinte:

Pretende colorir o chão da sua cozinha com quadrados coloridos. As cores devem ser colocadas de acordo com um padrão. A figura abaixo mostra um exemplo possível. A escolha das duas cores é sua!



Vamos reflectir. Olhando para a figura acima vemos que existe um padrão: os quadrados são colocados de modo alternado. Por outro lado, como é dito no enunciado, as formas são quadradas. Finalmente, embora na imagem a cozinha tenha uma dimensão 4 x 3, nó queremos uma solução geral, ou seja, para cozinhas de dimensão n x m. Do ponto de vista informático o que precisamos fazer? De acordo com o princípio geral deste tipo de aplicações vamos ter que responder a três sub-problemas:

(1) Definir uma janela onde possam ser colocados os azulejos;
(2) Gerar os quadrados de duas cores
(3) Posicionar os quadrados e mostrar na janela

A primeira questão, obriga-nos a saber a dimensão dos quadrados e as dimensões n x m da cozinha. Claro que as duas cores também são importantes. Mas disso trataremos de seguida. Daí o nosso programa principal poder ser definido do seguinte modo:

1.def main1(nx,ny,lado,cores):
2.    janela = cImage.ImageWin('Ladrilhos',nx * lado, ny*lado)
3.    # -- resto do programa  a definir aqui
4.    janela.exitOnclick()

A segunda questão, remete para a geração de quadrados coloridos. Trata-se de uma questão geral, pelo que a solução para o problema de gerar quadrados de duas cores diferentes pode ser resolvido por um único programa:
01.def quadrado(lado,cor):
02.    """
03.    Cria um quadrado colorido de lado.
04.    """
05.    imagem = cImage.EmptyImage(lado,lado)
06.    pixel = cImage.Pixel(cor[0],cor[1],cor[2])
07.    for linha in range(lado): 
08.        for coluna in range(lado):
09.            imagem.setPixel(coluna,linha,pixel)      
10.    return imagem


Como se pode ver, começamos por criar uma imagem vazia, com as dimensões apropriadas. Depois definimos um pixel com a cor apropriada. A indicação da cor é dada por um tuplo com os valores (r,g,b). Finalmente, colocamos o pixel em cada ponto da imagem.

Falta agora a parte mais difícil, a questão três: posicionar os quadrados e mostrar a imagem. Pensemos um pouco e olhemos para a figura, que ilustra o caso de quadrados 2 x 2, para serem colocados numa cozinha 4 x 3:




Os círculos alaranjados indicam os pontos onde cada quadrado deve começar a ser desenhado. Correspondem aos índices de uma matriz 4 x 3. (0,0), (1,0), (2,0) ....É aí que devemos colocar as imagens. Mas, é claro, que neste caso estes pontos estão afastados entre si do valor do lado. Assim, na realidade, em termos da imagem, esses pontos são (0,0), (lado,0), (2*lado, 0), ..... Assim o problema reduz-se a colocar 4 x 3 = 12 imagens nas posições referidas. Isso faz-se com dois ciclos for, um dentro do outro que são gerados os índices da matriz, calculando-se em função deles o posicionamento na imagem. Para simplificar admitamos, por agora, que os quadrados são todos da mesma cor:

1.def cozinha_mono(nx,ny,lado, cor, janela):
2.    """ Desenha os azulejos todos da mesma cor."""
3.    for coluna in range(nx):
4.        for linha in range(ny):
5.            imagem = quadrado(lado, cor)
6.            imagem.setPosition(coluna * lado,linha * lado)
7.            imagem.draw(janela)

Se executarmos o programa apenas vemos desenhar uma cozinha com o chão todo da mesma cor. Não é muito impressionante! Então com alternar entre duas cores?? Um modo possível é notar que a soma das posições (x,y) do canto superior esquerdo das imagens são, alternadamente, pares e ímpares. E sabermos como determinar se um número é par. Logo:
01.def cozinha_poli(nx,ny,lado, cores, janela):
02.    """ Desenha os azulejos com duas cores alternadas."""
03.    for coluna in range(nx):
04.        for linha in range(ny):
05.            if (coluna + linha)%2 == 0:
06.                # par
07.                imagem = quadrado(lado, cores[0])
08.            else:
09.                # ímpar
10.                imagem = quadrado(lado, cores[1])
11.                 
12.            imagem.setPosition(coluna * lado,linha * lado)
13.            imagem.draw(janela)

Juntando agora todas as peças temos o programa completo:

01.import cImage
02. 
03.def cozinha_mono(nx,ny,lado, cor, janela):
04.    """ Desenha os azulejos todos da mesma cor."""
05.    for coluna in range(nx):
06.        for linha in range(ny):
07.            imagem = quadrado(lado, cor)
08.            imagem.setPosition(coluna * lado,linha * lado)
09.            imagem.draw(janela)
10. 
11.def cozinha_poli(nx,ny,lado, cores, janela):
12.    """ Desenha os azulejos com duas cores alternadas."""
13.    for coluna in range(nx):
14.        for linha in range(ny):
15.            if (coluna + linha)%2 == 0:
16.                # par
17.                imagem = quadrado(lado, cores[0])
18.            else:
19.                # ímpar
20.                imagem = quadrado(lado, cores[1])
21.                 
22.            imagem.setPosition(coluna * lado,linha * lado)
23.            imagem.draw(janela)
24.                 
25.def quadrado(lado,cor):
26.    """
27.    Cria um quadrado colorido de lado.
28.    """
29.    imagem = cImage.EmptyImage(lado,lado)
30.    pixel = cImage.Pixel(cor[0],cor[1],cor[2])
31.    for linha in range(lado): 
32.        for coluna in range(lado):
33.            imagem.setPixel(coluna,linha,pixel)      
34.    return imagem
35. 
36.def main1(nx,ny,lado,cores):
37.    janela = cImage.ImageWin('Ladrilhos',nx * lado, ny*lado)
38.    cozinha_poli(nx,ny,lado,cores, janela)
39.    janela.exitOnClick()
40.     
41.if __name__=='__main__':
42.    main1(4,3,50,[(255,0,0),(0,0,255)])

Se quisermos variar nas cores e ter alguma surpresa basta fazer uma pequena mudança no programa principal:
01.def main2(nx,ny,lado):
02.    janela = cImage.ImageWin('Ladrilhos',nx * lado, ny*lado)
03.    # escolhe cores aleatoriamente
04.    cores= []
05.    for i in range(2):
06.        r = random.randint(0,255)
07.        g= random.randint(0,255)
08.        b = random.randint(0,255)
09.        while (r,g,b) in cores:
10.            r = random.randint(0,255)
11.            g= random.randint(0,255)
12.            b = random.randint(0,255)
13.        cores.append((r,g,b))
14.             
15.    cozinha_poli(nx,ny,lado,cores, janela)
16.    janela.exitOnClick()


Os mais puristas poderão criar um programa à parte para produzir uma lista de cores diferentes de tamanho variável:
01.def gera_cores(n):
02.    “”” Gera uma lista de n cores.”””
03.    cores= []
04.    for i in range(n):
05.        r = random.randint(0,255)
06.        g= random.randint(0,255)
07.        b = random.randint(0,255)
08.        while (r,g,b) in cores:
09.            r = random.randint(0,255)
10.            g= random.randint(0,255)
11.            b = random.randint(0,255)
12.        cores.append((r,g,b))

Sem comentários:

Enviar um comentário