当前位置:首页>python>地下城冒险:用Python写文字冒险游戏

地下城冒险:用Python写文字冒险游戏

  • 2026-09-08 14:20:02
地下城冒险:用Python写文字冒险游戏

从"画画"到"玩游戏"——你的Python小精灵,终于成为游戏设计师了


🎬 开场:女儿的"终极挑战"

那天,女儿合上了Turtle画图窗口,转头问我:

女儿: "妈妈,画图很好玩,但……能不能做个真正能玩的游戏?"

我: "什么样的游戏?"

女儿: "就是那种……文字冒险游戏!我在爸爸手机上玩过,输入'攻击'就打架,输入'逃跑'就跑路,还有血条、装备、打怪兽!"

爸爸:(从书房探出头)"闺女,这可是大工程啊。要用到类、字典、函数、循环、判断……之前学的全都要用上。"

女儿:(眼睛发亮)"那就是毕业作品了?"

爸爸:(笑)"对,Python小探险家的毕业设计!"

三小时后,女儿做出了她的第一个RPG游戏——《地下城勇士》。
这就是综合项目的魅力:不是学新知识点,而是把旧知识编织成作品。

🎪 第一幕:游戏设计的三大支柱

支柱
像什么
Python实现
🎭 角色系统
演员表
类(Class)
:玩家、怪物都是"角色"类的对象
🗺️ 世界状态
剧本+场景布置
字典(Dictionary)
:存位置、血量、背包
🎮 游戏循环
导演喊"Action"
While循环
:反复问"你要干嘛?"

🎬 第二幕:第一招——用"类"造演员(面向对象入门)

核心思路:把"玩家"和"怪物"都当成角色(Character),有共同的属性(名字、血量、攻击力),但具体值不同。

创建"角色"类(演员模板)

import randomimport timeclass 角色:    """所有角色的基类:玩家和怪物都继承这个"""    def __init__(self, 名字, 血量, 攻击力):        self.名字 = 名字        self.血量 = 血量        self.最大血量 = 血量        self.攻击力 = 攻击力    def 攻击(self, 目标):        """攻击另一个角色"""        伤害 = random.randint(self.攻击力 - 2, self.攻击力 + 2)        目标.血量 -= 伤害        print(f"⚔️ {self.名字}攻击了{目标.名字},造成{伤害}点伤害!")        time.sleep(0.5)  # 停顿0.5秒,有戏剧效果        return 伤害    def 是否存活(self):        return self.血量 > 0    def 显示状态(self):        血条 = "█" * int(self.血量 / self.最大血量 * 10)  # 10格血条        空格 = "░" * (10 - len(血条))        print(f"❤️ {self.名字}: [{血条}{空格}] {self.血量}/{self.最大血量}")# 创建玩家(你自己)class 玩家(角色):    def __init__(self, 名字):        super().__init__(名字, 血量=100, 攻击力=10)        self.等级 = 1        self.经验 = 0        self.背包 = []  # 空背包    def 获得经验(self, 数值):        self.经验 += 数值        print(f"⭐ {self.名字}获得{数值}点经验!")        if self.经验 >= self.等级 * 20:            self.升级()    def 升级(self):        self.等级 += 1        self.最大血量 += 20        self.血量 = self.最大血量  # 回满血        self.攻击力 += 3        print(f"🎉 升级了!{self.名字}升到{self.等级}级!血量+20,攻击+3!")# 创建怪物类class 怪物(角色):    def __init__(self, 名字, 血量, 攻击力, 经验值):        super().__init__(名字, 血量, 攻击力)        self.经验值 = 经验值    def AI行动(self, 玩家):        """简单AI:50%概率攻击,50%概率防御(下回合受伤减半)"""        if random.random() < 0.5:            return self.攻击(玩家)        else:            print(f"🛡️ {self.名字}进入防御姿态!")            return 0
女儿的发现:

"就像Scratch里的'角色'!class是'制作新角色',__init__是'初始化'(设置属性),self就是'我自己'!"


🎭 第三幕:第二招——用"字典"存世界(游戏状态管理)

核心思路:用字典存储整个游戏世界——玩家在哪、地图什么样、有什么物品。
# 游戏世界状态游戏状态 = {    "玩家位置": "入口",    "游戏结束": False,    "当前怪物": None}# 地图设计:每个房间有什么地图 = {    "入口": {        "描述": "你站在地下城入口,火把照亮了前方的走廊。",        "出口": {"北": "大厅"},        "物品": ["小血瓶"]    },    "大厅": {        "描述": "一个巨大的石厅,墙上刻着古老的符文。",        "出口": {"南": "入口", "东": "宝库", "西": "深渊"},        "怪物概率": 0.3  # 30%概率遇到怪物    },    "宝库": {        "描述": "金光闪闪!地上散落着金币和装备。",        "出口": {"西": "大厅"},        "物品": ["大血瓶", "铁剑"],        "怪物": 怪物("宝箱怪", 50, 15, 30)  # 固定守卫    },    "深渊": {        "描述": "黑暗无边,只有你的心跳声。",        "出口": {"东": "大厅"},        "怪物概率": 0.8  # 80%概率遇到怪物!    }}# 物品数据库物品库 = {    "小血瓶": {"类型": "消耗品", "效果": 20, "描述": "恢复20点生命"},    "大血瓶": {"类型": "消耗品", "效果": 50, "描述": "恢复50点生命"},    "铁剑": {"类型": "装备", "攻击力": 5, "描述": "攻击力+5"}}
核心概念:字典嵌套字典,像俄罗斯套娃——大字典是"世界",中字典是"房间",小字典是"物品属性"。

🎪 第四幕:第三招——游戏主循环(导演的Action)

核心思路:用while循环反复问玩家"你要干嘛?",直到游戏结束。
def 主循环(玩家角色):    """游戏主循环"""    print("=" * 40)    print("🏰 欢迎来到地下城!输入'帮助'查看指令。")    print("=" * 40)    while not 游戏状态["游戏结束"]:        当前房间 = 地图[游戏状态["玩家位置"]]        # 显示当前场景        print(f"\n📍 {游戏状态['玩家位置']}")        print(当前房间["描述"])        # 检查物品        if "物品" in 当前房间 and 当前房间["物品"]:            print(f"💎 地上有:{', '.join(当前房间['物品'])}")        # 随机遭遇怪物        if "怪物概率" in 当前房间 and random.random() < 当前房间["怪物概率"]:            遭遇怪物(玩家角色, 生成随机怪物())            if not 玩家角色.是否存活():                print("💀 你死了!游戏结束。")                break        # 玩家输入        指令 = input("\n🎮 你要做什么?(移动/搜索/背包/状态/退出)> ").strip().lower()        # 指令处理        if 指令.startswith("移动"):            移动(玩家角色, 指令)        elif 指令 == "搜索":            搜索房间(玩家角色, 当前房间)        elif 指令 == "背包":            显示背包(玩家角色)        elif 指令 == "状态":            玩家角色.显示状态()        elif 指令 == "帮助":            显示帮助()        elif 指令 == "退出":            print("👋 再见,勇士!")            break        else:            print("❓ 不懂你的指令,输入'帮助'查看可用指令。")def 移动(玩家角色, 指令):    """处理移动指令"""    方向 = 指令.replace("移动", "").strip()    当前房间 = 地图[游戏状态["玩家位置"]]    if 方向 in 当前房间["出口"]:        新位置 = 当前房间["出口"][方向]        游戏状态["玩家位置"] = 新位置        print(f"🚶 你向{方向}移动,来到了{新位置}。")    else:        print("🚫 那个方向没有路!可用方向:", list(当前房间["出口"].keys()))def 搜索房间(玩家角色, 房间):    """搜索房间捡物品"""    if "物品" in 房间 and 房间["物品"]:        物品 = 房间["物品"].pop(0)  # 拿走第一个        玩家角色.背包.append(物品)        print(f"✅ 你捡起了【{物品}】!")    else:        print("🔍 这里什么都没有。")def 遭遇怪物(玩家, 敌人):    """战斗系统"""    print(f"\n⚠️ 遭遇了{敌人.名字}!")    游戏状态["当前怪物"] = 敌人    while 玩家.是否存活() and 敌人.是否存活():        玩家.显示状态()        敌人.显示状态()        行动 = input("🗡️ 攻击/逃跑/使用物品?> ").strip().lower()        if 行动 == "攻击":            玩家.攻击(敌人)            if 敌人.是否存活():                敌人.AI行动(玩家)        elif 行动 == "逃跑":            if random.random() < 0.5:                print("🏃 逃跑成功!")                return            else:                print("❌ 逃跑失败!")                敌人.攻击(玩家)        elif 行动 == "使用物品":            使用物品(玩家)        else:            print("❓ 无效指令")    if 玩家.是否存活():        print(f"🎉 击败了{敌人.名字}!")        玩家.获得经验(敌人.经验值)    else:        游戏状态["游戏结束"] = Truedef 生成随机怪物():    """随机生成怪物"""    怪物表 = [        怪物("史莱姆", 30, 5, 10),        怪物("哥布林", 50, 8, 20),        怪物("骷髅兵", 40, 12, 15)    ]    return random.choice(怪物表)# 启动游戏!英雄 = 玩家(input("请输入你的名字:"))主循环(英雄)

🎥 NG镜头:3个让游戏"崩盘"的Bug

❌ NG镜头1:"怪物打死了还在攻击!"

案发现场:玩家一击打死怪物,但怪物临死前还能反击一次。
导演复盘:

攻击后没检查怪物是否存活!代码顺序应该是:玩家攻击→检查怪物死活→如果活着,怪物才反击。

急救方案:
玩家.攻击(敌人)if 敌人.是否存活():  # 关键检查!    敌人.AI行动(玩家)else:    print("敌人已倒下!")

❌ NG镜头2:"捡了物品,背包里却没有!"

案发现场:搜索房间显示"捡起了铁剑",但查看背包是空的。
导演复盘:

可能玩家角色.背包和玩家.背包搞混了(变量名不一致),或者搜索房间函数里修改的是局部变量,不是真正的玩家对象。

急救方案:确保所有函数都接收玩家对象作为参数,并且修改的是玩家.背包(对象的属性),不是新建变量。

❌ NG镜头3:"输入'移动北',程序说'不懂你的指令'!"

案发现场:玩家输入"移动 北"或"move north",程序不识别。
导演复盘:

字符串匹配太严格!input()拿到的是"移动北"(有空格),但代码判断的是指令 == "移动"。

急救方案:用startswith或分割字符串:
if 指令.startswith("移动"):  # 只要以"移动"开头就行    方向 = 指令.replace("移动", "").strip()  # 提取后面的方向

👨‍💻 程序员爸爸点评:软件工程启蒙

(爸爸看完女儿的200行代码后,在GitHub上开了个仓库)

闺女,你知道你刚才完成了什么吗?一个完整的MVC架构游戏!

M - Model(模型):角色类、怪物类、物品库字典——这是数据层,存所有游戏数据。

V - View(视图): 所有print语句、血条显示、状态面板——这是表现层,玩家看到的。

C - Controller(控制器):主循环、移动、遭遇怪物函数——这是逻辑层,处理用户输入和游戏流程。

关于面向对象:你用继承(玩家和怪物都继承角色),这是代码复用的精髓。以后加"NPC商人",再继承角色改一改就行。

关于游戏状态管理:你用全局字典存状态,这是状态机(State Machine)的雏形。复杂游戏会有"菜单态""战斗态""对话态",用状态机切换。

关于AI:你的AI行动是随机策略。高级AI会用行为树(Behavior Tree):如果血量<30%→逃跑;如果玩家血量<10%→狂暴攻击;否则→50%攻击50%防御。

最后的挑战:你能把游戏改成多房间实时地图吗?用[][]二维列表表示地图,玩家用WASD移动,怪物也会巡逻。这就是Roguelike游戏的雏形,像《元气骑士》那样!


🏆 分层作业:从"地下城"到"开放世界"

✅ 必做作业(基础RPG)

《地下城勇士V1.0》
  • 角色系统:玩家类(血、攻、经验、背包),至少3种怪物

  • 地图系统:至少4个房间,用字典存储

  • 战斗系统:攻击、逃跑、使用物品

  • 物品系统:至少2种消耗品(血瓶)和1种装备

提交方式:可运行的.py文件或Trinket链接。

🥉 青铜挑战(加剧情)

《地下城勇士V1.5:任务系统》
  • 添加NPC:入口处的"老商人",可以对话、买物品

  • 添加任务:老商人说"帮我找回深渊里的魔法石,给你100金币"

  • 添加结局:击败深渊Boss或完成任务,显示"胜利"画面

提示:用if判断任务状态,用字典存"任务进度"。

🥈 白银挑战(加策略)

《地下城勇士V2.0:技能系统》
  • 玩家可以升级学技能:火球术(远程攻击)、治疗术(回血)、狂暴(下回合攻击×2)

  • 技能有冷却时间:用变量记录"还有几回合能用"

  • 怪物也有技能:史莱姆会"分裂"(召唤小史莱姆)

工程思维点:这是资源管理和策略选择——什么时候用火球,什么时候治疗?

🥇 黄金挑战(开放世界)

《地下城勇士V3.0:无限地牢》
  • 程序生成地图:用算法随机生成10×10的地图,每次玩都不一样

  • 永久死亡(Roguelike):死了就从头开始,但解锁"天赋"(下局初始血量+10)

  • 存档系统:用json模块把游戏状态存到文件,下次能读档

爸爸挑战:这是程序化生成(Procedural Generation)和数据持久化,专业游戏开发的核心技术!

🎬 尾声:从玩家到创造者

那天晚上,女儿玩了很久自己的游戏,然后问我:

"妈妈,为什么我自己做的游戏,比买的还好玩?"

"因为我知道它所有的秘密。我知道史莱姆的血量是30,我知道宝库里有宝箱怪,我知道……因为我创造了它。"

是的,孩子。这就是编程的终极快乐——从"玩游戏"到"创造世界"。
你学会了:
  • 用类创造生命

  • 用字典构建世界

  • 用循环驱动时间

  • 用函数编织规则

这不仅仅是编程,这是创世。

📌 系列完结感言

亲爱的探险家,我们的Python小探险家系列到这里就告一段落了。
从第一行print("你好"),到今天的200行RPG游戏,你完成了从消费者到创造者的蜕变。
但这只是开始。Python的世界无穷无尽——数据分析、人工智能、网站开发、自动化脚本……每一个方向都是新的冒险。
记住爸爸的话:"编程不是记住语法,而是学会用代码表达想法。"
现在,去创造属于你的世界吧!
系列进阶预告:《家庭小管家:用Python解决真实问题》
亲爱的探险家,恭喜你完成了Python小探险家系列的"创意篇"!从画画到游戏,你已经掌握了编程的"魔法"。
接下来,我们将进入"实用篇"——用Python解决真实世界的烦恼:

📁文件整理大师:自动分类照片、重命名文件、清理重复项

📊记账本自动化:读取银行账单,自动生成收支图表

🌤️天气提醒助手:每天早上自动查天气,发微信提醒带伞

📧邮件批量发送:给全班同学群发通知,每人称呼不同

编程,不只是创造世界,更是让生活更轻松。
准备好成为家庭小管家了吗?

最新文章

随机文章