我刚刚完成了基础中级Python课程的学习,并想测试自己。这是我的基本岩石纸剪刀游戏。
def play():
import random
player_score = 0
ai_score = 0
while True:
try:
user_choice = int(input("\nRock: 1"
"\nPaper: 2"
"\nScissor: 3"
"\nWrite the number of the object you choose: "))
except NameError:
print("You can only enter number.")
continue
except ValueError:
print("You can only enter number.")
continue
if user_choice not in range(1, 4):
print("Invalid number, you have to write numbers between 1-3")
continue
rps = {1: "Rock", 2: "Paper", 3: "Scissor"}
ai_choice = random.randint(1, 3)
print(f"\nPlayer's choice: {rps[user_choice]} | AI's choice: {rps[ai_choice]}")
if user_choice == ai_choice:
print("Draw!")
elif user_choice == 1:
if ai_choice == 2:
print("AI's paper wrapped Player's rock, AI won this round!")
ai_score += 1
elif ai_choice == 3:
print("Player's rock crushed AI's scissor, Player won this round!")
player_score += 1
elif user_choice == 2:
if ai_choice == 1:
print("Players's paper wrapped AI's rock, Player won this round!")
player_score += 1
elif ai_choice == 3:
print("AI's scissor cut Player's paper, AI won this round!")
ai_score += 1
elif user_choice == 3:
if ai_choice == 1:
print("AI's rock crushed Player's scissor, AI won this round!")
ai_score += 1
elif ai_choice == 2:
print("Player's scissor cut AI's paper, Player won this round!")
player_score += 1
print(f"\nPlayer's score: {player_score} | AI's score: {ai_score}"
f"\nGame ends when player or AI's score reach 3!")
if player_score == 3:
print("Game over, Player won!")
quit()
elif ai_score == 3:
print("Game over, AI won!")
proceed = input("Wanna try again and show the AI your unmatched and great wisdom?"
"\nWrite Y or N >: ").lower()
if proceed == "y":
play()
elif proceed == "n":
quit()
else:
print("Invalid command, exiting program...")
quit()
if __name__ == "__main__":
play()
那么,你怎么看?我怎样才能做得更好,我的错误是什么?
发布于 2019-11-06 16:17:04
我想说,在您的代码中有两个主要问题。
第一个是主循环,它非常不清楚,很多if语句都是用continue
和quit()
填充的,这是spagetthi代码,它使您的代码更难读,所以很难调试,因为这会跳到任何地方。
第二个问题是缺乏面向对象程序设计( OOP ),这可以很好地适应这种情况。游戏通常使用强大的面向对象语言(Unreal使用C++,Unreal使用C#等),因为组件之间有很强的交互,并且非常有利于抽象和模块化。公平地说,这并不是真正需要的短期游戏,如岩石剪刀,但它阻止你进一步扩大游戏规模。
我建议您进行很少的设计改进:
将代码拆分为函数,第一种可能是游戏循环中应该使用的游戏获胜条件,以避免不必要的无限循环,这与常量条件(如while True:
)相同。将此语句替换为while has_game_ended():
,改为has_game_ended
,如下所示:
def has_game_ended(player_score: int, ia_score: int) -> bool:
if player_score == 3 or ia_score == 3:
print("Game over: {} won!".format("player" if player_score == 3 else "AI"))
return True
return False
然后使用一个枚举来列出您的移动以使它们更易于在代码中重用(论文比1更有意义),并使用操作符重载启用比较,请注意,这是一个特定于游戏规则的棘手的比较。
from enum import Enum
class Move(Enum):
PAPER = 1
ROCK = 2
SCISSORS = 3
def __lt__(self, other):
return (self is Move.ROCK and other is Move.PAPER) or (self is Move.Paper and other is Move.SCISSORS) or (self is Move.SCISSORS and other is Move.ROCK)
现在你可以写:
>>> player_choice = Move.PAPER
>>> ia_choice = Move.ROCK
>>> player_choice < ia_choice
True
就像
player_score = player_score + int(player_choice > ia_choice)
ia_score = ia_score + int(ia_choice > player_choice)
这很好,因为它不再比较两个整数,而是比较两个Move
,这与操作符重载有很大的不同。
避免脚本中的quit()
,它完全减少了代码流,并且不允许很好的错误处理,相反,它更倾向于循环条件,或者尝试为意外行为定制异常的you语句(例如,当您使用无效命令时,如下面的示例所示)。
def WrongCommand(Exception):
pass
if __name__ == "__main__":
try:
play()
except WrongCommand:
print("Invalid command, exiting program...")
https://codereview.stackexchange.com/questions/231955
复制相似问题