TransWikia.com

¿Cómo organizar código en funciones?

Stack Overflow en español Asked by Alfredo Arvelaez on January 18, 2021

Estoy aprendiendo a programar en Python y estaría muy agradecido con su opinión acerca de mi código de este clásico juego.

Este fue el código que implemente para poder hacer funcional el "juego". Cuenta con el módulo random para que el bot seleccione una opción "aleatoria".

Intente hacerlo lo más organizado posible.

Una de mis preguntas es cómo se podría organizar para reducir el código a funciones. Para que no se a tan largo y tedioso a la hora de leerlo.

#Modulos
import random

#Lista de opciones: bot
lista_opciones = ['piedra', 'papel', 'tijera']
#Contadores:
contador_victorias = 0
contador_derrotas = 0
contador_empates = 0

def mostrar_menu_principal():
   menu_principal = open('menu_principal.txt')
   print(menu_principal.read())

def mostar_menu_juego():
   menu_juego = open('menu_juego.txt')
   print(menu_juego.read())

print('Bienvenido a PIEDRA, PAPEL O TIJERA!: El juego')
nombre_usuario = input('Ingrese su nombre: ')
nombre_usuario = nombre_usuario.strip()
mostrar_menu_principal()
while True:
   seleccion_menu_principal = input('Seleccione una opcion: ')
   if seleccion_menu_principal == '1':
       while True:
           mostar_menu_juego()
           seleccion_usuario_juego = input('Escriba una opcion: ')
           seleccion_usuario_juego = seleccion_usuario_juego.lower()
           seleccion_usuario_juego = seleccion_usuario_juego.strip()
           seleccion_bot_juego = random.choice(lista_opciones)
           if (seleccion_usuario_juego == 'piedra' and seleccion_bot_juego == 'tijera') or (seleccion_usuario_juego == 'papel' and seleccion_bot_juego == 'piedra') or (seleccion_usuario_juego == 'tijera' and seleccion_bot_juego == 'papel'):
               contador_victorias += 1
               print(f"Su eleccion fue: {seleccion_usuario_juego}")
               print(f"La eleccion de la computadora fue: {seleccion_bot_juego}")
               print('Victoria!')
           elif (seleccion_usuario_juego == 'piedra' and seleccion_bot_juego == 'papel') or (seleccion_usuario_juego == 'papel' and seleccion_bot_juego == 'tijera') or (seleccion_usuario_juego == 'tijera' and seleccion_bot_juego == 'piedra'):
               contador_derrotas += 1
               print(f"Su eleccion fue: {seleccion_usuario_juego}")
               print(f"La eleccion de la computadora fue: {seleccion_bot_juego}")
               print('Derrota!')
           elif seleccion_usuario_juego == seleccion_bot_juego:
               contador_empates += 1
               print(f"Su eleccion fue: {seleccion_usuario_juego}")
               print(f"La eleccion de la computadora fue: {seleccion_bot_juego}")
               print('Empate!')
           elif seleccion_usuario_juego == 'salir':
               print('Ha vuelto al menu principal!')
               mostrar_menu_principal()
               break
   elif seleccion_menu_principal == '2':
       print(f"Victorias: {contador_victorias}")
       print(f"Derrotas: {contador_derrotas}")
       print(f"Empates {contador_empates}")
   elif seleccion_menu_principal == '0':
       print('Ha salido exitosamente del juego!')
       exit()
   else:
       print('Error. Seleccion invalida.')

3 Answers

un dia despues, logre reorganizar el codigo para que estuviera mejor expresado por medio de funciones. Este fue mi codigo final:

from index import *

presentar_juego()
nombre_usuario = nombre_usuario()
mostar_menu_principal()
while True:
    print('')
    opcion_usuario = leer_opcion_usuario()
    if opcion_usuario == 1:
        contadores = jugar()
    elif opcion_usuario == 2:
        print('En esta ronda, su puntuacion fue:')
        print(f'Victorias: {contadores[0]}')
        print(f'Derrotas: {contadores[1]}')
        print(f'Empates: {contadores[2]}')
    elif opcion_usuario == 0:
        print('Ha salido exitosamente del juego! Vuelva pronto.')
        exit()
    else:
        print('Error. Opcion invalida.')

Answered by Alfredo Arvelaez on January 18, 2021

Una primera cosa que puedes hacer es estructurar tu código en forma de pseudocódigo que diga "a grandes rasgos" lo que debes ir haciendo. Sería algo así:

presentar juego
pedir datos al jugador
en bucle:
  leer opcion del jugador
  caso 1:
     jugar partidas
  caso 2:
     mostrar estadísticas
  caso 0:
     finalizar
  otro caso:
     error

Como ves, de ese pseudocódigo salen prácticamente los nombres de las funciones que deberías escribir. Así tendríamos por ejemplo:

def presentar_juego():
   print('Bienvenido a PIEDRA, PAPEL O TIJERA!: El juego')

def pedir_datos_al_jugador():
   nombre_usuario = input('Ingrese su nombre: ')
   nombre_usuario = nombre_usuario.strip()
   return nombre_usuario

Las funciones anteriores son muy sencillas y prácticamente ya no admiten descomposición en otras aún más simples. No obstante un detalle que has de tener en cuenta mientras las escribes es la posibilidad de pasarles parámetros, para que puedan ser más genéricas. Por ejemplo, el prompt "Ingrese su nombre" podría ser un parámetro para pedir_datos_al_jugador(). Además hay que tratar de evitar el uso de variables globales. Las funciones deberían recibir como parámetro lo que necesiten para su funcionamiento, y devolver en un return el resultado apropiado para que otras funciones puedan obtenerlo.

Una función más compleja es la de jugar_partidas(). Si la escribimos de nuevo como pseudocódigo veremos cómo simplificarla y delegar trabajo en otras funciones:

jugar partidas sería:
  en bucle:
    mostrar menú del juego
    leer jugada del jugador
    si elige salir, terminar el bucle
    crear jugada del bot
    calcular quién gana (a partir de las jugadas anteriores)
    actualizar contadores
    mostrar resultado

Aquí tenemos ya una función más útil, que determina quién gana a partir de los parámetros que reciba. Pero esta función no imprime nada, simplemente retorna quién ha ganado. Por ejemplo podemos hacer que retorne la cadena "humano", "bot" o "empate"

def quien_vence(human, bot):
   if (human == 'piedra' and bot == 'tijera') or (human == 'papel' and bot == 'piedra') or (human == 'tijera' and bot == 'papel'):
      return "humano"
   elif (human == 'piedra' and bot == 'papel') or (human == 'papel' and bot == 'tijera') or (human == 'tijera' and bot == 'piedra'):
      return "bot"
   else:
      return "empate"

Como ves, esta función tiene una sola misión y muy sencilla. Determinar quién ha ganado esta ronda. Es lo que se llama el principio de la resposabilidad única. Cada función debe tener un solo cometido y muy claro. No estaría bien meter en esta misma función la comprobación de si el usuario quiere salir, pues eso ya es otra tarea a realizar en otro sitio.

La implementación de jugar_partida(), que haría uso de otras funciones, podría ser así:

def jugar_partidas():
   victorias = derrotas = empates = 0
   while True:
     mostrar_menu_juego()
     humano = leer_jugada_jugador()
     if humano == "salir":
        break
     bot = crear_jugada_robot()
     ganador = quien_vence(humano, bot)
     if ganador == "humano":
        victorias += 1
     elif ganador == "bot":
        derrotas += 1
     else:
        empates += 1 
     imprimir_resultado(humano, bot, ganador)
  return victorias, derrotas, empates

Observa cómo esta función retorna los contadores para que la función que la haya llamado (la principal) pueda añadir estos contadores a sus propias estadísticas, evitando así el uso de variables globales.

Creo que esto es suficiente para darte algunas ideas sobre cómo descomponer en funciones un programa. Inténtalo tú mismo y si encuentras problemas pregunta de nuevo.

Answered by abulafia on January 18, 2021

Con esta "respuesta" no pretendo resolver el problema, creo que a veces es más beneficioso enseñar a pescar.

Organizar el código en funciones, es fundamental a la hora de programar, te permite tenerlo organizado, hacerlo más legible, debugear de forma más fácil los errores, etc.

Las dos formula más extendidas para refactorizar tu código es,

  1. Todo aquello que ejecuta una función específica por mínima que sea.
  2. El código que es repetitivo.

Por ejemplo en tu código puedes hacer varias cosas.

  1. Los print() de los condicionales se repiten constantemente, es una buena opción para crear funciones en base a parámetros.

  2. Los condicionales, podrías crear una función, que los aglutinara y devuelva, True o False. Estas funciones que devuelven booleanos son llamadas "Predicates"

  3. Crear el contador (victorias, derrotas, empates) en otra función que sea llamada y contabilice.

  4. Que las distintas opciones sean llamadas a una función.

  5. Después puedes introducir todos los puntos anteriores en otra función que se encuentre en un archivo .py a parte, e importarlos al archivo principal, que será el que ejecute el juego.

Como ves puedes hacer multiples cosas, si consigues completar estas cinco, tu código habrá quedado mucho más limpio, ordenado y no solo será más fácil para ti, si no para cualquier persona.

Answered by Rubiales Alberto on January 18, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP