2017-02-02 2 views
0

Ich schreibe ein Spiel von Rock, Papier und Schere in Python. Aber hier ist der Fehler:Wiederholte Bestätigung am Programmausgang

Wenn ich 8 mal gespielt habe und ich beenden will, fragt mich das Spiel auch 8 mal.

Beispiel: Ich habe 5 mal gespielt.

Das Spiel fragt mich: Do you want to exit? yes/no.

Wenn ich sage (schreiben) ja, das Spiel wieder mich fragt, ist dieser Fall 5 mal.

Ich bin ein Anfänger in Python-Programmierung, und ich verstehe wirklich nicht, warum das passiert.

Können Sie mir bitte helfen?

Ich programmiere in Windows und über die Befehlszeile, um das Programm auszuführen. (Ich weiß nicht, ob dies die korrekte Funktion des Programms beeinträchtigt.)

Hier ist der Code. Es ist noch nicht fertig:

class RPS_Game(object): 

    def Check(self): 

      P1 = raw_input("Player 1: Enter Rock, Paper or Scissors: ") 
      P2 = raw_input("Player 2: Enter Rock, Paper or Scissors: ") 

      if(str(P1.lower()) != "rock" and str(P1.lower()) != "paper" and str(P1.lower()) != "scissors"): 

       print "Must be Rock, Scissors or Paper, not: " + str(P1.lower()) 

      elif(str((P2).lower()) != "rock" and str(P2.lower()) != "paper" and str(P2.lower()) != "scissors"): 

       print "Must be Rock, Scissors or Paper, not: " + str(P2.lower()) 
      else: 
       sendDataToGame = self.Game(P1,P2) 


    def Game(self,P1,P2): 
     self.P1 = P1 
     self.P2 = P2 

     wantToExit = "" 

     while(True): 
      if(str(self.P1).lower() == str(self.P2).lower()): 
       print "You are in a tie!" 
       wantToExit = raw_input("Do you want to exit? yes/no: ") 
       if(wantToExit.lower() == "yes"): 
        break 
       else: 
        self.Check() 

Call = RPS_Game() #instantiate 

Call.Check() #calling Check function 
+0

Warum rufen Sie nicht 'niedriger () 'einmal, wenn Sie jede Eingabe lesen, damit Sie' P1.lower() 'nicht immer wieder schreiben müssen? – Barmar

+0

Ich sehe nicht, wie das überhaupt funktioniert. Wenn es kein Gleichstand ist, sucht man nie nach einem Gewinner, so dass die while-Schleife für immer wiederholt wird. – Barmar

Antwort

2

Sie erstellen reusiwell mehr Spiele. Beachten Sie, dass RPS_Game.Game Anrufe self.Chek() und RPS_Game.Check Anrufe self.Game() aufrufen.

Also jedes Mal, wenn ein Spiel vorbei ist, erstellt die Zeile mit sendDataToGame = self.Game(P1,P2) ein neues Spiel. Sie müssen alle Spiele beenden, um das Skript zu beenden.

Sie haben viele andere Dinge in Ihrem Code, den ich auch anders machen würde, so ist hier eine Implementierung, die das Problem behebt und einige andere Dinge bereinigt:

class RPS_Game(object): 

    # create tuples that contain all valid combinations 
    # this will make the comparisons easier later 
    ties = (('r', 'r'), ('p', 'p'), ('s', 's')) 
    p1_wins = (('r', 's'), ('s', 'p'), ('p', 'r')) 
    p2_wins = (('s', 'r'), ('p', 's'), ('r', 'p')) 

    # use a method to print our options for the users so we don't have to code the same 
    # thing twice - also notice that I'm using the python convention of lowercase names 
    # for functions & methods     
    def display_options(self, player): 

     print("Player {}: Press 'R' for rock, 'P' for paper, or 'S' for scissors" 
       .format(player)) # using string substitution to insert the player 
            # number appropriate on each function call 

    def check(self, inputs): 

     # Since we created the ties and wins tuples, we can now use the "in" operator 
     # to check for membership instead of having long and difficult to read 
     # string comparisons 
     if inputs in self.ties: 
      print("You tied!") 

     elif inputs in self.p1_wins: 
      print("Player 1 wins!") 

     elif inputs in self.p2_wins: 
      print("Player 2 wins!") 

     # if the inputs weren't in any of our tuples, we know it was invalid input 
     else: 
      print("\nInvalid input. Please try again.\n") 
      # return false if the input was invalid - this will be used by the caller 
      return False 

     # returning True indicates that the responses were valid  
     return True 

    def run(self): 

     # use a loop to start another game if the user wants to 
     while True: 

      # call our display options function, passing it the player number 
      self.display_options(1) 
      # get first player's response 
      p1 = raw_input("").lower() 
      # same things for second player 
      self.display_options(2) 
      p2 = raw_input("").lower() 

      # create a tuple out of our player's selections for easy membership 
      # checking in our tuples of valid combinations 
      inputs = (p1, p2) 

      # check our inputs both for validity and to see who wins 
      valid = self.check(inputs) 

      # if our input wasn't valid, skip the exit prompt and start a new game 
      # notice how the "check" function was set up to return false if 
      # input is not valid - now this comparison reads almost like regular 
      # English! 
      if not valid: 
       continue 

      repeat = raw_input("Play again? (Y/N)\n").lower() 

      # if the user entered "n" for starting another game, break out of 
      # the infinite loop and exit 
      if repeat == 'n': 
       break     

# create the game object and run it 
game = RPS_Game() 
game.run() 
+0

ruft er 'self.Check()' nicht auf, wenn der Benutzer beenden möchte. – Barmar

+0

@Barmar Aber wenn er ein paar Spiele vor dem Beenden spielt, muss jedes Spiel auf dem Stapel verlassen werden. – skrrgwasme

+0

Ich puted eine Pause in der if/else-Anweisung des RPS_Game.Game Mit diesem kann ich das Skript beenden –

0

Sie in einigen rekursiven Aufruf fallen

check -> 
    Game -> 
     check -> 
      Game -> ... 

Wenn Sie das Spiel in einer Ebene beenden, kehren Sie zu einer vorherigen Ebene im Kettenaufruf zurück und deshalb fragt es Sie so oft.

Sie konvertieren auch Ihre Variablen in Zeichenfolge, wenn sie bereits eine Zeichenfolge wie in str(...) sind, so dass nichts erreicht. Du wiederholst auch zu oft einen Anruf zu senken, versuche das so weit wie möglich zu vermeiden. Statt rekursivem Aufruf, wie Sie es jetzt tun, verwenden Sie return, um das Ergebnis einer Funktion zu erhalten.

wie dies zum Beispiel

class RPS_Game(object): 

    def ask_play(self, player): 
     # this function will iterate until you get a satisfactory 
     # input from the user 
     while True: 
      P = raw_input(player+" Enter Rock, Paper or Scissors: ").lower() 
       #raw_input give you a string result, to that result you can immediately call 
       #.lower(), that way you always work with a lower case string 
      if P in {"rock","paper","scissors"}: 
       #this is one of the best way to ask if a variable have one of several values 
       return P #exit the function now that you get a satisfactory input 
      else: 
       print "Must be Rock, Scissors or Paper, not:", P 

    def Game(self): 
     while True: 
      P1 = self.ask_play("Player 1") 
      P2 = self.ask_play("Player 2") 
      if P1 == P2: 
       print "You are in a tie!" 
       wantToExit = raw_input("Do you want to exit? yes/no: ").lower() 
       if wantToExit == "yes": 
        break 
      elif P1 == "rock" and P2 == "paper": 
       print "Player 2 win" 
      #complete the rest of combination 


the_game = RPS_Game() #instantiate 

the_game.Game() #play the game 

Hinweis, wie ich die ask_play so allgemein wie möglich zu machen und die Details werden von, wie Sie es verwendet wird, auf diese Weise Sie durch Überprüfen 2 Variablen zu kompliziert Sachen brauchen nicht zur gleichen Zeit gegen alle möglichen Kombination, tun Sie es einfach für 1 Variable, und verwenden Sie diese verallgemeinerte Funktion, um so viele Werte wie Sie wollen erhalten, wie alle von ihnen auf die gleiche Weise erhalten