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:


def main1(nx,ny,lado,cores):
janela = cImage.ImageWin('Ladrilhos',nx * lado, ny*lado)
# -- resto do programa a definir aqui
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:

def quadrado(lado,cor):
"""
Cria um quadrado colorido de lado.
"""
imagem = cImage.EmptyImage(lado,lado)
pixel = cImage.Pixel(cor[0],cor[1],cor[2])
for linha in range(lado):
for coluna in range(lado):
imagem.setPixel(coluna,linha,pixel)
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:


def cozinha_mono(nx,ny,lado, cor, janela):
""" Desenha os azulejos todos da mesma cor."""
for coluna in range(nx):
for linha in range(ny):
imagem = quadrado(lado, cor)
imagem.setPosition(coluna * lado,linha * lado)
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:

def cozinha_poli(nx,ny,lado, cores, janela):
""" Desenha os azulejos com duas cores alternadas."""
for coluna in range(nx):
for linha in range(ny):
if (coluna + linha)%2 == 0:
# par
imagem = quadrado(lado, cores[0])
else:
# ímpar
imagem = quadrado(lado, cores[1])

imagem.setPosition(coluna * lado,linha * lado)
imagem.draw(janela)

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


import cImage

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

def cozinha_poli(nx,ny,lado, cores, janela):
""" Desenha os azulejos com duas cores alternadas."""
for coluna in range(nx):
for linha in range(ny):
if (coluna + linha)%2 == 0:
# par
imagem = quadrado(lado, cores[0])
else:
# ímpar
imagem = quadrado(lado, cores[1])

imagem.setPosition(coluna * lado,linha * lado)
imagem.draw(janela)

def quadrado(lado,cor):
"""
Cria um quadrado colorido de lado.
"""
imagem = cImage.EmptyImage(lado,lado)
pixel = cImage.Pixel(cor[0],cor[1],cor[2])
for linha in range(lado):
for coluna in range(lado):
imagem.setPixel(coluna,linha,pixel)
return imagem

def main1(nx,ny,lado,cores):
janela = cImage.ImageWin('Ladrilhos',nx * lado, ny*lado)
cozinha_poli(nx,ny,lado,cores, janela)
janela.exitOnClick()

if __name__=='__main__':
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:

def main2(nx,ny,lado):
janela = cImage.ImageWin('Ladrilhos',nx * lado, ny*lado)
# escolhe cores aleatoriamente
cores= []
for i in range(2):
r = random.randint(0,255)
g= random.randint(0,255)
b = random.randint(0,255)
while (r,g,b) in cores:
r = random.randint(0,255)
g= random.randint(0,255)
b = random.randint(0,255)
cores.append((r,g,b))

cozinha_poli(nx,ny,lado,cores, janela)
janela.exitOnClick()


Os mais puristas poderão criar um programa à parte para produzir uma lista de cores diferentes de tamanho variável:

def gera_cores(n):
“”” Gera uma lista de n cores.”””
cores= []
for i in range(n):
r = random.randint(0,255)
g= random.randint(0,255)
b = random.randint(0,255)
while (r,g,b) in cores:
r = random.randint(0,255)
g= random.randint(0,255)
b = random.randint(0,255)
cores.append((r,g,b))

Sem comentários:

Enviar um comentário