1
Torres de Hanói en Python Para esto, creamos tres listas, la primera de ellas llamada R esumen: En el presente informe se desarrolla la construcción de una interfaz gráfica para el juego el juego “las torres de Hanói” utilizando la librería Pygame y el lenguaje de programación Python. Este programa debe permitir 2 o más jugadores, además de guardar la cantidad de movimientos que haga cada jugador y elaborar un ranking con las posiciones de los jugadores.
I. INTRODUCCIÓN Las torres de Hanoi son un juego matemático y trata sobre un número de discos de radio creciente que se instalan en una de tres posibles torres del tablero. Este consiste en traspasar los discos desde una torre inicial a otra final, con la ayuda de una tercera torre que sirve de paso, es decir, replicar la pila inicial en otra torre, posicionando los discos de mayor a menor diámetro. En esta ocasión, se creará el juego y la interfaz gráfica de éste con la ayuda de la librería Pygame y el lenguaje de programación Python. Además de programar el juego de las torres de Hanói, nos exigen una serie de requerimientos adicionales, entre ellos: permitir a un número mayor a dos jugadores, establecer la cantidad de movimientos movimientos que efectúan los jugadores y establecer a un ganador que se regirá por haber traspasado la torre con la menor cantidad de movimientos. movimientos. II. DESARROLLO Y RESULTADOS Como bien se mencionó, el objetivo del juego es crear la pila en otra de las torres, sin embargo, para ello existen ciertas reglas a seguir, las cuales se muestran a continuación: -
“altura” destinada a la posición de los discos en el eje y, la siguiente llamada “torre” destinada a la posición de las tres torres del juego y finalmente la lista llamada “posi” que
relaciona el número de la pieza (del 1 al 7), en que torre se ubica y a que altura (posición eje y). Importamos el archivo donde se ubican estas listas y la llamamos “pi”. Lu ego de pedir el nombre del jugador dibujamos el tablero con sus respectivos discos. Para dibujar los discos, es decir, darles un largo y ancho, lo que hacemos es definir una función llamada “dibujar(aaa)”, que depende del parámetro “aaa” el cual va de 1 a 10, y según el valor de este parámetro obtendremos las ubicaciones de los discos en la pantalla, hacemos esto simplemente en vez de poner las posiciones posiciones en coordenadas. coordenadas. Luego, definimos otra función llamada “mover(aaa)”, la cual a través de ciclos “For” tendrá la misión de rellenar las listas que contienen las piezas actuales de cada torre. Finalmente, se crea una ventana donde se pueda jugar, esta ventana corresponderá a toda la pantalla del equipo donde se juegue, esto se logra utilizando el módulo Pygame (pygame. FULLSCREEN) para controlar la ventana de visualización y la pantalla. Adicional a esto, se agregan otros módulos para el control del color de fondo de la ventana y también para el color y la fuente del texto que se visualiza en pantalla. En la figura 1 se puede apreciar la interfaz del punto de partida del juego.
La torre estará formada por diez discos. Solo se puede mover un disco a la vez. Un disco de mayor tamaño no puede descansar sobre un disco de menor tamaño. Solo se puede desplazar el disco que se encuentra a mayor altura.
Para la realización de la programación, lo que se hizo fue dividir en distintas áreas o etapas el proceso, con los cuales determinamos las características que presenta el juego, cumpliendo así con los requerimientos y reglas que se nos piden. E tapa tapass del del j uego.
Comenzamos con la programación del juego, estableciendo en primera instancia, instancia, la librería, librería, la cantidad de discos y jugadores. jugadores. Para ello, al comenzar el juego, el usuario deberá indicar su nombre, luego se encontrará con diez discos en la primera torre, pudiendo realizar sus movimientos movimientos hasta lograr la réplica de la pila inicial en la torre 3. Figura 1: interfaz del punto de partida del juego.
2 Posteriormente se realiza la programación correspondiente al movimiento de los discos conjunto a las reglas que se deben cumplir. Para ello, se definen las teclas a utilizar para realizar el movimiento y que a la vez están asociada a cada torre. Estas teclas son: tecla “A” para la torre 1, tecla “S” para la torre 2 y tecla “D” para la torre 3. Cada tecla está asociada a una sentencia “if” y ésta a la vez está dentro de una sentencia “for”.
Lo que se hace aquí es verificar que tecla se oprimió, y según sea A, S o D se verificará las listas de cada torre, es decir, las alturas de las piezas en las columnas 1, 2 y 3. Considerando por ejemplo la torre 1, asociada a la tecla “A”, si es que hay alguna pieza en esta torre y no se está jugando la pieza más alta (altura máxima) pasa a ser la que se está jugando, permitiendo así que solo se pueda desplazar el disco que se encuentre a mayor altura. Sí por el contrario se juega alguna pieza, en una sentencia “if”
se compara la pieza en juego (en alto) con la pieza de mayor altura en la torre 1, permitiendo el movimiento de la pieza seleccionada a la otra torre siempre y cuando la pieza trasladada sea más pequeña que la existente en la torre de destino, cumpliendo así otra de las reglas fundamentales del juego. Finalmente, si se realizó el correcto movimiento desde una torre a otra, se guarda el número de movimientos en una variable denominada “ puntaje”, la cual será útil para elaborar el ranking de puntajes obtenidos por cada jugador, es decir, si la torre objetivo es distinta a la inicial se suma un punto. Este proceso descrito para la tecla “A” se repite para ca da
tecla asociada a cada torre, permitiendo el correcto funcionamiento del juego en cuanto a los movimientos de los discos hechos por el jugador. Para finalizar con la programación, lo que sigue es verificar cuando se ha logrado posicionar la totalidad de los discos en la torre 3, para así culminar el juego y dar el puntaje final del jugador y posicionarlo en el ranking. Para ello se crea un archivo de texto llamado “highscores” el cual se llama en
modalidad de lectura identificando los puntajes y nombres de jugadores que han participado anteriormente y luego se agrega el puntaje y el nombre del jugador actual (los puntajes se almacenan como enteros). A continuación, estos dos parámetros se comparan en función del puntaje mediante el comando “sorted” el cual nos
proporciona una lista ordenada con los 5 mejores puntajes y el nombre de los respectivos jugadores, cabe destacar, que el puesto número 1 lo ocupara el jugador que haya realizado menos movimientos. Finalmente, se escribe en pantalla el puntaje del último jugador y la posición que ocupa en el ranking, siempre y cuando este dentro de los 5 mejores, dando paso así al siguiente jugador. En la figura 2 se puede apreciar el número de movimientos que realizó el jugador “simulación” y el puesto que ocupa dentro del ranking, una vez finalizada la partida.
Figura 2: Simulación de una partida del juego
A continuación, se muestra el código con el cual podemos realizar la interfaz gráfica y jugar a las torres de Hanói. import pygame, sys, time import posiniciales as pi from pygame.locals import * # SETUP nombre = input("Cual es su nombre? ") jugando = 0 def dibujar(aaa): #dibuja pieza numero (gracias a esto se pueden pedir las posiciones de las piezas con numeros del 1 al 10, en vez de poner las posiciones en coordenadas pygame.draw.line(ventana,pi.colormadera,(pi.torre[pi.posi[aaa ]]aaa*10,pi.altura[pi.posi[10+aaa]]),(pi.torre[pi.posi[aaa]]+aaa* 10,pi.altura[pi.posi[10+aaa]]),9) def mover(aaa): #rellena las listas (xs1, xs2, xs3) que contienen las piezas actuales de cada torre for x in range(1,11): if pi.posi[x]==1 and pi.posi[x+10]!=11: xs1.append(pi.posi[x+10]) else: xs1.append(0) for x in range(1,11): if pi.posi[x]==2 and pi.posi[x+10]!=11: xs2.append(pi.posi[x+10]) else: xs2.append(0) for x in range(1,11): if pi.posi[x]==3 and pi.posi[x+10]!=11: xs3.append(pi.posi[x+10]) else: xs3.append(0) pygame.init()
3 puntaje = 0 ventana = pygame.display.set_mode((800,500),pygame.FULLSCREEN) pygame.display.set_caption("Torre de Hanói") ##titulo ventana.fill(pi.colorfondo) ##fondo de la ventana ganador=pygame.font.Font(None,30) ##tamaño letra ganador1=pygame.font.Font(None,50) while True: # LOOP ventana.fill(pi.colorfondo) for x in range(1,11): #dibuja todas las piezas dibujar(x) pygame.draw.line(ventana,pi.colormaderados,(40+0,400),(40+ 660,400),10) # base horizontal
xs2=[0] #alturas de las piezas en la columna 2 xs3=[0] #alturas de las piezas en la columna 3 mover(1) if jugando == 0: if max(xs2) != 0: pi.posi[xs2.index(max(xs2))+10]=11 jugando=1 piezaenalto=[xs2.index(max(xs2)),2] elif jugando == 1: if piezaenalto[0]<=xs2.index(max(xs2)) xs2.index(max(xs2))==0: pi.posi[piezaenalto[0]+10]=1+max(xs2) pi.posi[piezaenalto[0]]=2 jugando = 0 if piezaenalto[1]!=pi.posi[piezaenalto[0]]: puntaje+=1
or
pygame.draw.line(ventana,pi.colormaderados,(40+110,400),(4 0+110,290),10) # base TORRE1 pygame.draw.line(ventana,pi.colormaderados,(40+330,400),(4 0+330,290),10) # base TORRE2 pygame.draw.line(ventana,pi.colormaderados,(40+550,400),(4 0+550,290),10) # base TORRE3
if event.key==K_d: #Tecla D, torre 3 xs1=[0] #alturas de las piezas en la columna 1 xs2=[0] #alturas de las piezas en la columna 2 xs3=[0] #alturas de las piezas en la columna 3 mover(1) if jugando == 0: if max(xs3) != 0: pi.posi[xs3.index(max(xs3))+10]=11 jugando=1 piezaenalto=[xs3.index(max(xs3)),3]
for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() elif event.type == pygame.KEYDOWN: if event.key==K_ESCAPE: pygame.quit() sys.exit()
elif jugando == 1: if piezaenalto[0]<=xs3.index(max(xs3)) xs3.index(max(xs3))==0: pi.posi[piezaenalto[0]+10]=1+max(xs3) pi.posi[piezaenalto[0]]=3 jugando = 0 if piezaenalto[1]!=pi.posi[piezaenalto[0]]: puntaje+=1
if event.key==K_a: #Tecla A, torre 1 xs1=[0] #alturas de las piezas en la columna 1 xs2=[0] #alturas de las piezas en la columna 2 xs3=[0] #alturas de las piezas en la columna 3 mover(1)
or
if pi.posi[1:11]==[3, 3, 3, 3, 3, 3, 3, 3, 3, 3]: if jugando == 0: if max(xs1) != 0: pi.posi[xs1.index(max(xs1))+10]=11 jugando=1 piezaenalto=[xs1.index(max(xs1)),1] elif jugando == 1: if piezaenalto[0]<=xs1.index(max(xs1)) xs1.index(max(xs1))==0: pi.posi[piezaenalto[0]+10]=1+max(xs1) pi.posi[piezaenalto[0]]=1 jugando = 0 if piezaenalto[1]!=pi.posi[piezaenalto[0]]: puntaje+=1 if event.key==K_s: #Tecla S, torre 2 xs1=[0] #alturas de las piezas en la columna 1
or
continuar=ganador.render("PARA EL SIGUIENTE TURNO PRESIONE X",0,(0,0,255)) tituloganador=ganador.render(("Felicidades "+str(nombre)+", has logrado finalizar, su puntaje es: "+str(puntaje)),0,(0,0,255)) highscores=ganador.render("Los 5 mejores puntajes son:",0,(0,0,255)) fp = open('highscores.txt',"r") # lee lo que hay desde el punto y coma hacia la izquierda en el archivo de texto. score = fp.readlines()[0].split(",;")[0].split(",") fp.close() fp = open('highscores.txt',"r") # lee lo que hay desde el punto y coma hacia la derecha en el archivo de texto. names = fp.readlines()[0].split(",;")[1].split(",")
4 fp.close()
ventana.fill(pi.colorfondo) ##fondo de la ventana
score.append(str(puntaje)) names.append(str(nombre)) # Agrega el nombre y puntaje del jugador actual en el archivo de texto "highscores"
III. CONCLUSIONES -
scoreint=[] for i in range(0,(len(score))): scoreint.append(int(str(score[i]))) e= sorted(zip(scoreint, names),reverse=False)[:5] # crea una lista con los nombres y puntaje de los 5 mejores f=open("highscores.txt","w") for punto in score: # el puntaje lo escribe en score, los separa por una coma y finalmente punto y coma f.write(str(punto)) f.write(",") f.write(";") for name in names: f.write(str(name)) f.write(",") f.write(";") f.close() # el nombre lo escribe en name, los separa por una coma y finalmente con punto y coma y cierra la lista. ranking1=ganador.render(("1. "+str(e[0])),0,(0,0,255)) ranking2=ganador.render(("2. "+str(e[1])),0,(0,0,255)) ranking3=ganador.render(("3. "+str(e[2])),0,(0,0,255)) ranking4=ganador.render(("4. "+str(e[3])),0,(0,0,255)) ranking5=ganador.render(("5. "+str(e[4])),0,(0,0,255)) # Imprime el ranking en pantalla en las coordenadas establecidas ventana.fill(pi.colorfondo) ventana.blit(highscores,(200,200)) ventana.blit(tituloganador,(100,100)) ventana.blit(continuar,(180,150)) ventana.blit(ranking1,(300,250)) ventana.blit(ranking2,(300,300)) ventana.blit(ranking3,(300,350)) ventana.blit(ranking4,(300,400)) ventana.blit(ranking5,(300,450)) pygame.display.update() while True: for event in pygame.event.get(): if event.type == pygame.KEYDOWN: if event.key==K_ESCAPE: pygame.quit() sys.exit() if event.key==K_x: #Presionar x para que pueda jugar el proximo jugador pygame.quit() sys.exit() Titulo = ganador1.render("Torres de Hanói",0,(33,33,33)) ventana.blit(Titulo,(250,50)) pygame.display.update()
-
El lenguaje de programación Python es más sencillo de utilizar en comparación a otros lenguajes, esto debido a que este lenguaje es más legible y elegante, simple, poderoso y denso, es decir, con poco código se hace mucho y todo aquello innecesario no hay que escribirlo. Además, la librería Python sigue creciendo. Gracias al uso de la librería Pygame se puede prototipar y desarrollar rápidamente, pues Pygame es un conjunto de módulos del lenguaje Python que permiten la creación de videojuegos en dos dimensiones de una manera sencilla, lo cual quedo demostrado en lo desarrollado anteriormente. La dificultad del juego dependerá netamente de la cantidad de discos con los que se juegue, siendo mayor a medida que aumentamos el número de discos. El número de movimientos óptimos para llegar a la mejor solución se obtiene a partir de la siguiente ecuación: (2 − 1) donde es el número de discos, por ende, para este caso (10 discos) se requieren como mínimo 1023 movimientos.