Skip to content

Revisión automática de la práctica 04-formas

Este es el resultado de una revisión automática de la prácica 04-formas, tal y como la hemos recogido de este repositorio de entrega. Por favor, ten en cuenta que al ser una revisión automática, realizada en parte con la ayuda de un asistente de inteligencia artificial generativa, puede incluir errores, y ser incorrecta. Pero leela con atención, porque creemos que puede tener información útil. Si tienes cualquier duda, o crees que la revisión es errónea, por favor, consulta con los profesores de la asignatura.


Comprobación de archivos con extension '.py'

  • Archivos Python excluidos de la búsqueda: pixels.py
  • Archivos Python encontrados (excluyendo esos): formas.py

Correcto, se elige formas.py como entrega.

Comprobación con ficheros de solución

Los archivos son diferentes de los de la solución.

Prueba automática del programa

Pruebas realizadas por 04-formas/tests/test_argumentos.py:

OK

Pruebas realizadas por 04-formas/tests/test_formas.py:

OK

Pruebas realizadas por 04-formas/tests/test_funciones.py:

OK

Revisión automática de programa

Programa revisado:

import sys
from pixels import tam_lienzo, pinta, espera


def lee_formas():
    """Lee los argumentos de línea de comandos y construye una lista de
    diccionarios que representan las formas."""
    argumentos = sys.argv[1:]
    if len(argumentos) < 4:
        print("Se requieren al menos 4 argumentos para dibujar una "
              "figura.")
        return []

    formas = []
    i = 0
    while i < len(argumentos):
        if argumentos[i] == "cuad":
            x = int(argumentos[i + 1])
            y = int(argumentos[i + 2])
            lado = int(argumentos[i + 3])
            if i + 4 < len(argumentos) and argumentos[i + 4] not in \
                    ["cuad", "rect"]:
                color = argumentos[i + 4]
                # Si existe un quinto argumento y no es el nombre de otra
                # figura, asumimos que va a ser el color.
                i += 5
            else:
                color = "black"
                i += 4
            # Si había color, se han usado 5 argumentos para esta forma:
            # ["cuad", x, y, lado, color]
            # Suma 5 a la variable i para saltar los cinco argumentos ya
            # leídos y continuar leyendo desde el siguiente elemento no
            # procesado.
            # Si no había color solo se han usado 4 argumentos:
            # ["cuad", x, y, lado] y suma 4 a la variable i
            formas.append({"tipo": "cuadrado", "x": x, "y": y,
                           "lado": lado, "color": color})
        elif argumentos[i] == "rect":
            x = int(argumentos[i + 1])
            y = int(argumentos[i + 2])
            ancho = int(argumentos[i + 3])
            alto = int(argumentos[i + 4])
            if i + 5 < len(argumentos) and argumentos[i + 5] not in \
                    ["cuad", "rect"]:
                color = argumentos[i + 5]
                # Si existe un sexto argumento y no es el nombre de otra
                # figura, asumimos que va a ser el color
                i += 6
            else:
                color = "black"
                i += 5
            formas.append({"tipo": "rectángulo", "x": x, "y": y,
                           "ancho": ancho, "alto": alto, "color": color})

    return formas


def dibuja_cuadrado(x, y, lado, color="black"):
    """Dibuja el borde de un cuadrado en el lienzo."""
    ancho_lienzo, alto_lienzo = tam_lienzo()
    if x < 0 or y < 0 or x + lado - 1 >= ancho_lienzo or \
            y + lado - 1 >= alto_lienzo:
        # Comprueba si el cuadrado cabe en el lienzo, si x o y son
        # negativos estamos fuera del lienzo,
        # si la coordenada máxima (x + lado - 1, y + lado - 1) excede o
        # iguala el tamaño del lienzo estamos fuera del lienzo
        # Si no cabe, devuelve False y no pinta nada. (la resta -1 se
        # usa porque se consideran píxeles índices enteros desde 0).
        return False

    # Dibuja solo el borde: lados superior e inferior
    for i in range(lado):
        pinta(x + i, y, color)  # Lado superior
        pinta(x + i, y + lado - 1, color)  # Lado inferior

    # Dibuja lados izquierdo y derecho (excluyendo las esquinas ya pintadas)
    for j in range(1, lado - 1):
        pinta(x, y + j, color)  # Lado izquierdo
        pinta(x + lado - 1, y + j, color)  # Lado derecho

    return True


def dibuja_rectangulo(x, y, ancho, alto, color="black"):
    """Dibuja el borde de un rectángulo en el lienzo."""
    ancho_lienzo, alto_lienzo = tam_lienzo()
    if x < 0 or y < 0 or x + ancho - 1 >= ancho_lienzo or \
            y + alto - 1 >= alto_lienzo:
        return False

    # Dibuja solo el borde: lados superior e inferior
    for i in range(ancho):
        pinta(x + i, y, color)  # Lado superior
        pinta(x + i, y + alto - 1, color)  # Lado inferior

    # Dibuja lados izquierdo y derecho (excluyendo las esquinas ya pintadas)
    for j in range(1, alto - 1):
        pinta(x, y + j, color)  # Lado izquierdo
        pinta(x + ancho - 1, y + j, color)  # Lado derecho

    return True


def main():
    """Programa principal"""
    (ancho, alto) = tam_lienzo()
    formas = lee_formas()

    for forma in formas:
        tipo = forma["tipo"]
        x = forma["x"]
        y = forma["y"]
        color = forma.get("color", "black")

        if tipo == "cuadrado":
            lado = forma["lado"]
            dibuja_cuadrado(x, y, lado, color)
        elif tipo == "rectángulo":
            ancho_forma = forma["ancho"]
            alto_forma = forma["alto"]
            dibuja_rectangulo(x, y, ancho_forma, alto_forma, color)

    espera()


if __name__ == "__main__":
    main()

Análisis

Cumple con el enunciado

El programa no cumple completamente con el enunciado. Aunque implementa las funciones requeridas y sigue la lógica básica de dibujo, presenta dos problemas críticos:

  1. Error en el análisis de argumentos: En lee_formas(), al detectar el color, se asume que cualquier argumento después de los obligatorios que no sea "cuad" o "rect" es un color. Esto falla si el color se llama "cuad" o "rect" (ej: python3 formas.py cuad 1 1 2 cuad), interpretándolo erróneamente como inicio de una nueva figura y causando errores de índice.
  2. Falta validación de parámetros mínimos por figura: Si se proporcionan argumentos incompletos para una figura (ej: cuad 1 2 sin el lado), el programa intentará acceder a índices fuera de rango en argumentos, generando un IndexError no controlado.

Es fácil de leer y entender

El código es medianamente comprensible para principiantes:

  • Los nombres de variables y funciones son descriptivos (ej: dibuja_cuadrado, lado).
  • Los comentarios explican la lógica de los bucles de dibujo, útil para entender cómo se pinta el borde.
  • Pero la lógica de lee_formas() es compleja para principiantes: el uso de i += 5/i += 4 y las condiciones anidadas para detectar el color dificultan su comprensión, especialmente al mezclar el control de índice con la detección de tipos de figura.

Sigue buenas prácticas de programación

No sigue buenas prácticas básicas:

  • Falta validación robusta: No se verifica que haya suficientes argumentos para cada figura antes de acceder a ellos (ej: para cuad se necesitan al menos 4 argumentos después del tipo).
  • Lógica frágil en lee_formas(): La detección del color depende de que los nombres de colores no coincidan con "cuad"/"rect", lo cual es un supuesto peligroso.
  • No se usa el valor de retorno de las funciones de dibujo: Aunque el enunciado pide que devuelvan True/False, main() ignora estos valores, perdiendo oportunidad de notificar errores al usuario.

Recomendaciones de mejora

  1. Valida parámetros por figura en lee_formas():

    • Antes de procesar cada figura, verifica que haya suficientes argumentos restantes (ej: para cuad necesitas al menos 3 argumentos después del tipo). Si no, muestra un mensaje de error específico y termina.
  2. Simplifica la detección del color:

    • En lugar de depender de que el color no sea "cuad"/"rect", define que el color siempre será el quinto argumento para cuad (si existe) y el sexto para rect (si existe), sin importar su valor. Ejemplo:
      # Para cuad
      if i + 4 < len(argumentos):
          color = argumentos[i + 4]
          i += 5
      else:
          color = "black"
          i += 4
  3. Usa el valor de retorno de las funciones de dibujo:

    • En main(), verifica si dibuja_cuadrado()/dibuja_rectangulo() devuelven False e imprime un mensaje como "Error: Figura fuera del lienzo".
  4. Mejora los mensajes de error:

    • En lee_formas(), si faltan parámetros para una figura, indica cuál figura tiene el problema (ej: "Error: 'cuad' requiere 3 parámetros (x, y, lado)").