jeu des permutations, version interactive avec curses
This commit is contained in:
parent
518e20ee83
commit
36dda2bf81
3 changed files with 174 additions and 1 deletions
|
|
@ -71,3 +71,4 @@ if __name__=="__main__":
|
|||
break
|
||||
else:
|
||||
attempts += 1
|
||||
|
||||
|
|
|
|||
172
src/permutator_interactif.py
Normal file
172
src/permutator_interactif.py
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
#encoding: utf-8
|
||||
|
||||
import random
|
||||
import curses
|
||||
import time
|
||||
|
||||
|
||||
def swap( items, i, j ):
|
||||
assert( i < len(items) and j < len(items) )
|
||||
items[i], items[j] = items[j],items[i]
|
||||
return items
|
||||
|
||||
|
||||
def permute( items, index ):
|
||||
""" Permute 4 chiffres deux à deux, par exemple avec index==0 :
|
||||
0 1 2 3 4 5 6 7
|
||||
▲ ▲ ▲ ▲
|
||||
│ └─┘ │
|
||||
└─────┘
|
||||
3 2 1 0 4 5 6 7
|
||||
"""
|
||||
assert( index+3 < len(items) )
|
||||
|
||||
# Échange les nombres aux deux bouts.
|
||||
items = swap( items, index, index+3 )
|
||||
|
||||
# Échange les nombres au milieu.
|
||||
items = swap( items, index+1, index+2 )
|
||||
|
||||
return items
|
||||
|
||||
|
||||
def display( scr, items, index, msg = "" ):
|
||||
""" Affiche un écran de jeu interactif en mode texte:
|
||||
D'abord une ligne pour un éventuel message,
|
||||
ensuite la séquence permutée,
|
||||
puis le schéma de permutation.
|
||||
|
||||
Par exemple:
|
||||
Séquence mélangée en 2 permutations
|
||||
0 1 6 7 3 2 5 4
|
||||
▲ ▲ ▲ ▲
|
||||
│ └─┘ │
|
||||
└─────┘
|
||||
"""
|
||||
# Efface ce qui aurait été affiché précédemment.
|
||||
scr.clear()
|
||||
# Ajoute une chaine de caractères,
|
||||
# à partir de la première ligne et de la première colonne.
|
||||
scr.addstr( 0,0, msg + "\n" )
|
||||
# Rempli le restant de la ligne affichée à l'écran par des espaces.
|
||||
# (lire "CLeaR TO End Of Line")
|
||||
scr.clrtoeol()
|
||||
|
||||
# On peut omettre les coordonnées, le curseur d'affichage part alors de la
|
||||
# dernière position...
|
||||
scr.addstr( " ".join([str(i) for i in items]) )
|
||||
# ... d'où l'intérêt d'ajouter des fins de ligne (caractère "\n").
|
||||
scr.addstr("\n")
|
||||
|
||||
# On insèrera une colonne d'espaces avant le schéma de permutation,
|
||||
# selon l'index considéré.
|
||||
pad = " " * index
|
||||
|
||||
scr.addstr( pad + ("▲ " * 4) + "\n" )
|
||||
scr.clrtoeol()
|
||||
scr.addstr( pad + "│ └─┘ │\n" )
|
||||
scr.clrtoeol()
|
||||
scr.addstr( pad + "└─────┘\n" )
|
||||
scr.clrtoeol()
|
||||
|
||||
# Rempli l'écran de ligne vide jusqu'en bas ("CLeaR TO BOttom").
|
||||
scr.clrtobot()
|
||||
|
||||
|
||||
def shuffle( items, permutations ):
|
||||
""" Applique un nombre donné de permutations aléatoires """
|
||||
for n in range(permutations):
|
||||
i = random.randint(0,size-4)
|
||||
items = permute( items, i )
|
||||
|
||||
|
||||
def loop( scr, items, nb_shuffle ):
|
||||
msg = "Séquence mélangée en "+str(nb_shuffle)+" permutations"
|
||||
display( scr, items, 0, msg )
|
||||
|
||||
end_msg = ""
|
||||
|
||||
ui_delay = 0.05
|
||||
# Modèle de la séquence initiale, ordonnée
|
||||
items_ok = sorted( items )
|
||||
attempts = 1
|
||||
i = 0
|
||||
while True:
|
||||
# Récupère le code de la touche qui viens d'être utilisée.
|
||||
keycode = scr.getch()
|
||||
cmd = chr(0)
|
||||
|
||||
# Si le code est un caractère ASCII (une lettre non accentuée)
|
||||
if 0 < keycode < 256:
|
||||
# Récupère le caractère correspondant à ce code.
|
||||
cmd = chr(keycode)
|
||||
|
||||
if cmd in 'qQ':
|
||||
break
|
||||
|
||||
elif keycode == curses.KEY_LEFT:
|
||||
if i > 0:
|
||||
i -= 1
|
||||
|
||||
elif keycode == curses.KEY_RIGHT:
|
||||
if i < size-4:
|
||||
i += 1
|
||||
|
||||
elif cmd == " " or keycode == curses.KEY_UP:
|
||||
permute( items, i )
|
||||
|
||||
# Si la séquence permutée correspond à la même séquence, mais triée
|
||||
if items == items_ok:
|
||||
msg = "Vous avez réussi en "+str(attempts)+" permutations"
|
||||
end_msg = msg
|
||||
else:
|
||||
attempts += 1
|
||||
|
||||
# Affiche l'écran de jeu
|
||||
display( scr, items, i, msg )
|
||||
# Met à jour le terminal
|
||||
scr.refresh()
|
||||
# Attends quelques millisecondes avant de relancer le tout.
|
||||
# Si on n'attends pas, le processeur sera utilisé à 100%,
|
||||
# ce qui est inutile vu le temps de réaction moyen d'un être humain.
|
||||
time.sleep( ui_delay )
|
||||
|
||||
return end_msg
|
||||
|
||||
|
||||
def play( size, nb_shuffle ):
|
||||
|
||||
scr = curses.initscr()
|
||||
# Ne pas afficher les touches pressées.
|
||||
curses.noecho()
|
||||
# Active la prise en compte des touches "flèches".
|
||||
scr.keypad(1)
|
||||
|
||||
items = [n for n in range(size)]
|
||||
|
||||
end_msg = ""
|
||||
try:
|
||||
shuffle( items, nb_shuffle )
|
||||
end_msg = loop( scr, items, nb_shuffle )
|
||||
|
||||
# Quelles que soit les erreurs ayant été levées, ou pas,
|
||||
# on effectue ce bloc de code.
|
||||
finally:
|
||||
# Dé-initialise la bibliothèque et remet le terminal
|
||||
# dans sa configuration précédente, sans quoi le terminal
|
||||
# ne s'affichera plus correctement à la sorti du programme.
|
||||
curses.endwin()
|
||||
|
||||
return end_msg
|
||||
|
||||
|
||||
if __name__=="__main__":
|
||||
size = 8
|
||||
nb_shuffle = 2
|
||||
|
||||
msg = play( size, nb_shuffle )
|
||||
|
||||
# Si le message n'est pas vide.
|
||||
if msg:
|
||||
print(msg)
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue