3天精通文本游戏开发:从基础到15种手势的Python实战指南
你还在为如何将面向对象编程应用到实际项目中而烦恼吗?还在寻找既能巩固知识点又有趣的编程练习吗?本文将通过3天时间,带你从零构建一个完整的文本游戏系统,从经典的"石头剪刀布"到复杂的15种手势版本,全面掌握Python类设计、游戏逻辑实现和数据驱动开发。读完本文你将获得:
- 面向对象编程(OOP)的实战经验
- 游戏循环与状态管理的核心逻辑
- CSV数据解析与动态配置应用
- 从简单到复杂系统的迭代开发能力
项目概述与准备工作
本项目是"100天Python编程挑战"的第13-15天内容,专注于文本交互游戏的开发。我们将通过构建两个版本的"石头剪刀布"游戏,逐步掌握Python面向对象编程和游戏开发的核心概念。
技术栈与环境配置
# 克隆项目仓库
git clone https://gitcode.com/gh_mirrors/10/100daysofcode-with-python-course
# 进入项目目录
cd 100daysofcode-with-python-course/days/13-15-text-games
项目结构解析
13-15-text-games/
├── README.md # 任务说明文档
├── data/
│ ├── battle-table.csv # 15种手势胜负关系数据
│ └── sample_reader.py # CSV解析示例代码
└── dnd_game/ # 额外文本游戏示例(可选扩展)
Day 13:面向对象基础与项目初始化
核心类设计
文本游戏的核心在于对游戏实体和规则的抽象。我们需要设计两个基础类:Roll(手势)和Player(玩家)。
项目初始化实现
首先创建游戏入口文件rps_game.py,实现基础框架:
class Roll:
def __init__(self, name):
self.name = name
self.defeats = [] # 能击败的手势列表
self.defeated_by = [] # 被击败的手势列表
def can_defeat(self, other_roll):
"""判断当前手势是否能击败另一个手势"""
return other_roll.name in self.defeats
def is_defeated_by(self, other_roll):
"""判断当前手势是否被另一个手势击败"""
return other_roll.name in self.defeated_by
class Player:
def __init__(self, name):
self.name = name
self.score = 0
def get_name(self):
return self.name
def increment_score(self):
self.score += 1
def get_score(self):
return self.score
def print_header():
"""打印游戏标题头"""
print("=" * 40)
print(" 石头剪刀布游戏 v1.0")
print("=" * 40)
print()
def get_player_name():
"""获取玩家姓名"""
return input("请输入你的名字: ").strip()
def main():
print_header()
name = get_player_name()
# 创建玩家
player = Player(name)
computer = Player("电脑")
print(f"\n欢迎 {player.get_name()}! 准备和{computer.get_name()}对战吧!")
if __name__ == "__main__":
main()
Day 14:基础版石头剪刀布实现
游戏核心逻辑
基础版游戏包含三种手势:石头(Rock)、剪刀(Scissors)和布(Paper),它们之间的胜负关系如下:
手势关系实现
扩展Roll类,添加手势间的胜负关系定义:
def build_basic_rolls():
"""创建基础版的三种手势及其关系"""
# 创建手势实例
rock = Roll("Rock")
scissors = Roll("Scissors")
paper = Roll("Paper")
# 定义胜负关系
rock.defeats = [scissors.name]
rock.defeated_by = [paper.name]
scissors.defeats = [paper.name]
scissors.defeated_by = [rock.name]
paper.defeats = [rock.name]
paper.defeated_by = [scissors.name]
return [rock, scissors, paper]
游戏循环实现
实现游戏的主要流程控制逻辑:
import random
def player_choose_roll(rolls):
"""玩家选择手势"""
print("\n请选择手势:")
for i, roll in enumerate(rolls, 1):
print(f"{i}. {roll.name}")
while True:
try:
choice = int(input(f"输入选项(1-{len(rolls)}): ")) - 1
if 0 <= choice < len(rolls):
return rolls[choice]
print(f"请输入1到{len(rolls)}之间的数字")
except ValueError:
print("请输入有效的数字")
def computer_choose_roll(rolls):
"""电脑随机选择手势"""
return random.choice(rolls)
def determine_winner(p1_roll, p2_roll):
"""判断一轮的胜负"""
if p1_roll.name == p2_roll.name:
return None # 平局
if p2_roll.name in p1_roll.defeats:
return "player1"
return "player2"
def game_loop(player1, player2, rolls, rounds=3):
"""游戏主循环"""
current_round = 1
while current_round <= rounds:
print(f"\n===== 第 {current_round} 轮 =====")
# 选择手势
p1_roll = player_choose_roll(rolls)
p2_roll = computer_choose_roll(rolls)
# 显示选择
print(f"\n{player1.get_name()} 选择了: {p1_roll.name}")
print(f"{player2.get_name()} 选择了: {p2_roll.name}")
# 判断胜负
winner = determine_winner(p1_roll, p2_roll)
if winner is None:
print("这一轮是平局!")
else:
if winner == "player1":
player1.increment_score()
print(f"{player1.get_name()} 赢得了这一轮!")
else:
player2.increment_score()
print(f"{player2.get_name()} 赢得了这一轮!")
# 显示当前比分
print(f"比分: {player1.get_name()} {player1.get_score()} - {player2.get_score()} {player2.get_name()}")
current_round += 1
# 确定最终赢家
print("\n===== 游戏结束 =====")
if player1.get_score() > player2.get_score():
print(f"恭喜 {player1.get_name()} 获胜!")
elif player2.get_score() > player1.get_score():
print(f"{player2.get_name()} 获胜!")
else:
print("游戏以平局结束!")
# 更新main函数
def main():
print_header()
rolls = build_basic_rolls()
name = get_player_name()
player1 = Player(name)
player2 = Player("Computer")
game_loop(player1, player2, rolls)
if __name__ == "__main__":
main()
Day 15:代码优化与进阶版实现
基础版代码优化
对现有代码进行重构,提高可维护性和可扩展性:
- 添加类型注解,提高代码可读性
- 优化异常处理,增强程序健壮性
- 提取重复逻辑为辅助函数
进阶版:15种手势实现
进阶版游戏包含15种手势,其胜负关系通过CSV文件定义。这种数据驱动的方式使游戏更易于扩展。
CSV数据解析
使用Python的csv模块解析手势关系数据:
import csv
from typing import List, Dict
def load_rolls_from_csv(file_path: str) -> List[Roll]:
"""从CSV文件加载15种手势及其关系"""
rolls = {}
# 读取CSV文件并创建所有手势
with open(file_path, 'r') as f:
reader = csv.DictReader(f)
for row in reader:
roll_name = row['Attacker']
rolls[roll_name] = Roll(roll_name)
# 再次读取CSV以设置胜负关系
with open(file_path, 'r') as f:
reader = csv.DictReader(f)
for row in reader:
attacker_name = row['Attacker']
attacker_roll = rolls[attacker_name]
for defender_name, result in row.items():
if defender_name == 'Attacker' or defender_name == attacker_name:
continue
if result.strip().lower() == 'win':
attacker_roll.defeats.append(defender_name)
elif result.strip().lower() == 'lose':
attacker_roll.defeated_by.append(defender_name)
return list(rolls.values())
15种手势游戏流程
集成进阶版到主程序
def main():
print_header()
# 让用户选择游戏版本
print("请选择游戏版本:")
print("1. 基础版 (石头、剪刀、布)")
print("2. 进阶版 (15种手势)")
while True:
choice = input("输入选项 (1/2): ").strip()
if choice == '1':
rolls = build_basic_rolls()
break
elif choice == '2':
try:
rolls = load_rolls_from_csv('data/battle-table.csv')
break
except FileNotFoundError:
print("找不到进阶版数据文件,请确保data目录下有battle-table.csv")
print("将使用基础版游戏...")
rolls = build_basic_rolls()
break
else:
print("请输入1或2选择游戏版本")
name = get_player_name()
player1 = Player(name)
player2 = Player("Computer")
# 进阶版游戏增加回合数
rounds = 5 if len(rolls) > 3 else 3
game_loop(player1, player2, rolls, rounds)
15种手势对比表
部分手势及其胜负关系示例:
| 手势 | 能击败 | 被击败 |
|---|---|---|
| Rock | Scissors, Sponge, Wolf, Tree, Human | Gun, Lightning, Devil, Dragon, Water, Air, Paper, Fire |
| Gun | Lightning, Devil, Dragon, Water, Air, Paper, Sponge | Rock, Wolf, Tree, Human, Snake, Scissors, Fire |
| Paper | Rock, Gun, Lightning, Devil, Dragon, Water, Air | Scissors, Fire, Sponge, Wolf, Tree, Human, Snake |
项目扩展与学习资源
功能扩展建议
- 多人对战模式:添加本地多人对战功能,支持两人轮流操作
- 游戏难度设置:为电脑玩家添加不同难度级别(简单、中等、困难)
- 历史记录:使用文件系统或数据库保存游戏记录
- 图形界面:使用Tkinter或PyQt为游戏添加简单的图形界面
进阶学习路径
常见问题解决
- CSV文件路径问题:确保CSV文件路径正确,或使用绝对路径
- 手势关系复杂:通过
print语句调试胜负关系是否正确加载 - 用户输入验证:增强输入处理,防止无效输入导致程序崩溃
总结与成果展示
通过这三天的学习,我们从基础的"石头剪刀布"游戏,逐步扩展到包含15种手势的复杂版本,掌握了以下技能:
- 面向对象编程思想的实际应用
- 游戏核心逻辑与状态管理
- 数据驱动开发(通过CSV文件动态配置游戏规则)
- 代码重构与优化技巧
最终代码结构
rps_game.py # 游戏主程序
data/
battle-table.csv # 15种手势关系数据
运行示例
========================================
石头剪刀布游戏 v1.0
========================================
请选择游戏版本:
1. 基础版 (石头、剪刀、布)
2. 进阶版 (15种手势)
输入选项 (1/2): 2
请输入你的名字: Alice
===== 第 1 轮 =====
请选择手势:
1. Rock
2. Gun
3. Lightning
4. Devil
5. Dragon
6. Water
7. Air
8. Paper
9. Sponge
10. Wolf
11. Tree
12. Human
13. Snake
14. Scissors
15. Fire
输入选项(1-15): 3
Alice 选择了: Lightning
Computer 选择了: Tree
Lightning 击败了 Tree!
Alice 赢得了这一轮!
比分: Alice 1 - 0 Computer
现在你已经掌握了文本游戏开发的核心技术。继续探索,你可以创建更复杂的角色扮演游戏(RPG)或策略游戏。记得在社交媒体上分享你的成果,并标记#100DaysOfCode话题!
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



