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.')
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,
Por ejemplo en tu código puedes hacer varias cosas.
Los print()
de los condicionales se repiten constantemente, es una buena opción para crear funciones en base a parámetros.
Los condicionales, podrías crear una función, que los aglutinara y devuelva, True
o False
. Estas funciones que devuelven booleanos son llamadas "Predicates"
Crear el contador (victorias, derrotas, empates) en otra función que sea llamada y contabilice.
Que las distintas opciones sean llamadas a una función.
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
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP