用于For,While和Try的Python缩进

时间:2017-08-21 20:32:44

标签: python

我写了一个小程序来模拟纸张,剪刀,摇滚游戏。

我正在使用for循环来控制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

3 个答案:

答案 0 :(得分: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"}。这是从口头语言到代码的非常直接的翻译 - 可能看起来很自然地要求&#34;输入是Rock还是摇滚?&#34;。但是,在Python中,or实际上是一个用于操作布尔值(TrueFalse值)的特殊词。例如,False or TrueTrue1 == 4 or 6 < 7True,依此类推。当Python尝试"Rock" or "rock"时,它会尝试将两个字符串视为布尔值。因为它们不是空的,所以它们的行为类似于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,这是最长条件的作用。它使用模运算符%,因此它包含了#34;回来。

使用此比较功能,代码可以找出要增加的分数,而不必枚举每个案例。

除此之外,还有一些较小的变化:

round_counter来自for循环,因此不再需要递增。

我正在使用.format进行字符串插值。它具有相对简单,简洁的语法,非常强大。我建议在这种情况下使用它。

user_pointscomputer_points只是整数,就代码而言,每次添加1就足够了。

我正在验证用户是否想要再次使用'y' in play_again.lower()播放,并且实际上已删除了elif条件,因为如果用户未给出肯定,则只需要退出。

此外,我已将a = a + 1格式的某些陈述更改为a += 1,这些陈述的内容相同但略短。

如上所述,我已将导入移至文件的开头。

对于这段代码,实际上有些东西很简单 - rockpaperscissor是递归的。这本质上不是一个问题,但因为它可能最终无限次地调用自己 - 如果你找到一个非常热情的用户 - 它最终会崩溃。这是因为当你去更深层次的时候。在Python中的一个函数中,必须存储整个&#34; stack&#34;的状态。功能在某处。这是一个&#34;堆栈框架&#34;并且Python只有有限数量的堆栈帧,它们可以在溢出之前分配。请注意,有时候实际上并不需要新的堆栈框架 - 您的功能就是这种情况,因为来自任何&#34;父级的信息&#34; rockpaperscissor不需要保留。这被称为&#34;尾递归&#34;函数,许多语言实际上会优化尾调用,所以这不是问题。不幸的是,我们在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

分别

答案 1 :(得分:0)

快速浏览一下,我注意到你希望游戏能够以三个最好的方式执行,但在你的情况下你只是决定谁在第一轮比赛的基础上赢得比赛,所以你需要缩进并努力做到最好三个循环。

答案 2 :(得分: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"]而只需使用:{{ 1}}。