2015-11-15 8 views
0

J'ai un code de cryptage composé de 26 lettres et une option qui permet à l'utilisateur de le changer s'il le souhaite. Après avoir essayé plusieurs fois mon programme, j'ai rencontré une erreur, logique. L'utilisateur peut changer le code, mais aussi, ils peuvent entrer le même personnage 26 fois ou au moins 1 caractère plus d'une fois ce qui pourrait ruiner tout mon programme. Est-il possible de permettre à l'utilisateur de taper chaque lettre une seule fois? Voici ce que j'ai jusqu'à présent:Comment autoriser la saisie de chaque caractère une fois?

import tkinter 

letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 

encryption_code = 'LFWOAYUISVKMNXPBDCRJTQEGHZ' 

letters += letters.lower() 
encryption_code += encryption_code.lower() 

window = tkinter.Tk() 

encrypt_entry = tkinter.Entry(window) 
encrypt_entry.pack() 


def code_change(event): 
    global encrypt_entry 
    global encryption_code 

    encryptget = encrypt_entry.get() 

    if len(encryptget) == 26: 
     print("You have changed the encryption code") 
     encryption_code = encryptget 
     encryption_code += encryption_code.lower() 
     enc = dict(zip(letters, encryption_code)) 
     dec = dict(zip(encryption_code, letters)) 

    elif len(encryptget) < 26 or len(encryptget) > 26: 
     print("Please enter 26 characters") 
     encrypt_entry.delete(0, tkinter.END) 

window.bind('<Return>', code_change) 

EDIT J'ai essayé si j'essayez ce qui suit, mais maintenant taper l'alphabet ou encryption_code la déclaration elif ne fait rien.

import tkinter 

letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 

encryption_code = 'LFWOAYUISVKMNXPBDCRJTQEGHZ' 

letters += letters.lower() 
encryption_code += encryption_code.lower() 

window = tkinter.Tk() 

encrypt_entry = tkinter.Entry(window) 
encrypt_entry.pack() 


def code_change(event): 
    global encrypt_entry 
    global encryption_code 

    encryptget = encrypt_entry.get() 

    if len(set(encryptget)) == 26 and encryptget != encryption_code and encryptget != letters: 
     print("You have changed the encryption code") 
     encryption_code = encryptget 
     encryption_code += encryption_code.lower() 
     enc = dict(zip(letters, encryption_code)) 
     dec = dict(zip(encryption_code, letters)) 

    elif len(set(encryptget)) != 26 and encryptget == encryption_code and encryptget == letters: 
     print("Please enter each character exactly once") 
     encrypt_entry.delete(0, tkinter.END)   

window.bind('<Return>', code_change) 
+2

Si vous voulez que tous les 26 caractères pour être uniques, puis 'len (set (encryptget)) == 26' DÉCOUVRIRA; 'len (set ('abc')) == 3' mais' len (set ('aaa')) == 1'. – jonrsharpe

+0

Donc en utilisant simplement la fonction 'set()', cela permet d'avoir 26 caractères uniques? De plus, je ne veux pas que l'utilisateur puisse simplement taper l'alphabet - il ruine la partie de cryptage - et je l'ai trié. – Inkblot

+2

un ensemble ne peut contenir que des éléments * uniques *, donc si la chaîne a 26 caractères mais que tout caractère est répété, l'ensemble sera plus court. – jonrsharpe

Répondre

1

Tkinter dispose d'une fonctionnalité spécifique pour ce type de validation. Vous pouvez appeler une fonction pour chaque insertion, et cette fonction peut accepter ou rejeter cette insertion en fonction des critères que vous souhaitez.

Dans votre cas, le critère est "pas de caractères en double". Un moyen facile de déterminer cela est de convertir la chaîne en un ensemble (par définition, un ensemble n'a pas de doublons), puis comparez la longueur de l'ensemble à la longueur de la chaîne.

Pour appeler cette fonction chaque fois que l'utilisateur appuie sur une touche, définissez les options validate et validatecommand du widget d'entrée. Il y a une étape supplémentaire où vous devez enregistrer la commande, qui indique à tkinter lequel de plusieurs arguments spéciaux vous voulez que votre commande reçoive.

La solution ressemble à ceci:

# Define a command to be run whenever the user edits the entry 
# N.B. d will be "1" for an insert, "0" for delete, and "-1" 
# for anything else. P will be the value of the entry if this 
# edit is allowed. 
# 
# Note: this function must always return either True or False 
def encryption_validation(d, P): 
    if d == "1": # ie: an insert 
     unique_chars = set(P) 
     if len(P) > len(unique_chars): 
      return False 
    return True 

# register the command with tkinter 
vcmd = (window.register(encryption_validation), '%d', '%P') 

# configure the entry widget to use this command 
encrypt_entry.configure(validate="key", validatecommand=vcmd) 

Avec ce qui précède, il sera impossible pour l'utilisateur d'entrer un caractère deux fois. Notez que cette solution empêche également l'utilisateur de coller une chaîne avec des caractères en double.

Pour une explication plus exhaustive de la validation de la saisie, voir cette réponse sur StackOverflow: https://stackoverflow.com/a/4140988/7432

+0

Merci, y a-t-il un moyen de le limiter aux seules majuscules? – Inkblot

+0

@Inkblot: oui. Vous pouvez mettre tous les contrôles que vous voulez là-bas. –

-1

-moi si je me trompe, mais il semble que vous voulez juste vous assurer que la chaîne de caractères les entrées de l'utilisateur pour le code ne contient pas de doublons?

Je ne sais pas personnellement sur les commandes de validation, mais je pense que cela pourrait fonctionner pour atteindre votre objectif:

def IsCodeValid(encryption_code): 
    c = [0]*26 

    pos = 0 
    for i in range(len(encryption_code)): 
     pos = ord(encryption_code[i])-ord('A') #find placement relative to A in unicode 
     c[pos] = c[pos] + 1 #increment counter for that letter 

    j = 0 
    ValidCode = True 
    while j<26 and ValidCode: 
     if c[j]>1: #check to see if any letter occurred more than once 
      ValidCode = False 
     else: 
      j += 1 

    return ValidCode 

Rappelez-vous, ce que toutes s'attend lettres saisies en majuscules. Mais vous pouvez corriger cela en normalisant les données avant de l'accepter. Alternativement, vous pourriez compliquer la logique pour vérifier les deux minuscules & supérieure. Edit: Cela suppose que vous ne voulez pas que le code s'exécute si le encryption_code n'est pas valide, vous pouvez utiliser cet indicateur pour demander un nouveau encryption_code à l'utilisateur avant d'exécuter le reste du programme.

+0

J'ai essayé votre code ci-dessus, y a-t-il un moyen de vérifier si la modification a réussi en utilisant des instructions d'impression? – Inkblot

+0

@InkBlot print ValidCode le ferait. Si elle renvoie false, cela n'a pas fonctionné. –