剪刀、石头、布作业的意外结果



我正在编程课上做一个剪刀、石头、布的游戏来学习函数。

我的程序按照预期运行,除了平局时,它重复两次结果。

我有一个函数来获取用户的选择,我有一个函数来生成计算机的选择,我有一个函数来确定获胜者并显示它(使用结果+赢/输函数来显示获胜者),所有这三个都在一个名为Play_the_Game的函数中。

在领带的情况下,函数打印&;It's a tie!&;并再次调用Play_the_Game

这是我得到的输出:

请选择-石头,布,还是剪刀?岩石
计算机选择岩石。
平局,再选一次

请选择-石头,布,还是剪刀?岩石
计算机选择纸张。
纸盖石头,你输了。
纸盖石头,你输了。

def user_choice():
choice = input("Please choose - Rock, Paper, or Scissors? ")
global choice_int
choice_int = int()
if choice == "Rock" or choice == "rock":
choice_int = 1
elif choice == "Paper" or choice == "paper":
choice_int = 2
elif choice == "Scissors" or choice == "scissors":
choice_int = 3
else:
print("That is not a valid choice.")
user_choice()

def comp_choice():
global choice
choice = random.randint(1,3)
if choice == 1:
print("The computer chooses rock.")
if choice == 2:
print("The computer chooses paper.")
if choice == 3:
print("The computer chooses scissors.")
return choice
### does comparisons to determine the winner
def determine_winner():
if choice_int == 1:
if choice == 1:
Tied()
if choice == 2:
print(PaperVRock(), Loser())
if choice == 3:
print(RockVScissors(), Winner())
if choice_int == 2:
if choice == 1:
print(PaperVRock(), Winner())
if choice == 2:
Tied()
if choice == 3: 
print(ScissorsVPaper(), Loser())
if choice_int == 3:
if choice == 1:
print(RockVScissors(), Loser())
if choice == 2:
print(ScissorsVPaper(), Winner())
if choice == 3:
Tied()

def PaperVRock():
return "Paper covers rock, "
def ScissorsVPaper():
return "Scissors cuts paper, "
def RockVScissors():
return "Rock smashes scissors, "
def Winner():
return "you win!"
def Loser():
return "you lose."
def Tied():
print("The game is tied, choose again.")
print()
Play_the_Game()

### Take everything together
def Play_the_Game():
user_choice()
comp_choice()
determine_winner()
Play_the_Game()

你的问题是,你在重复游戏,当你得到一个平局,使用递归,你的if条款在determin_winner是相互独立的。如果第一个游戏是用石头或布,而另一个游戏是由不同的玩家用剪刀或布,那么这两个功能可以让你在最后得到多个输出结果。

为了理解发生了什么,让我们首先考虑一个不同的函数:

def foo():
if a == 1:
do_stuff()
if a == 2:
do_some_other_stuff()

在这个函数中,您有两个if语句,用于测试某个全局变量a的值。现在,由于a不能同时等于12,因此您可能期望只运行do_stuffdo_other_stuff函数中的一个。但是如果do_stuff改变了全局变量的值呢?在这种情况下,如果a最初是1,但被更改为2,这两个函数可以依次运行。

这是代码中发生的事情的简化版本。当在determine_winner的前两个顶级if块之一检测到平局时(即当用户选择了"rock"或"剪刀"),你调用Tied函数,这将导致整个游戏重玩。作为重玩的一部分,代表玩家和电脑选择的全局变量将被改变,所以当决胜局最终结束时,原始的determine_result函数将继续运行,并将进行更多的测试来看看谁赢了。就像我上面写的例子一样,您通常不会期望它找到另一个结果,因为我们已经在前面的一个分支中找到了一个平局。但是,由于if语句是独立的,并且依赖于全局变量,因此另一个语句也可能为真。

有几种方法可以解决这个问题。最简单的方法可能是在每个复合测试中使用elif而不是if来进行除第一个测试之外的所有测试。这使得测试相互依赖,因为只有一个分支可以运行,即使在测试它们的时候有多个条件为真。

def determine_winner():
if choice_int == 1:
if choice == 1:
Tied()
elif choice == 2:
print(PaperVRock(), Loser())
elif choice == 3:
print(RockVScissors(), Winner())
elif choice_int == 2:
if choice == 1:
print(PaperVRock(), Winner())
elif choice == 2:
Tied()
elif choice == 3: 
print(ScissorsVPaper(), Loser())
elif choice_int == 3:
if choice == 1:
print(RockVScissors(), Loser())
elif choice == 2:
print(ScissorsVPaper(), Winner())
elif choice == 3:
Tied()

另一个选择是改变代码的设计,以避免使用递归进行流控制。当你想要多次运行一些东西时,使用循环!下面是Rock - Paper scissors的草图:

def play_the_game():
pchoice = cchoice = None
while pchoice == cchoice:
pchoice = user_choice()
cchoice = comp_choice()
determine_winner(pchoice, cchoice)

有了这个游戏框架,determine_winner函数可以只向玩家报告平局,但不需要重新运行游戏,循环将处理这个问题。您可能希望在user_choice中使用类似的循环,反复要求用户做出选择,直到得到有效的答案。

另一个可以改进代码并帮助您避免类似问题的设计更改是避免使用全局变量。你的问题是由一个游戏的全局变量(第一场比赛,平局)被第二场比赛中使用的相同全局变量覆盖造成的。如果使用参数,就可以避免这种情况。我在上面的play_the_game函数的草图展示了它是如何工作的,X_choice函数return表示所选的值,determine_answer函数接受这两个选择作为参数。如果您愿意,您可以只做这样的更改(同时保留递归结构),这也会解决您当前的问题,但最好是摆脱递归和全局变量!