学习 Python 并借助 AI 伙伴构建游戏程序
一个基于生成式 AI 的助手,它可以帮助您构建小型项目(如文字游戏)并从中学习编程。




让我们来构建一个简单的文字游戏,从而练习和学习 Python。为了跟随教程指导,您需要一个带有 Amazon Q 开发者版插件的集成开发环境。请按照以下步骤下载并安装该插件。
您从 Amazon Q 获取的建议可能与本教程存在差异,但您可以向 Amazon Q 提供自己的反馈,并获得相似或更好的结果。在任何步骤中,如果您对任何不明确的内容存在疑问,您都可以要求 Amazon Q 为您提供更详细的信息。
找到合适的项目
首先,创建一个包含空的 game.py 文件的新目录。在设置中,打开了集成开发环境,并在编辑器的一侧打开了 Amazon Q 聊天窗口。
在 Amazon Q 聊天窗口中,询问一些想法:
告诉我 5 个可以用 Python 制作的简单文字游戏。

在聊天窗口中,得到了诸如“猜数字”、“上吊的人”以及“文字冒险”等选项。从尝试一个简单的游戏开始,比如“石头、剪刀、布”。因此,在聊天窗口中输入了下一个指令。
给我一个“石头、剪刀、布”游戏的起始 Python 代码。
将 Amazon Q 建议的代码复制到编辑器中(在代码后面有一个“在光标处插入”的按钮),并保存。
import random
def get_choices():
player_choice = input("Enter your choice (rock, paper, scissors): ")
player_choice = player_choice.lower()
options = ["rock", "paper", "scissors"]
computer_choice = random.choice(options)
choices = {"player": player_choice, "computer": computer_choice}
return choices
def check_win(player, computer):
print(f"You chose {player}, computer chose {computer}")
if player == computer:
return "It's a tie!"
elif player == "rock":
if computer == "scissors":
return "Rock smashes scissors! You win!"
else:
return "Paper covers rock! You lose."
elif player == "paper":
if computer == "rock":
return "Paper covers rock! You win!"
else:
return "Scissors cuts paper! You lose."
elif player == "scissors":
if computer == "paper":
return "Scissors cuts paper! You win!"
else:
return "Rock smashes scissors! You lose."
choices = get_choices()
result = check_win(choices["player"], choices["computer"])
print(result)
Amazon Q 在代码后面提供了代码的工作原理解释:
以下是代码的工作原理:
- get_choices ( ) 函数提示用户输入他们的选择(石头、剪刀或布),并随机挑选出电脑的选择。然后它返回一个包含玩家和电脑选择的字典。
- check_win ( ) 函数将玩家和电脑的选择作为参数。它首先打印输出双方所做的选择,接着检查平局条件。如果不是平局,它会根据“石头、剪刀、布”的规则检查玩家的选择和电脑的选择来确定胜者。然后它返回相应的结果信息。
- 通过调用 get_choices ( ) 函数来创建 choices 字典。
- result 变量存储 check_win ( ) 函数经由玩家和电脑选择参数传入而返回的结果信息。
- 最后,将结果信息打印输出到控制台。
这是一个“石头、剪刀、布”游戏的基本实现。您可以通过添加记录分数、多轮游戏或更友好的用户界面等功能来进一步增强它。
阅读这段描述并运行代码,看看会发生什么。
python game.py
Enter your choice (rock, paper, scissors): rock
You chose rock, computer chose scissors
Rock smashes scissors! You win!
游戏雏形初现,但它还有很多可以改进的地方!例如,游戏程序在第一轮结束后就终止了。
在 Amazon Q 的聊天窗口中,要求在第一轮结束后继续运行游戏。还建议重构代码,添加一个处理游戏循环的 play_game 函数。
创建一个 play_game 函数,该函数将循环执行直至玩家输入 "bye" 为止。
采纳 Amazon Q 的所有建议并逐一实现了它们。这里不再逐一复制所有信息,但您可以重现这些步骤并获得类似的答案。以下是这些更改后的完整代码。
import random
def get_choices():
player_choice = input("Enter your choice (rock, paper, scissors) or 'bye' to quit: ")
player_choice = player_choice.lower()
if player_choice == "bye":
return {"player": "bye"}
options = ["rock", "paper", "scissors"]
computer_choice = random.choice(options)
choices = {"player": player_choice, "computer": computer_choice}
return choices
def check_win(player, computer):
print(f"You chose {player}, computer chose {computer}")
if player == computer:
return "It's a tie!"
elif player == "rock":
if computer == "scissors":
return "Rock smashes scissors! You win!"
else:
return "Paper covers rock! You lose."
elif player == "paper":
if computer == "rock":
return "Paper covers rock! You win!"
else:
return "Scissors cuts paper! You lose."
elif player == "scissors":
if computer == "paper":
return "Scissors cuts paper! You win!"
else:
return "Rock smashes scissors! You lose."
def play_game():
while True:
choices = get_choices()
if choices["player"] == "bye":
print("Thanks for playing!")
break
result = check_win(choices["player"], choices["computer"])
print(result)
play_game()
将编辑器中的代码替换为聊天窗口中的新版本,保存并再次运行。如此一来,现在就可以轻松进行多轮游戏了!
Enter your choice (rock, paper, scissors) or 'bye' to quit: rock
You chose rock, computer chose paper
Paper covers rock! You lose.
Enter your choice (rock, paper, scissors) or 'bye' to quit: rock
You chose rock, computer chose rock
It's a tie!
Enter your choice (rock, paper, scissors) or 'bye' to quit: bye
Thanks for playing!
重构代码
让我门尝试避免在代码中多次重复编写这三个可能的选项(石头、剪刀、布),将它们放进一个列表中。首先,向 Amazon Q 提问:
如何在 Python 中创建一个常量?
从 Amazon Q 的答案中了解到惯例做法是使用大写字母。
重构代码,并将三个选项(石头、剪刀、布)放入一个全局列表中。这个列表是常量列表,因此使用大写字母为其命名,如 CHOICES。
从聊天窗口中看到了重构后的代码。代码添加了一个额外的检查(使用递归)来确保玩家的选择是有效的选项。
CHOICES = ["rock", "paper", "scissors"]
def get_choices():
player_choice = input("Enter your choice (rock, paper, scissors) or 'bye' to quit: ")
player_choice = player_choice.lower()
if player_choice == "bye":
return {"player": "bye"}
if player_choice not in CHOICES:
print("Invalid choice. Please try again.")
return get_choices()
computer_choice = random.choice(CHOICES)
choices = {"player": player_choice, "computer": computer_choice}
return choices
在这种情况下,递归不是最优选择。要求 Amazon Q 对代码进行简化:
将 get_choices 函数中的递归替换为循环。
在 Amazon Q 的回应中,递归调用已经被一个 while True 循环所替代。
def get_choices():
while True:
player_choice = input("Enter your choice (rock, paper, scissors) or 'bye' to quit: ")
player_choice = player_choice.lower()
if player_choice == "bye":
return {"player": "bye"}
if player_choice in CHOICES:
computer_choice = random.choice(CHOICES)
choices = {"player": player_choice, "computer": computer_choice}
return choices
else:
print("Invalid choice. Please try again.")
现在改进检查哪方获胜的部分。它包含许多 if / then 条件语句。对于游戏而言,通常需要找到一种数据结构来包含所有规则。这样可以在游戏的多个部分应用这些规则,而无需重复相同的代码。
以下是指令:
对于检查哪方获胜的部分,更新代码以使用 BEATS 字典,该字典对于任何选择都将返回输给该选择的选项。重构代码以从 BEATS 字典中计算 CHOICES。然后,将 check_win 函数重命名为 "who_wins",并使其返回 "player"(玩家)、"computer"(电脑)或 "tie"(平局)。
BEATS = {
"rock": "scissors",
"paper": "rock",
"scissors": "paper"
}
CHOICES = list(BEATS.keys())
. . .
def who_wins(player, computer):
print(f"You chose {player}, computer chose {computer}")
if player == computer:
return "tie"
elif BEATS[player] == computer:
return "player"
else:
return "computer"
由于 who_wins 函数输出的简化,该函数现在仅返回一个单词(player、computer 或 tie),因此 play_game 函数现在负责文本的格式设置和显示。
def play_game():
while True:
choices = get_choices()
if choices["player"] == "bye":
print("Thanks for playing!")
break
result = who_wins(choices["player"], choices["computer"])
if result == "player":
print("You win!")
elif result == "computer":
print("You lose.")
else:
print("It's a tie!")
此外,避免将玩家和电脑的选择混合在同一个函数 (get_choices) 中。玩家从终端进行输入,而电脑使用某种策略(目前是随机性)来做出选择。这是完全不同的两个过程,因此要求将该函数进行拆分:
将 get_choices 函数拆分为两个函数,一个用于玩家,一个用于电脑。
最终的代码包含了 get_player_choice 和 get_computer_choice 两个函数。以下是修改后的完整代码。
import random
BEATS = {
"rock": "scissors",
"paper": "rock",
"scissors": "paper"
}
CHOICES = list(BEATS.keys())
def get_player_choice():
while True:
player_choice = input("Enter your choice (rock, paper, scissors) or 'bye' to quit: ")
player_choice = player_choice.lower()
if player_choice == "bye":
return "bye"
if player_choice in CHOICES:
return player_choice
else:
print("Invalid choice. Please try again.")
def get_computer_choice():
return random.choice(CHOICES)
def who_wins(player, computer):
print(f"You chose {player}, computer chose {computer}")
if player == computer:
return "tie"
elif BEATS[player] == computer:
return "player"
else:
return "computer"
def play_game():
while True:
player_choice = get_player_choice()
if player_choice == "bye":
print("Thanks for playing!")
break
computer_choice = get_computer_choice()
result = who_wins(player_choice, computer_choice)
if result == "player":
print("You win!")
elif result == "computer":
print("You lose.")
else:
print("It's a tie!")
play_game()
get_player_choice 函数还可以进一步改进。例如,"bye" 被重复了两次。在编辑器中选中这个函数,并从上下文菜单中选择 Amazon Q 和 Optimize。可以使用相同的方法来解释、修复或重构代码,或者使用自定义提示与所选代码进行交互以执行不同的操作,例如要求以特定方式更改代码。
根据建议,将函数替换为这个优化后的版本:
def get_player_choice():
while True:
player_choice = input("Enter your choice (rock, paper, scissors) or 'bye' to quit: ").lower()
if player_choice == "bye" or player_choice in CHOICES:
return player_choice
print("Invalid choice. Please try again.")
跟踪得分
在改进电脑策略之前,让我们先跟踪玩家的得分,这样在一场长时间的游戏结束后,我们就可以知道谁获胜最多。以下是指令:
更新代码以在 play_game 函数内存储玩家和电脑的获胜次数。在每一轮结束时打印输出得分。最后,打印输出谁赢得更多。
为了避免在响应中使用全局变量,指定在 play_game 函数内存储得分。即使全局变量在小型程序中也许是可接受的,但最好避免使用它们,因为当应用程序增长并变得更加复杂时,它们可能会引发问题。
def play_game():
player_wins = 0
computer_wins = 0
. . .
if result == "player":
print("You win!")
player_wins += 1
elif result == "computer":
print("You lose.")
computer_wins += 1
. . .
print(f"Score: Player {player_wins} - Computer {computer_wins}")
if player_wins > computer_wins:
print("You won more games!")
elif computer_wins > player_wins:
print("Computer won more games.")
else:
print("It's a tie overall.")
做一下快速测试来查看这是如何工作的。
Enter your choice (rock, paper, scissors) or 'bye' to quit: rock
You chose rock, computer chose scissors
You win!
Score: Player 1 - 0 Computer
Enter your choice (rock, paper, scissors) or 'bye' to quit: rock
You chose rock, computer chose scissors
You win!
Score: Player 2 - 0 Computer
Enter your choice (rock, paper, scissors) or 'bye' to quit: bye
Thanks for playing!
You won more games!
既然我们已经按照预期进行分数管理,现在是时候改进电脑策略了。
改进电脑策略
与其完全随机地做出选择,不如让电脑通过玩家之前的选择去理解他们的游戏玩法。为此,需要创建一个数据结构,当电脑预测到玩家的选择时,返回最佳对策。
计算出与 BEATS 字典相反的字典,并将其命名为 BEATEN_BY。
BEATEN_BY = {value: key for key, value in BEATS.items()}
现在,尝试通过玩家历史记录来改进电脑的选择方式:
通过以下更改来优化电脑的策略。在 get_computer_choice 函数中,输入一个包含玩家之前所有选择的列表。然后,从列表中随机选取一个元素,并返回能够打败该选择的选项(即 BEATEN_BY[random element] 的值)。在电脑做出选择后,更新这个列表。如果列表为空,则返回随机选择。
必须在这里非常清楚地说明如何使用这些数据结构,因为如果缺少上下文说明,BEATS 和 BEATEN_BY 字典可能会令人困惑。以下是建议的代码:
def get_computer_choice(player_choices):
if player_choices:
previous_choice = random.choice(player_choices)
return BEATEN_BY[previous_choice]
else:
return random.choice(CHOICES)
def play_game():
. . .
player_choices = []
while True:
player_choice = get_player_choice()
. . .
computer_choice = get_computer_choice(player_choices)
. . .
player_choices.append(player_choice)
这个策略比随机性策略要好,但对于长时间的游戏,它还可以改进。事实上,最好不要依赖过于陈旧的历史记录。
优化电脑的策略,使其仅使用玩家历史记录中的最新 n 个条目,其中 n 等于 10。将这个变量 n 命名为 MEMORY_LENGTH。
以下是更新后的 get_computer_choice 函数和 MEMORY_LENGTH 常量。
MEMORY_LENGTH = 10
. . .
def get_computer_choice(player_choices):
if len(player_choices) > MEMORY_LENGTH:
recent_choices = player_choices[-MEMORY_LENGTH:]
else:
recent_choices = player_choices
if recent_choices:
previous_choice = random.choice(recent_choices)
return BEATEN_BY[previous_choice]
else:
return random.choice(CHOICES)
我们快要完成了。get_computer_choice 函数还可以进一步改进。例如,在 Python 中,即使数组中的元素少于所请求的数量,也可以进行切片操作。我选中这个函数,并使用上下文菜单,让 Amazon Q 来优化代码。
以下是优化后的函数:
def get_computer_choice(player_choices):
recent_choices = player_choices[-MEMORY_LENGTH:] if player_choices else []
if recent_choices:
previous_choice = random.choice(recent_choices)
return BEATEN_BY[previous_choice]
else:
return random.choice(CHOICES)
这个版本的函数更简洁易懂。通过这些策略的改进,电脑无疑成为了一个更出色的玩家。
Enter your choice (rock, paper, scissors) or 'bye' to quit: rock
You chose rock, computer chose scissors
You win!
Score: Player 1 - Computer 0
Enter your choice (rock, paper, scissors) or 'bye' to quit: rock
You chose rock, computer chose paper
You lose.
Score: Player 1 - Computer 1
Enter your choice (rock, paper, scissors) or 'bye' to quit: rock
You chose rock, computer chose paper
You lose.
Score: Player 1 - Computer 2
Enter your choice (rock, paper, scissors) or 'bye' to quit: bye
Thanks for playing!
Computer won more games.
收尾工作以及使用类
让我们请求进行最后一次更新,以清理程序的启动方式。
仅在直接运行此程序而非作为模块导入时,才运行 play_game 函数。
这会将程序的最终部分更改为使用一个常见的 Python 惯例。
if __name__ == "__main__":
play_game()
当前的游戏实现似乎不错,但是否可以将不同的游戏功能更紧密地结合在一起?
import random
BEATS = {
"rock": "scissors",
"paper": "rock",
"scissors": "paper"
}
BEATEN_BY = {value: key for key, value in BEATS.items()}
CHOICES = list(BEATS.keys())
MEMORY_LENGTH = 10
def get_player_choice():
while True:
player_choice = input("Enter your choice (rock, paper, scissors) or 'bye' to quit: ").lower()
if player_choice == "bye" or player_choice in CHOICES:
return player_choice
print("Invalid choice. Please try again.")
def get_computer_choice(player_choices):
if len(player_choices) > MEMORY_LENGTH:
recent_choices = player_choices[-MEMORY_LENGTH:]
else:
recent_choices = player_choices
if recent_choices:
previous_choice = random.choice(recent_choices)
return BEATEN_BY[previous_choice]
else:
return random.choice(CHOICES)
def who_wins(player, computer):
print(f"You chose {player}, computer chose {computer}")
if player == computer:
return "tie"
elif BEATS[player] == computer:
return "player"
else:
return "computer"
def play_game():
player_wins = 0
computer_wins = 0
player_choices = []
while True:
player_choice = get_player_choice()
if player_choice == "bye":
print("Thanks for playing!")
break
computer_choice = get_computer_choice(player_choices)
result = who_wins(player_choice, computer_choice)
if result == "player":
print("You win!")
player_wins += 1
elif result == "computer":
print("You lose.")
computer_wins += 1
else:
print("It's a tie!")
player_choices.append(player_choice)
print(f"Score: Player {player_wins} - Computer {computer_wins}")
if player_wins > computer_wins:
print("You won more games!")
elif computer_wins > player_wins:
print("Computer won more games.")
else:
print("It's a tie overall.")
if __name__ == "__main__":
play_game()
让我们尝试使用面向对象的方法。整个游戏程序可以嵌入到一个类中。然后,每个游戏程序都是该类的一个实例。以下是请求样本:
用一个实现相同功能的 RockPaperScissorsGame 类来替换 BEATS、BEATEN_BY 和 CHOICES 这些数据结构。这个类应当有一个内置的 BEATS 结构,并据此计算所有其他数据。
以下是最终代码,供您参考。这个结果可能不够完美,但比之前有所改进。如果您一直跟着做,您可能会得到相似但不完全相同的代码。您可以继续向 Amazon Q 提问,并给出添加更多功能或重构代码的指令。
import random
class RockPaperScissorsGame:
def __init__(self):
self.BEATS = {
"rock": "scissors",
"paper": "rock",
"scissors": "paper"
}
self.BEATEN_BY = {value: key for key, value in self.BEATS.items()}
self.CHOICES = list(self.BEATS.keys())
def get_player_choice(self):
while True:
player_choice = input("Enter your choice (rock, paper, scissors) or 'bye' to quit: ").lower()
if player_choice == "bye" or player_choice in self.CHOICES:
return player_choice
print("Invalid choice. Please try again.")
def get_computer_choice(self, player_choices, memory_length=10):
if len(player_choices) > memory_length:
recent_choices = player_choices[-memory_length:]
else:
recent_choices = player_choices
if recent_choices:
previous_choice = random.choice(recent_choices)
return self.BEATEN_BY[previous_choice]
else:
return random.choice(self.CHOICES)
def who_wins(self, player, computer):
print(f"You chose {player}, computer chose {computer}")
if player == computer:
return "tie"
elif self.BEATS[player] == computer:
return "player"
else:
return "computer"
def play_game(self):
player_wins = 0
computer_wins = 0
player_choices = []
while True:
player_choice = self.get_player_choice()
if player_choice == "bye":
print("Thanks for playing!")
break
computer_choice = self.get_computer_choice(player_choices)
result = self.who_wins(player_choice, computer_choice)
if result == "player":
print("You win!")
player_wins += 1
elif result == "computer":
print("You lose.")
computer_wins += 1
else:
print("It's a tie!")
player_choices.append(player_choice)
print(f"Score: Player {player_wins} - Computer {computer_wins}")
if player_wins > computer_wins:
print("You won more games!")
elif computer_wins > player_wins:
print("Computer won more games.")
else:
print("It's a tie overall.")
if __name__ == "__main__":
game = RockPaperScissorsGame()
game.play_game()
如果您喜欢本节关于 AI 辅助编程的内容,请别忘记尝试一下 Amazon Q 开发者版。