Acerca de:

Este blog contiene los códigos, ejemplos y bases de datos que he usado cuando aprendía acerca de algún tema específico. En lugar de borrarlos (una vez dominado ya el tema), he decidido publicarlos :)

sábado, 17 de junio de 2023

Cuadrados recursivos (y con colores) usando la tortuga de Python

Quise jugar un poco más con la recursividad en Python, así que cogí mi código de los arbolitos fractales y lo modifiqué para que dibujara cuadraditos (tuve que hacer unos cálculos en mi cabeza para que los cuadrados pequeños se ubicaran en medio de cada lado del cuadrado más grande):

from operator import length_hint
import turtle as t

def cuadrado(lenght):
    t.forward(lenght)
    t.seth(90)
    t.forward(lenght)
    t.seth(180)
    t.forward(lenght)
    t.seth(270)
    t.forward(lenght)
    t.seth(0)

def drawit2(x, y, lenght):
    if lenght > 5:
        t.penup()
        t.goto(x, y)
        
        if lenght < 20:
            t.color('gray')
        else:
            t.color('black')

        t.pensize(lenght/15)
        t.pendown()
        cuadrado(lenght)
                
        cx = x - lenght / 4
        cy = y + lenght / 4
        drawit2(cx, cy, lenght / 2)
        cx = x + lenght / 4
        cy = y - lenght / 4
        
        drawit2(cx, cy, lenght / 2)
        cx = x + lenght * 3 / 4
        cy = y + lenght / 4
        drawit2(cx, cy, lenght / 2)
        cx = x + lenght / 4
        cy = y + lenght * 3 / 4
        drawit2(cx, cy, lenght / 2)
    else:
        t.hideturtle()
        return 0

lenght = 160
drawit2(0 - lenght / 2, 0 - lenght / 2, 160)
t.mainloop()


Creo que no es necesario el import length_hint, (no recuerdo de qué tutorial lo copié) pero los dibujos tardan su buen rato en terminarse de dibujar, así que al final dejé el import.

El resultado es:



Se ve bien, pero no lo suficiente, hice un pequeño cambio al parámetro que se pasa a la función cuadrado():

from operator import length_hint
import turtle as t

def cuadrado(lenght):
    t.forward(lenght)
    t.seth(90)
    t.forward(lenght)
    t.seth(180)
    t.forward(lenght)
    t.seth(270)
    t.forward(lenght)
    t.seth(0)

def drawit2(x, y, lenght):
    if lenght > 5:
        t.penup()
        t.goto(x, y)
        
        if lenght < 20:
            t.color('gray')
        else:
            t.color('black')

        t.pensize(lenght/15)
        t.pendown()
        cuadrado(lenght - lenght / 10)
                
        cx = x - lenght / 4
        cy = y + lenght / 4
        drawit2(cx, cy, lenght / 2)
        cx = x + lenght / 4
        cy = y - lenght / 4
        
        drawit2(cx, cy, lenght / 2)
        cx = x + lenght * 3 / 4
        cy = y + lenght / 4
        drawit2(cx, cy, lenght / 2)
        cx = x + lenght / 4
        cy = y + lenght * 3 / 4
        drawit2(cx, cy, lenght / 2)
    else:
        t.hideturtle()
        return 0

lenght = 160
drawit2(0 - lenght / 2, 0 - lenght / 2, 160)
t.mainloop()


El resultado es:


Mucho mejor, pero le falta color, el código para el color lo copié de aquí.


from operator import length_hint
import turtle as t
from turtle import*
from random import randint

def cuadrado(lenght):
    color(randint(0, 255), randint(0, 255), randint(0, 255))
    t.forward(lenght)
    t.seth(90)
    t.forward(lenght)
    t.seth(180)
    t.forward(lenght)
    t.seth(270)
    t.forward(lenght)
    t.seth(0)

def drawit2(x, y, lenght):
    if lenght > 5:
        t.penup()
        t.goto(x, y)
        
        t.pensize(lenght/15)
        t.pendown()
        cuadrado(lenght - lenght / 10)
                
        cx = x - lenght / 4
        cy = y + lenght / 4
        drawit2(cx, cy, lenght / 2)
        cx = x + lenght / 4
        cy = y - lenght / 4
        
        drawit2(cx, cy, lenght / 2)
        cx = x + lenght * 3 / 4
        cy = y + lenght / 4
        drawit2(cx, cy, lenght / 2)
        cx = x + lenght / 4
        cy = y + lenght * 3 / 4
        drawit2(cx, cy, lenght / 2)
    else:
        t.hideturtle()
        return 0

lenght = 160
colormode(255)
drawit2(0 - lenght / 2, 0 - lenght / 2, 160)
t.mainloop()


El resultado es:


No está mal, pero esas líneas gruesas del cuadrado grande molestan un poco. Voy a ponder un color distinto a cada línea:

from operator import length_hint
import turtle as t
from turtle import*
from random import randint

def cuadrado(lenght):
    color(randint(0, 255), randint(0, 255), randint(0, 255))
    t.forward(lenght)
    t.seth(90)
    color(randint(0, 255), randint(0, 255), randint(0, 255))
    t.forward(lenght)
    t.seth(180)
    color(randint(0, 255), randint(0, 255), randint(0, 255))
    t.forward(lenght)
    t.seth(270)
    color(randint(0, 255), randint(0, 255), randint(0, 255))
    t.forward(lenght)
    t.seth(0)

def drawit2(x, y, lenght):
    if lenght > 5:
        t.penup()
        t.goto(x, y)
        
        t.pensize(lenght/15)
        t.pendown()
        cuadrado(lenght - lenght / 10)
                
        cx = x - lenght / 4
        cy = y + lenght / 4
        drawit2(cx, cy, lenght / 2)
        cx = x + lenght / 4
        cy = y - lenght / 4
        
        drawit2(cx, cy, lenght / 2)
        cx = x + lenght * 3 / 4
        cy = y + lenght / 4
        drawit2(cx, cy, lenght / 2)
        cx = x + lenght / 4
        cy = y + lenght * 3 / 4
        drawit2(cx, cy, lenght / 2)
    else:
        t.hideturtle()
        return 0

lenght = 160
colormode(255)
drawit2(0 - lenght / 2, 0 - lenght / 2, 160)
t.mainloop()


Queda asi:


Creo que prefiero la versión en negro y gris.

Como se ve tan feo, encontré un dato en uno de los tutoriales: el módulo colorsys. Con la ayuda de este enlace y luego de probar un poco llegué a este código:

from colorsys import hsv_to_rgb
import turtle as t
from turtle import*
from random import randint

def cuadrado(lenght, n):
    t.pencolor(hsv_to_rgb(n / 36, 0.75, 0.75))
    t.forward(lenght)
    t.seth(90)
    t.forward(lenght)
    t.seth(180)
    t.forward(lenght)
    t.seth(270)
    t.forward(lenght)
    t.seth(0)

def drawit2(x, y, lenght, n):
    if lenght > 5:
        t.penup()
        t.goto(x, y)
        n += 4
                
        t.pensize(lenght/15)
        t.pendown()
        cuadrado(lenght - lenght / 10, n)
                
        cx = x - lenght / 4
        cy = y + lenght / 4
        drawit2(cx, cy, lenght / 2, n + 1)
        cx = x + lenght / 4
        cy = y - lenght / 4
        
        
drawit2(cx, cy, lenght / 2, n + 2)
        cx = x + lenght * 3 / 4
        cy = y + lenght / 4
        
drawit2(cx, cy, lenght / 2, n + 3)
        cx = x + lenght / 4
        cy = y + lenght * 3 / 4
        
drawit2(cx, cy, lenght / 2, n + 4)
    else:
        t.hideturtle()
        return 0

lenght = 160
drawit2(0 - lenght / 2, 0 - lenght / 2, 160, 12)
t.mainloop()


Se ve mucho mejor ahora: