2017-08-21 38 views
1

我寫了一個小程序來模擬紙,剪刀,搖滾遊戲。Python縮進For,While和Try

我正在使用for-loop來控制3的行爲,我正在使用while並嘗試控制用戶輸入。

我不相信python運行遊戲評估邏輯中的代碼,但我不太確定爲什麼。我認爲這可能與範圍/縮進有關,但我不確定?已經用完了想法!

如果有人能指出我以前的答案的方向,資源或幫助澄清我的代碼中的問題,我會非常感激。

# module packages 
import random 

def rockpaperscissor(): 

    # data structures and primary variables 
    state = ["Rock", "Paper", "Scissor"] 
    user_points = [] 
    computer_points = [] 
    round_counter = 1 

    # game loop (best of three rounds) 
    for i in range(3): 
     print("Round " + str(round_counter) + ":") 
     computer_choice = random.choice(state) 
     # user input 
     while True: 
      try: 
       print("You: ", end='') 
       user_input = input().strip() 
       if user_input not in {"Rock", "rock", "Paper", "paper", "Scissor", "scissor"}: 
        raise Exception 
      except Exception: 
       print("You have not entered a valid choice. Please re-enter.") 
      else: 
       break 
     print("Computer: ", end='') 
     print(computer_choice + "\n") 
     # game evaluation logic 
     if user_input in {"Rock" or "rock"}: 
      if computer_choice == "Paper": 
       computer_points.append(1) 
      elif computer_choice == "Scissor": 
       user_points.append(1) 
      elif computer_choice == user_input: 
       computer_points.append(0) 
       user_points.append(0) 
     elif user_input in {"Paper" or "paper"}: 
      if computer_choice == "Rock": 
       print('test') 
       user_points.append(1) 
      elif computer_choice == "Scissor": 
       computer_points.append(1) 
       print('test') 
      elif computer_choice == user_input: 
       computer_points.append(0) 
       user_points.append(0) 
       print('test') 
     elif user_input in {"Scissor" or "scissor"}: 
      if computer_choice == "Paper": 
       user_points.append(1) 
      elif computer_choice == "Rock": 
       computer_points.append(1) 
      elif computer_choice == user_input: 
       computer_points.append(0) 
       user_points.append(0) 
     round_counter = round_counter + 1 
     print(user_points) 
     print(computer_points) 
    print("Your final score: ", end='') 
    print(sum(user_points)) 
    print("The Computer's final score: ", end='') 
    print(sum(computer_points)) 
    # outcome logic 
    if user_points < computer_points: 
     print("\nSorry, you lost! Better luck next time!") 
    elif user_points > computer_points: 
     print("\nCongratulations, you won!") 
    else: 
     print("\nYou drew with the computer!") 
    # repeat logic 
    print("\nDo you want to play again? Yes or No?") 
    play_again = input().strip() 
    print("\n") 
    if play_again in {"Yes", "yes"}: 
     rockpaperscissor() 
    elif play_again in {"No", "no"}: 
     print("Not a problem. Thanks for playing. Catch you next time!") 

rockpaperscissor() 

# end of code 
+0

最後一行不應縮進,例如。 – Andras

+1

附註:爲什麼要設置一個*昂貴的*嘗試/除非你只打印一些信息。爲什麼不在'if'中打印消息,並使用簡單的'if/else'來打破'else'。 –

+0

@Moses Koledoye ...因爲我是新來的Python我只是試圖練習一個嘗試/除了;是的,if/else可能更合適。 – PS94

回答

1

除了固定的代碼,我做了一些比較細微的變化凝聚,或者整理一下這裏和那裏:

# module packages 
import random 

state = ("rock", "paper", "scissors") 

def get_input(): 
    while True: 
     user_input = input("You: ").strip().lower() 
     if user_input not in state: 
      print("You have not entered a valid choice. Please re-enter.") 
      continue 
     break 
    return user_input 

def compare(move1, move2): 
    """ 
    If draw, return 0 
    If move1 beats move2, return 1 
    If move2 beats move1, return -1 
    """ 

    if move1 == move2: 
     return 0 
    if move2 == state[(state.index(move1) + 1) % 3]: 
     return -1 
    return 1 

def rockpaperscissor(): 
    # data structures and primary variables 
    user_points = 0 
    computer_points = 0 

    # game loop (best of three rounds) 
    for round_counter in range(1, 4): 
     print("\nRound {}".format(round_counter)) 
     computer_choice = random.choice(state) 
     # user input 
     user_input = get_input() 
     print("Computer: {}".format(computer_choice)) 

     # game evaluation logic 
     result = compare(user_input, computer_choice) 
     if result == 1: 
      user_points += 1 
     elif result == -1: 
      computer_points += 1 

     print("Round {} standings:".format(round_counter)) 
     print("User: {}".format(user_points)) 
     print("Computer: {}".format(computer_points)) 

    print("Your final score: {}".format(user_points)) 
    print("The Computer's final score: {}".format(computer_points)) 
    # outcome logic 
    if user_points < computer_points: 
     print("\nSorry, you lost! Better luck next time!") 
    elif user_points > computer_points: 
     print("\nCongratulations, you won!") 
    else: 
     print("\nYou drew with the computer!") 
    # repeat logic 
    print("\nDo you want to play again? Yes or No?") 
    play_again = input().strip() 
    print("\n") 
    if "y" in play_again.lower(): 
     rockpaperscissor() 
    else: 
     print("Not a problem. Thanks for playing. Catch you next time!")  

rockpaperscissor() 
# end of code 

我工作的一些解釋了。

代碼中最大的問題是試圖測試user_input in {"Rock" or "rock"}。這是從口頭語言到代碼的非常直接的翻譯 - 要求「輸入是岩石還是岩石?」可能很自然。但是,在Python中,or實際上是一個用於對布爾值(TrueFalse值)進行操作的特殊字。例如,False or TrueTrue,1 == 4 or 6 < 7True等等。當Python試圖執行"Rock" or "rock"時,它會嘗試將兩個字符串視爲布爾值。因爲它們不是空的,它們表現爲True,所以它們減少爲True,除非它們中的一個是True,所以它大致減少到其中的一個。對於那些不太熟悉真實性的想法以及可以使用的地方,這有點令人困惑,但重要的是修正是用逗號,而不是or來分隔它們。

但是,還有更好的方法來測試 - 使用.lower()方法。然後你可以直接做user_input.lower() == "rock"。請注意,這確實意味着"ROck"等也是有效的,但推測這很好,因爲在那種情況下用戶可能確實意味着搖滾樂。現在我們實際上可以使用這個技巧以及前面對使用in的解釋,將整個驗證合併到user_input.lower() in state中,因爲state實際上就是它的三件事情(因爲我已將狀態修改爲小寫)。

我也將一些你正在做的事情轉移到函數中來提高清晰度。

get_input現在是一個函數,使用該驗證邏輯。它也使用比try/except更簡單的控制流 - 它使用continue語句,該語句跳過循環體的其餘部分,然後返回到開始處,從而跳過中斷,並重新開始整個循環。如果錯過了,則循環中斷並且函數返回。

我也寫了一個函數compare,它做比較兩個動作的邏輯。它使用一點巫術 - 如果move2在狀態move1的右側,move2跳動move1,所以它返回-1,這是最長的條件。它使用模運算符%,所以它「迴繞」回來。

使用這個比較函數,代碼可以找出增加哪個分數而不必列舉每個個案。

除此之外,也有一些小的變化:

round_counter從繪製循環,使其不再具有遞增。

我使用.format很多字符串插值。它具有相對直接,簡潔的語法,功能非常強大。我建議在這種情況下使用它。

user_pointscomputer_points只是整數,就代碼的目的而言,每次看起來都足夠加1。

我在驗證用戶是否想用'y' in play_again.lower()再次播放,並且實際上已經刪除elif條件,因爲如果用戶不給予肯定,它只需要退出。

此外,我已經將表格a = a + 1的一些聲明更改爲a += 1,它的功能相同,但略短一些。

作爲一個評論提到,我已經將導入移動到文件的開頭。

實際上有一些關於此代碼的stil很微小的草率 - rockpaperscissor是遞歸的。這本質上不是一個問題,但它最終可能無限次地自稱 - 如果你找到一個非常熱心的用戶 - 它最終會崩潰。這是因爲當你在Python中「深入」一個函數時,必須在某處存儲整個「堆棧」函數的狀態。這是一個「堆棧框架」,Python只有有限數量的堆棧幀可以在溢出之前分配。請注意,有時一個新的堆棧幀實際上並不需要 - 您的功能就是這種情況,因爲來自任何「父」rockpaperscissor的信息不需要保留。這被稱爲「尾遞歸」函數,許多語言實際上會優化掉尾部調用,所以這不是問題。不幸的是,我們在Python中並沒有那麼奢侈。所以,如果你喜歡,你可以嘗試改變這個代碼來使用while循環,所以你的假想球迷永遠不必停止玩。

這是最終會發生的事情:

Traceback (most recent call last): 
    File "code.py", line 71, in <module> 
    rockpaperscissor() 
    File "code.py", line 29, in rockpaperscissor 
    rockpaperscissor() 
    File "code.py", line 29, in rockpaperscissor 
    rockpaperscissor() 
    File "code.py", line 29, in rockpaperscissor 
    rockpaperscissor() 
    [Previous line repeated 995 more times] 
RecursionError: maximum recursion depth exceeded 

您也提到是有興趣在練習的try/except語句。如果你願意的話,你可以嘗試添加代碼,以免在命令行中的用戶點擊Ctrl-C或Ctrl-D時崩潰,它會優雅地退出,也許說再見。

他們提高

Round 1 
You: ^CTraceback (most recent call last): 
    File "code.py", line 70, in <module> 
    rockpaperscissor() 
    File "code.py", line 38, in rockpaperscissor 
    user_input = get_input() 
    File "code.py", line 8, in get_input 
    user_input = input("You: ").strip().lower() 
KeyboardInterrupt 
分別

Round 1 
You: Traceback (most recent call last): 
    File "code.py", line 70, in <module> 
    rockpaperscissor() 
    File "code.py", line 38, in rockpaperscissor 
    user_input = get_input() 
    File "code.py", line 8, in get_input 
    user_input = input("You: ").strip().lower() 
EOFError 

+0

這真的很有用 - 欣賞它,我想知道如何將離散函數的模塊化方法結合起來。我會拿一杯茶,並會審查。再次感謝:) – PS94

+0

謝謝伊扎克,我對此有一個疑問,因爲我沒有完全理解它,但現在有更好的理解。奇怪的是,在我添加try /之前,除了邏輯似乎用{「Rock」或「rock」}返回了正確的響應,我不知道爲什麼。 – PS94

0

在一個快看什麼,我注意到的是,你希望遊戲的三個最好的執行,但在你的情況,你只需決定誰贏得了比賽第一款T輪的基礎上,所以你需要縮進併爲循環工作三個最好的。

+0

嗨@Daniyal很遺憾,我的帖子沒有正確縮進代碼,但是它運行了三次。我將嘗試重新編輯。 – PS94

0

在這裏,我定你的代碼:

def rockpaperscissor(): #not indented properly 
    # module packages 
    import random 

    # data structures and primary variables 
    state = ["Rock", "Paper", "Scissor"] 
    user_points = [] 
    computer_points = [] 
    round_counter = 1 

    # game loop (best of three rounds) 
    for i in range(3): 
     print("Round " + str(round_counter) + ":") 
     computer_choice = random.choice(state) 
     # user input 
     while True: 
      try: 
       print("You: ", end='') 
       user_input = input().strip() 
       if user_input not in {"Rock", "rock", "Paper", "paper", "Scissor", "scissor"}: 
        raise Exception 
      except Exception: 
       print("You have not entered a valid choice. Please re-enter.") 
      else: 
       break 
     print("Computer: ", end='') 
     print(computer_choice + "\n") 
     # game evaluation logic 
     if user_input in ["Rock", "rock"]: 
      if computer_choice == "Paper": 
       computer_points.append(1) 
      elif computer_choice == "Scissor": 
       user_points.append(1) 
      elif computer_choice == user_input: 
       computer_points.append(0) 
       user_points.append(0) 
     elif user_input in ["Paper", "paper"]: 
      if computer_choice == "Rock": 
       print('test') 
       user_points.append(1) 
      elif computer_choice == "Scissor": 
       computer_points.append(1) 
       print('test') 
      elif computer_choice == user_input: 
       computer_points.append(0) 
       user_points.append(0) 
       print('test') 
     elif user_input in ["Scissor", "scissor"]: 
      if computer_choice == "Paper": 
       user_points.append(1) 
      elif computer_choice == "Rock": 
       computer_points.append(1) 
      elif computer_choice == user_input: 
       computer_points.append(0) 
       user_points.append(0) 
     round_counter = round_counter + 1 
     print(user_points) 
     print(computer_points) 
    print("Your final score: ", end='') 
    print(sum(user_points)) 
    print("The Computer's final score: ", end='') 
    print(sum(computer_points)) 
    # outcome logic 
    if user_points < computer_points: 
     print("\nSorry, you lost! Better luck next time!") 
    elif user_points > computer_points: 
     print("\nCongratulations, you won!") 
    else: 
     print("\nYou drew with the computer!") 
    # repeat logic 
    print("\nDo you want to play again? Yes or No?") 
    play_again = input().strip() 
    print("\n") 
    if play_again in {"Yes", "yes"}: 
     rockpaperscissor() 
    elif play_again in {"No", "no"}: 
     print("Not a problem. Thanks for playing. Catch you next time!") 

rockpaperscissor() 

由你可知道,你可以使用輸入lower()upper()功能,這樣你就不會需要比較USER_INPUT這樣的方式:user_input in ["Rock", "rock"],而不是僅僅使用: user_input.lower() == "rock"

+0

歡呼聲 - 請問最主要的問題是什麼?我想我第一次遇到這個問題,但忘了更新我的代碼。感謝您對此的反饋意見,我現在將着手添加它! – PS94