2017-09-14 1 views
0

Je tente actuellement de créer un jeu Bulls et vaches pour une évaluation maquette de l'école et je rencontre des problèmes avec cette ligne de code« IndexError: index de chaîne hors de portée », tout en essayant de vérifier une entrée

def BullsAndCows(): 
Guess= input("Please enter a 4 digit number, remember no duplicates!") 
Guess = str(Guess) 
while len(Guess) != 4: 
    Guess = input("IT has to be FOUR digits!") 
    Guess = str(Guess) 

while Guess[0] == Guess[1] or Guess[0] == Guess[2] or Guess[0] == Guess[3] or Guess[1] == Guess[2] or Guess[1] == Guess[3] or Guess[2] == Guess[3]: 
    Guess = input("You can't use duplicates silly! Try another number!") 
    Guess = str(Guess)` 

le problème est si je entrer un numéro à 4 chiffres avec un double i ne peut entrer plus un nombre non à 4 chiffres sans lui produire cette erreur

Traceback (most recent call last): File "python", line 64, in File "python", line 57, in BullsAndCows IndexError: string index out of range

ligne 57 est le while Guess[0] == ...

La ligne 64 est juste BullsandCows() qui est utilisée pour appeler la fonction. Quelqu'un connaît le problème?

+0

Je prends votre exemple de code est mal formaté, mais votre code actuel est correct, au moins en ce qui concerne l'indentation (questions espaces blancs en python) – vmg

+0

votre empreinte dans l'exemple est erroné qui peut provoquer des problèmes – JJAACCEeEKK

Répondre

2

Votre erreur est générée lorsqu'un utilisateur entre une chaîne dont la longueur est inférieure à 4. Dans ce cas, guess[3] sera hors limites.


Si vous voulez vérifier si votre entrée adhère à venir état, je recommanderais un seul while terminé par une condition:

import re 

guess = '' 
while not (guess.isdigit() \ 
      and len(guess) == 4 \ 
      and not re.search(r'(\d).*\1', guess)): 
    guess = input(...) 

Tant que la condition while reste False, la boucle continue courir.

  • guess.isdigit() est une fonction de chaîne pour vérifier si une chaîne est numérique ou non. Par exemple:

    In [889]: '1234'.isdigit() 
    Out[889]: True 
    
    In [890]: '1234abc'.isdigit() 
    Out[890]: False 
    
  • len(guess) == 4 vérifiera si la chaîne est de longueur 4, si la première condition est True.

  • En outre, pour éviter les doublons, je voudrais hautement recommandons d'utiliser des expressions régulières. Si la première et la deuxième condition sont True, la fonction re.search appliquera un motif regex (expliqué ci-dessous) pour rechercher des doublons dans la chaîne. S'il y a un doublon, une correspondance est renvoyée qui est évaluée à True. Sinon, None est renvoyé, à savoir False.

Tant que l'une quelconque de ces 3 conditions sont False, l'expression entière est False (en raison de la façon dont fonctionne or logiques booléennes) et la boucle continue à exécuter.


Regex Détails

(\d) # digit (capture group) 
.* # match 0 or more chars 
\1 # reference 1st capture group 
+0

Bien que cela aide, je peux Ne comprenez pas ce que signifie ce bloc de code. Ma connaissance de python est assez petite donc la majorité de ceci n'a pas beaucoup de sens pour moi. –

+0

@WilliamMayne Tout ce que vous avez à faire est de demander, et je peux m'améliorer. Vous ne devriez pas aller après des solutions de qualité inférieure juste parce que vous avez peur d'apprendre. Demandez et je peux expliquer :) –

+0

@ColdSpeed ​​Ma classe se termine maintenant, je dois y aller mais je vais vérifier plus tard pour poser des questions sur le code. –

1

Vous pouvez simplifier beaucoup de méthode en supprimant les tout en boucles et en utilisant simplement 1 qui gardera le programme en cours d'exécution jusqu'à ce que la méthode casse

Vous pouvez utiliser la fonction len() pour vérifier si la valeur entrée correspond à 4 chiffres

Vous pouvez utiliser le constructeur set() pour construire un ensemble de votre entrée qui supprimera les doublons, puis comparer le len() de l'ensemble à l'len() de l'entrée d'origine

def BullsAndCows(): 
    while True: 
     guess = str(input("Please enter a 4 digit number, remember no duplicates:")) 

     if len(guess) != 4: 
      print("It has to be FOUR digits") 
      continue 

     if len(set(guess)) != len(guess): 
      print("You cant enter duplicates silly! Try another number") 
      continue 

     print("No duplicates in number: {}".format(guess)) 
     break 

BullsAndCows() 

>> Please enter a 4 digit number, remember no duplicates: 
> 123 
>> It has to be FOUR digits 
>> Please enter a 4 digit number, remember no duplicates: 
> 1111 
>> You cant enter duplicates silly! Try another number 
>> Please enter a 4 digit number, remember no duplicates: 
> 1234 
>> No duplicates in number: 1234 
+0

Pas sûr que vous ayez besoin d'utiliser '[:]', 'set (deviner)' fonctionne aussi bien (sur Python 3.6 au moins). – pills

+0

Mis à jour. @pills – AK47

+0

J'aime cette méthode, je voudrais juste savoir exactement ce que fait le '{0}" format (deviner)) 'Il semble que cela fonctionne sans le 0. –

2

La raison de votre erreur est qu'une fois que vous avez passé le test à 4 chiffres une fois, vous ne le faites plus même si l'entrée change. Donc, si vous entrez d'abord 1111, il passe le premier test (while len(Guess) != 4) mais pas le second test. Si vous puis entrez 123, vous obtenez une erreur, car l'entrée a seulement 3 chiffres et Guess[3] soulève une IndexError

Vous devez factoriser votre code pour inclure tous les tests sur l'entrée au même endroit, et seulement une boucle while . Somehting comme ceci:

def BullsAndCows(): 
    Guess= input("Please enter a 4 digit number, remember no duplicates!") 
    Guess = str(Guess) 
    (correct, message) = check_input(Guess) 
    while not correct: 
     Guess = input(message) 
     (correst, message) = check_input(Guess) 

def check_input(guess): 
    if not guess.isdigit(): 
     return (False, "Input a number") 
    if len(guess) != 4: 
     return (False, "The number should have 4 digits") 
    if guess[0] == guess[1] or ... 
     return (False, "No duplicates") 
    #other tests if necessary 
    return (True, "ok") 

Edit: comme d'autres l'ont souligné, guess[0] == guess[1] or ... est lourde et sujette aux erreurs. Mieux vaut le remplacer par quelque chose de plus générique et qui fonctionne aussi bien si vous avez 4, 5, ... n chiffres dans l'entrée. La solution AK47 (len(set(guess)) != len(guess)) fonctionne bien pour cela. Étant donné que la syntaxe est un peu obscure pour les utilisateurs pour la première fois, voici comment cela fonctionne:

  • set(guess) transforme l'entrée en un ensemble de ses personnages. Un ensemble ne peut avoir que des éléments distincts, donc set('123') = set('1233212') = {'1', '2', '3'}.
  • si len(set(guess)) == len(guess), cela signifie que tous les caractères de guess sont également dans l'ensemble; donc tous les caractères sont distincts.