技术准备

在开始编码之前,我们需要准备开发环境和相关工具。以下是开发 元素大师 所需的技术栈和资源。

1. 技术栈

  • 编程语言:Python 3.x(推荐 3.8 或更高版本)。
  • 核心库
  • random:生成随机事件,如实验失败或新任务。
  • time:控制游戏节奏和实验时间。
  • json:保存和加载游戏状态。
  • pygame(可选):用于图形界面和反应可视化。
  • 数据存储
  • 使用字典存储元素和反应规则。
  • 列表存储任务、库存和实验室状态。
  • 用户界面:基于命令行界面(CLI)显示元素、任务和交互,图形界面作为扩展。
  • 依赖安装
  • randomtime 和 json 是 Python 标准库,无需额外安装。
  • pygame(可选):pip install pygame

2. 开发环境

确保已安装 Python(可从 python.org 下载)。推荐使用 Visual Studio Code 或 PyCharm 作为开发工具,提供代码补全和调试支持。本游戏的核心版本基于 CLI,扩展部分引入图形界面。项目结构如下:

element_synthesis_game/
├── main.py           # 主程序入口
└── game.py           # 游戏逻辑模块

3. 游戏目标

玩家将扮演化学家,目标是在 30 个回合(模拟 30 天)内完成所有实验任务,解锁所有反应并提升实验室等级。游戏采用回合制,每回合代表一天,玩家需要:

  • 合成元素:组合基础元素生成新元素或化合物。
  • 完成任务:合成指定目标,获得能量点和声誉。
  • 升级实验室:提升设备等级,解锁高级反应。
  • 管理资源:平衡能量、时间和元素库存。
  • 应对事件:处理实验失败或设备故障。

游戏设计与核心功能

1. 游戏结构

我们将游戏分解为多个模块,使用类和函数封装功能,确保代码清晰且易于维护。以下是核心设计:

  • Element 类:表示化学元素或化合物,包含名称和属性。
  • Reaction 类:定义合成反应规则,如“氢 + 氧 → 水”。
  • Lab 类:管理实验室状态,包括设备等级和能量。
  • Game 类:管理游戏状态、任务、库存和主循环。
  • 算法
  • 合成检查:验证元素组合是否符合反应规则。
  • 任务分配:生成随机任务,引导玩家探索反应。
  • 数据结构
  • 元素库存:字典存储元素名称和数量。
  • 反应规则:字典映射元素组合到产物。
  • 任务:列表存储目标元素和奖励。
  • 游戏状态:实验室等级、能量、声誉和回合数。

2. 核心代码实现

以下是游戏的完整代码框架,我们将逐一讲解每个模块的实现细节。

2.1 元素类:Element

Element 类定义化学元素或化合物的属性。

# game.py
class Element:def __init__(self, name, category, energy_cost):"""初始化元素"""self.name = name  # 元素或化合物名称self.category = category  # Basic, Compoundself.energy_cost = energy_cost  # 合成所需能量

说明

  • __init__:初始化元素名称、类别(基础/化合物)和合成能量成本。

2.2 反应类:Reaction

Reaction 类定义合成反应规则。

# game.py (续)
class Reaction:def __init__(self, reactants, product):"""初始化反应"""self.reactants = frozenset(reactants)  # 输入元素(不可变集合)self.product = product  # 输出元素

说明

  • __init__:定义反应的输入元素和产物,使用 frozenset 确保组合顺序无关。

2.3 实验室类:Lab

Lab 类管理实验室状态和合成操作。

# game.py (续)
class Lab:def __init__(self):"""初始化实验室"""self.level = 1  # 实验室等级self.energy = 100  # 初始能量self.inventory = {"Hydrogen": 10, "Oxygen": 10, "Carbon": 5}  # 初始库存self.reactions = self.create_reactions()self.unlocked_reactions = {frozenset(["Hydrogen", "Oxygen"]): "Water",frozenset(["Carbon", "Oxygen"]): "CarbonDioxide"}  # 已解锁反应def create_reactions(self):"""创建所有反应规则"""return [Reaction(["Hydrogen", "Oxygen"], "Water"),Reaction(["Carbon", "Oxygen"], "CarbonDioxide"),Reaction(["Water", "Carbon"], "Methane"),Reaction(["Water", "CarbonDioxide"], "Glucose")]def synthesize(self, elements):"""尝试合成元素"""key = frozenset(elements)if key not in self.unlocked_reactions:print("未知反应或未解锁!")return Falseproduct = self.unlocked_reactions[key]element_obj = next(e for e in self.create_elements() if e.name == product)if self.energy >= element_obj.energy_cost:for element in elements:if self.inventory.get(element, 0) <= 0:print(f"缺少 {element}!")return Falsefor element in elements:self.inventory[element] -= 1self.inventory[product] = self.inventory.get(product, 0) + 1self.energy -= element_obj.energy_costprint(f"合成成功:{elements} → {product}")return Trueprint("能量不足!")return Falsedef upgrade(self):"""升级实验室"""cost = self.level * 50if self.energy >= cost:self.energy -= costself.level += 1self.unlock_reactions()print(f"实验室升级到等级 {self.level},花费 {cost} 能量。")else:print("能量不足,无法升级!")def unlock_reactions(self):"""解锁新反应"""available_reactions = [r for r in self.reactions if r.reactants not in self.unlocked_reactions]if self.level >= 2 and frozenset(["Water", "Carbon"]) not in self.unlocked_reactions:self.unlocked_reactions[frozenset(["Water", "Carbon"])] = "Methane"print("解锁反应:Water + Carbon → Methane")if self.level >= 3 and frozenset(["Water", "CarbonDioxide"]) not in self.unlocked_reactions:self.unlocked_reactions[frozenset(["Water", "CarbonDioxide"])] = "Glucose"print("解锁反应:Water + CarbonDioxide → Glucose")@staticmethoddef create_elements():"""创建所有元素"""return [Element("Hydrogen", "Basic", 10),Element("Oxygen", "Basic", 10),Element("Carbon", "Basic", 15),Element("Water", "Compound", 20),Element("CarbonDioxide", "Compound", 25),Element("Methane", "Compound", 30),Element("Glucose", "Compound", 40)]

说明

  • __init__:初始化实验室等级、能量、库存和已解锁反应。
  • create_reactions:定义所有反应规则。
  • synthesize:验证元素组合,消耗库存和能量,生成产物。
  • upgrade:消耗能量提升实验室等级,解锁新反应。
  • unlock_reactions:根据等级解锁高级反应。
  • create_elements:定义元素及其属性。

2.4 任务类:Task

Task 类定义实验任务。

# game.py (续)
class Task:def __init__(self, id, target_element, reward_energy, reward_reputation):"""初始化任务"""self.id = idself.target_element = target_elementself.reward_energy = reward_energyself.reward_reputation = reward_reputation

说明

  • __init__:初始化任务 ID、目标元素和奖励。

2.5 游戏类:Game

Game 类管理游戏状态和逻辑。

# game.py (续)
import random
import time
import jsonclass Game:def __init__(self):"""初始化游戏"""self.lab = Lab()self.tasks = []self.reputation = 50  # 初始声誉self.turn = 0self.max_turns = 30self.game_over = Falsedef run(self):"""游戏主循环"""print("欢迎来到《元素大师》!目标:在 30 天内完成所有任务并解锁所有反应。")while not self.game_over:self.display_state()self.generate_tasks()action = self.get_action()if action == "synthesize":self.synthesize_elements()elif action == "upgrade_lab":self.lab.upgrade()elif action == "complete_task":self.complete_task()elif action == "save_game":self.save_game()elif action == "load_game":self.load_game()elif action == "end_turn":self.end_turn()if self.check_win():print("恭喜!你完成了所有任务并解锁所有反应!")self.game_over = Trueif self.check_lose():print("游戏结束。未能在 30 天内达成目标,或声誉过低。")self.game_over = Truetime.sleep(1)def display_state(self):"""显示游戏状态"""print(f"\n天数 {self.turn + 1}")print(f"实验室等级: {self.lab.level}")print(f"能量: {self.lab.energy}")print(f"声誉: {self.reputation}")print("库存:", {k: v for k, v in self.lab.inventory.items() if v > 0})print("任务:", [f"ID {t.id}: 合成 {t.target_element}, 奖励 {t.reward_energy} 能量, {t.reward_reputation} 声誉" for t in self.tasks])print("已解锁反应:", [f"{list(k)} → {v}" for k, v in self.lab.unlocked_reactions.items()])def get_action(self):"""获取玩家行动"""print("\n你想做什么?")print("1. 合成元素")print("2. 升级实验室")print("3. 完成任务")print("4. 保存游戏")print("5. 加载游戏")print("6. 结束天数")choice = input("输入选项 (1-6): ")actions = {"1": "synthesize","2": "upgrade_lab","3": "complete_task","4": "save_game","5": "load_game","6": "end_turn"}return actions.get(choice, self.get_action())def synthesize_elements(self):"""合成元素"""print("可用元素:", self.lab.inventory)elements = input("输入要合成的元素(用空格分隔): ").split()if self.lab.synthesize(elements):self.random_event()def generate_tasks(self):"""生成随机任务"""if random.random() < 0.7:  # 70% 几率生成任务task_id = len(self.tasks) + 1available_elements = [e.name for e in self.lab.create_elements() if e.name in self.lab.unlocked_reactions.values()]if available_elements:target = random.choice(available_elements)reward_energy = random.randint(20, 50)reward_reputation = random.randint(5, 15)self.tasks.append(Task(task_id, target, reward_energy, reward_reputation))print(f"新任务 ID {task_id}: 合成 {target}, 奖励 {reward_energy} 能量, {reward_reputation} 声誉")def complete_task(self):"""完成任务"""if not self.tasks:print("没有可用任务!")returnprint("可用任务:")for task in self.tasks:print(f"ID {task.id}: 合成 {task.target_element}, 奖励 {task.reward_energy} 能量, {task.reward_reputation} 声誉")try:task_id = int(input("输入任务 ID: "))task = next((t for t in self.tasks if t.id == task_id), None)if not task:print("无效任务 ID!")returnif self.lab.inventory.get(task.target_element, 0) > 0:self.lab.inventory[task.target_element] -= 1self.lab.energy += task.reward_energyself.reputation += task.reward_reputationself.tasks.remove(task)print(f"任务 ID {task_id} 完成!获得 {task.reward_energy} 能量, {task.reward_reputation} 声誉")else:print(f"库存中缺少 {task.target_element}!")except ValueError:print("输入错误,请重试。")def random_event(self):"""随机事件"""event = random.choice(["None", "ExperimentFailure", "EquipmentFailure"])if event == "ExperimentFailure":cost = random.randint(5, 15)self.lab.energy -= costprint(f"实验失败,损失 {cost} 能量!")elif event == "EquipmentFailure":cost = self.lab.level * 20if self.lab.energy >= cost:self.lab.energy -= costprint(f"设备故障,维修费用 {cost} 能量。")else:print("设备故障未修,声誉下降!")self.reputation -= 5def save_game(self):"""保存游戏状态"""state = {"turn": self.turn,"reputation": self.reputation,"lab": {"level": self.lab.level,"energy": self.lab.energy,"inventory": self.lab.inventory,"unlocked_reactions": {str(list(k)): v for k, v in self.lab.unlocked_reactions.items()}},"tasks": [{"id": t.id, "target_element": t.target_element, "reward_energy": t.reward_energy, "reward_reputation": t.reward_reputation} for t in self.tasks]}with open("savegame.json", "w") as f:json.dump(state, f)print("游戏已保存!")def load_game(self):"""加载游戏状态"""try:with open("savegame.json", "r") as f:state = json.load(f)self.turn = state["turn"]self.reputation = state["reputation"]self.lab.level = state["lab"]["level"]self.lab.energy = state["lab"]["energy"]self.lab.inventory = state["lab"]["inventory"]self.lab.unlocked_reactions = {frozenset(eval(k)): v for k, v in state["lab"]["unlocked_reactions"].items()}self.tasks = [Task(t["id"], t["target_element"], t["reward_energy"], t["reward_reputation"]) for t in state["tasks"]]print("游戏已加载!")except FileNotFoundError:print("没有找到存档文件!")def end_turn(self):"""结束当前天数"""self.turn += 1self.lab.energy += 10  # 每日恢复能量for task in self.tasks[:]:if random.random() < 0.2:  # 20% 几率任务过期print(f"任务 ID {task.id} 过期,声誉下降!")self.reputation -= 5self.tasks.remove(task)self.random_event()def check_win(self):"""检查胜利条件"""return len(self.lab.unlocked_reactions) >= 4 and not self.tasksdef check_lose(self):"""检查失败条件"""return self.turn > self.max_turns or self.reputation < 0

说明

  • __init__:初始化实验室、任务、声誉和回合数。
  • run:游戏主循环,显示状态、生成任务、处理行动。
  • display_state:显示实验室等级、能量、库存、任务和反应。
  • get_action:提供交互菜单,返回玩家选择。
  • synthesize_elements:输入元素组合,调用实验室合成。
  • generate_tasks:随机生成任务,要求合成特定元素。
  • complete_task:检查库存,完成任务并获得奖励。
  • random_event:处理实验失败或设备故障。
  • save_game 和 load_game:保存和加载游戏状态。
  • end_turn:推进天数,恢复能量,处理任务过期。
  • check_win 和 check_lose:检查是否解锁所有反应和任务完成,或失败。

2.6 主程序:main.py

启动游戏的入口文件。

# main.py
from game import Gameif __name__ == "__main__":game = Game()game.run()

运行游戏

1. 启动游戏

在项目目录下运行:

python main.py

2. 游戏流程

  1. 初始化
  • 玩家从实验室等级 1、100 能量、50 声誉开始,库存包含 Hydrogen、Oxygen 和 Carbon。
  1. 每回合行动
  • 显示状态:查看实验室等级、能量、库存、任务和反应。
  • 合成元素:选择元素组合,尝试生成新产物。
  • 升级实验室:消耗能量提升等级,解锁新反应。
  • 完成任务:提交目标元素,获得能量和声誉。
  • 保存/加载:保存进度或恢复游戏。
  • 结束天数:恢复能量,处理随机事件和任务过期。
  1. 游戏结束
  • 解锁所有反应并完成任务胜利,超过 30 天或声誉为负失败。

3. 示例运行

欢迎来到《元素大师》!目标:在 30 天内完成所有任务并解锁所有反应。天数 1
实验室等级: 1
能量: 100
声誉: 50
库存: {'Hydrogen': 10, 'Oxygen': 10, 'Carbon': 5}
任务: []
已解锁反应: [['Hydrogen', 'Oxygen'] → Water, ['Carbon', 'Oxygen'] → CarbonDioxide]
新任务 ID 1: 合成 Water, 奖励 30 能量, 10 声誉你想做什么?
1. 合成元素
2. 升级实验室
3. 完成任务
4. 保存游戏
5. 加载游戏
6. 结束天数
输入选项 (1-6): 1可用元素: {'Hydrogen': 10, 'Oxygen': 10, 'Carbon': 5}
输入要合成的元素(用空格分隔): Hydrogen Oxygen
合成成功:['Hydrogen', 'Oxygen'] → Water天数 1
实验室等级: 1
能量: 90
声誉: 50
库存: {'Hydrogen': 9, 'Oxygen': 9, 'Carbon': 5, 'Water': 1}
任务: ['ID 1: 合成 Water, 奖励 30 能量, 10 声誉']
已解锁反应: [['Hydrogen', 'Oxygen'] → Water, ['Carbon', 'Oxygen'] → CarbonDioxide]你想做什么?
1. 合成元素
2. 升级实验室
3. 完成任务
4. 保存游戏
5. 加载游戏
6. 结束天数
输入选项 (1-6): 3可用任务:
ID 1: 合成 Water, 奖励 30 能量, 10 声誉
输入任务 ID: 1
任务 ID 1 完成!获得 30 能量, 10 声誉天数 1
实验室等级: 1
能量: 120
声誉: 60
库存: {'Hydrogen': 9, 'Oxygen': 9, 'Carbon': 5}
任务: []
已解锁反应: [['Hydrogen', 'Oxygen'] → Water, ['Carbon', 'Oxygen'] → CarbonDioxide]你想做什么?
1. 合成元素
2. 升级实验室
3. 完成任务
4. 保存游戏
5. 加载游戏
6. 结束天数
输入选项 (1-6): 2实验室升级到等级 2,花费 50 能量。
解锁反应:Water + Carbon → Methane天数 1
实验室等级: 2
能量: 70
声誉: 60
库存: {'Hydrogen': 9, 'Oxygen': 9, 'Carbon': 5}
任务: []
已解锁反应: [['Hydrogen', 'Oxygen'] → Water, ['Carbon', 'Oxygen'] → CarbonDioxide, ['Water', 'Carbon'] → Methane]你想做什么?
1. 合成元素
2. 升级实验室
3. 完成任务
4. 保存游戏
5. 加载游戏
6. 结束天数
输入选项 (1-6): 6天数结束,恢复 10 能量。
天数 2
实验室等级: 2
能量: 80
声誉: 60
库存: {'Hydrogen': 9, 'Oxygen': 9, 'Carbon': 5}
任务: []
已解锁反应: [['Hydrogen', 'Oxygen'] → Water, ['Carbon', 'Oxygen'] → CarbonDioxide, ['Water', 'Carbon'] → Methane]
新任务 ID 2: 合成 Methane, 奖励 40 能量, 12 声誉你想做什么?
1. 合成元素
2. 升级实验室
3. 完成任务
4. 保存游戏
5. 加载游戏
6. 结束天数
输入选项 (1-6): 1可用元素: {'Hydrogen': 9, 'Oxygen': 9, 'Carbon': 5}
输入要合成的元素(用空格分隔): Water Carbon
合成成功:['Water', 'Carbon'] → Methane
实验失败,损失 10 能量!天数 2
实验室等级: 2
能量: 60
声誉: 60
库存: {'Hydrogen': 9, 'Oxygen': 9, 'Carbon': 4, 'Methane': 1}
任务: ['ID 2: 合成 Methane, 奖励 40 能量, 12 声誉']
已解锁反应: [['Hydrogen', 'Oxygen'] → Water, ['Carbon', 'Oxygen'] → CarbonDioxide, ['Water', 'Carbon'] → Methane]你想做什么?
1. 合成元素
2. 升级实验室
3. 完成任务
4. 保存游戏
5. 加载游戏
6. 结束天数
输入选项 (1-6): 3可用任务:
ID 2: 合成 Methane, 奖励 40 能量, 12 声誉
输入任务 ID: 2
任务 ID 2 完成!获得 40 能量, 12 声誉天数 2
实验室等级: 2
能量: 100
声誉: 72
库存: {'Hydrogen': 9, 'Oxygen': 9, 'Carbon': 4}
任务: []
已解锁反应: [['Hydrogen', 'Oxygen'] → Water, ['Carbon', 'Oxygen'] → CarbonDioxide, ['Water', 'Carbon'] → Methane]

分析

  • 第一天合成 Water,消耗 Hydrogen 和 Oxygen,完成任务 1。
  • 升级实验室到等级 2,解锁 Methane 反应。
  • 第二天合成 Methane,完成任务 2,尽管触发实验失败事件。
  • 声誉提升到 72,能量恢复到 100,继续游戏。

游戏机制详解

1. 元素合成

  • 基础元素:Hydrogen、Oxygen、Carbon,初始库存丰富。
  • 反应规则
  • Hydrogen + Oxygen → Water
  • Carbon + Oxygen → CarbonDioxide
  • Water + Carbon → Methane(需等级 2)
  • Water + CarbonDioxide → Glucose(需等级 3)
  • 消耗:每种元素消耗 1 单位,合成需要能量(10-40)。

2. 任务管理

  • 生成:70% 几率生成任务,要求合成已解锁的化合物。
  • 奖励:完成任务获得 20-50 能量和 5-15 声誉。
  • 过期:20% 几率任务过期,声誉 -5。

3. 实验室管理

  • 等级:初始 1 级,升级解锁新反应(等级 2:Methane,等级 3:Glucose)。
  • 能量:合成、升级和维修消耗能量,每日恢复 10。
  • 库存:管理基础元素和化合物,完成任务消耗产物。

4. 随机事件

  • 实验失败:损失 5-15 能量。
  • 设备故障:维修消耗等级 × 20 能量,未修声誉 -5。

5. 胜利与失败

  • 胜利:解锁所有 4 种反应并完成所有任务。
  • 失败:超过 30 天或声誉低于 0。

游戏扩展与优化

当前版本是一个功能完整的化学合成游戏原型,我们可以通过以下方式增强游戏性、技术实现和教育价值。

1. 游戏性增强

  • 新反应:增加更复杂的化学反应,如有机合成。
  • 元素属性:引入摩尔质量、化学性质影响合成。
  • 任务类型:添加多步合成任务或限时任务。
  • 库存补充:允许购买或采集基础元素。

示例代码:多步任务

class Task:def __init__(self, id, target_element, reward_energy, reward_reputation, steps=1):self.id = idself.target_element = target_elementself.reward_energy = reward_energyself.reward_reputation = reward_reputationself.steps = steps  # 合成步骤数class Game:# ... 其他方法保持不变 ...def generate_tasks(self):if random.random() < 0.7:task_id = len(self.tasks) + 1available_elements = [e.name for e in self.lab.create_elements() if e.name in self.lab.unlocked_reactions.values()]if available_elements:target = random.choice(available_elements)reward_energy = random.randint(20, 50)reward_reputation = random.randint(5, 15)steps = 2 if target == "Glucose" else 1self.tasks.append(Task(task_id, target, reward_energy, reward_reputation, steps))print(f"新任务 ID {task_id}: 合成 {target} ({steps} 步), 奖励 {reward_energy} 能量, {reward_reputation} 声誉")def complete_task(self):if not self.tasks:print("没有可用任务!")returnprint("可用任务:")for task in self.tasks:print(f"ID {task.id}: 合成 {task.target_element} ({task.steps} 步), 奖励 {task.reward_energy} 能量, {task.reward_reputation} 声誉")try:task_id = int(input("输入任务 ID: "))task = next((t for t in self.tasks if t.id == task_id), None)if not task:print("无效任务 ID!")returnrequired = task.stepsif self.lab.inventory.get(task.target_element, 0) >= required:self.lab.inventory[task.target_element] -= requiredself.lab.energy += task.reward_energyself.reputation += task.reward_reputationself.tasks.remove(task)print(f"任务 ID {task_id} 完成!获得 {task.reward_energy} 能量, {task.reward_reputation} 声誉")else:print(f"库存中缺少 {task.target_element} 或数量不足(需 {required} 单位)!")except ValueError:print("输入错误,请重试。")

实现效果

  • Glucose 任务要求 2 单位产物,增加挑战性。
  • 奖励和难度匹配,鼓励多步合成。

2. 技术优化

  • 图形界面:使用 Pygame 显示实验室、元素和反应动画。
  • 存档加密:防止玩家修改存档文件。
  • 反应可视化:展示化学反应的分子结构。

示例代码:Pygame 界面

import pygameclass GameWithGUI(Game):def __init__(self):super().__init__()pygame.init()self.screen = pygame.display.set_mode((800, 600))pygame.display.set_caption("元素大师")self.font = pygame.font.Font(None, 36)self.element_positions = {"Hydrogen": (100, 100), "Oxygen": (200, 100), "Carbon": (300, 100),"Water": (100, 200), "CarbonDioxide": (200, 200), "Methane": (300, 200),"Glucose": (200, 300)}def display_state(self):"""使用 Pygame 显示状态"""self.screen.fill((255, 255, 255))# 绘制元素库存for element, count in self.lab.inventory.items():if count > 0:pos = self.element_positions.get(element, (400, 100))pygame.draw.circle(self.screen, (0, 0, 255), pos, 20)text = self.font.render(f"{element}: {count}", True, (0, 0, 0))self.screen.blit(text, (pos[0] - 30, pos[1] + 30))# 显示状态texts = [f"天数: {self.turn + 1}",f"实验室等级: {self.lab.level}",f"能量: {self.lab.energy}",f"声誉: {self.reputation}",f"任务: {len(self.tasks)} 个"]for i, text in enumerate(texts):rendered = self.font.render(text, True, (0, 0, 0))self.screen.blit(rendered, (10, 400 + i * 30))pygame.display.flip()super().display_state()def run(self):print("欢迎来到《元素大师》!")running = Truewhile running and not self.game_over:self.display_state()for event in pygame.event.get():if event.type == pygame.QUIT:running = Falseaction = self.get_action()if action == "synthesize":self.synthesize_elements()elif action == "upgrade_lab":self.lab.upgrade()elif action == "complete_task":self.complete_task()elif action == "save_game":self.save_game()elif action == "load_game":self.load_game()elif action == "end_turn":self.end_turn()if self.check_win():print("恭喜!你完成了所有任务并解锁所有反应!")self.game_over = Trueif self.check_lose():print("游戏结束。未能在 30 天内达成目标,或声誉过低。")self.game_over = Truetime.sleep(1)pygame.quit()

实现效果

  • 显示元素库存(圆点表示元素,旁边标注数量)。
  • CLI 交互保留,状态在屏幕底部显示。

3. 教育模块

  • 反应原理:显示化学方程式,如 2H₂ + O₂ → 2H₂O。
  • 元素知识:介绍元素性质,如原子序数、周期表位置。
  • 历史背景:讲述化学发现的故事。

示例代码:反应原理

class Lab:# ... 其他方法保持不变 ...def synthesize(self, elements):key = frozenset(elements)if key not in self.unlocked_reactions:print("未知反应或未解锁!")return Falseproduct = self.unlocked_reactions[key]element_obj = next(e for e in self.create_elements() if e.name == product)if self.energy >= element_obj.energy_cost:for element in elements:if self.inventory.get(element, 0) <= 0:print(f"缺少 {element}!")return Falsefor element in elements:self.inventory[element] -= 1self.inventory[product] = self.inventory.get(product, 0) + 1self.energy -= element_obj.energy_costequation = {frozenset(["Hydrogen", "Oxygen"]): "2H₂ + O₂ → 2H₂O",frozenset(["Carbon", "Oxygen"]): "C + O₂ → CO₂",frozenset(["Water", "Carbon"]): "CH₄ (Methane) formed via complex reaction",frozenset(["Water", "CarbonDioxide"]): "6CO₂ + 6H₂O → C₆H₁₂O₆ (Photosynthesis)"}.get(key, "未知反应")print(f"合成成功:{elements} → {product} ({equation})")return Trueprint("能量不足!")return False

实现效果

  • 每次合成显示化学方程式,增强教育性。

游戏策略与玩法分析

1. 玩家策略

  • 资源管理:优先合成高价值化合物,保留基础元素。
  • 任务优先级:选择高奖励任务,避免过期。
  • 实验室升级:尽早升级以解锁高级反应。
  • 能量规划:平衡合成和升级的能量消耗。

2. 平衡性

  • 初始资源:100 能量和基础元素,适合初期合成。
  • 任务难度:简单任务(Water)到复杂任务(Glucose)。
  • 随机事件:实验失败和设备故障增加挑战。
  • 回合限制:30 天需高效规划。

3. 重玩价值

  • 尝试不同合成顺序和任务优先级。
  • 应对随机事件,优化资源管理。
  • 解锁所有反应,探索化学知识。

总结与未来展望

通过这篇博文,您已经成功构建了一个化学元素合成模拟游戏 元素大师!这个项目展示了如何使用 Python 创建一个科学类游戏,涵盖化学模拟、资源管理和教育内容。以下是回顾和未来方向:

1. 收获

  • 掌握了 Python OOP 和数据管理。
  • 实现了化学反应模拟和任务系统。
  • 体验了科学与策略的结合。

2. 未来扩展

  • 图形化:完善 Pygame 界面,显示分子动画。
  • 新反应:增加有机化学或核反应。
  • 多人模式:支持合作合成或竞赛。
  • 教育增强:融入更多化学知识和历史。

3. 动手实践

快去运行代码,探索化学世界吧!您可以尝试:

  • 合成复杂化合物,完成高级任务。
  • 优化能量和库存管理。
  • 实现图形界面,提升用户体验。

希望这篇教程为您打开了化学合成游戏开发的大门!如果您有疑问或建议,请留言,我将进一步完善内容。祝您编程愉快,享受元素大师的科学之美!


附录:完整代码

以下是整合后的完整代码,分为 game.pymain.py,可直接运行。

game.py

import random
import time
import jsonclass Element:def __init__(self, name, category, energy_cost):self.name = nameself.category = categoryself.energy_cost = energy_costclass Reaction:def __init__(self, reactants, product):self.reactants = frozenset(reactants)self.product = productclass Task:def __init__(self, id, target_element, reward_energy, reward_reputation, steps=1):self.id = idself.target_element = target_elementself.reward_energy = reward_energyself.reward_reputation = reward_reputationself.steps = stepsclass Lab:def __init__(self):self.level = 1self.energy = 100self.inventory = {"Hydrogen": 10, "Oxygen": 10, "Carbon": 5}self.reactions = self.create_reactions()self.unlocked_reactions = {frozenset(["Hydrogen", "Oxygen"]): "Water",frozenset(["Carbon", "Oxygen"]): "CarbonDioxide"}def create_reactions(self):return [Reaction(["Hydrogen", "Oxygen"], "Water"),Reaction(["Carbon", "Oxygen"], "CarbonDioxide"),Reaction(["Water", "Carbon"], "Methane"),Reaction(["Water", "CarbonDioxide"], "Glucose")]def create_elements(self):return [Element("Hydrogen", "Basic", 10),Element("Oxygen", "Basic", 10),Element("Carbon", "Basic", 15),Element("Water", "Compound", 20),Element("CarbonDioxide", "Compound", 25),Element("Methane", "Compound", 30),Element("Glucose", "Compound", 40)]def synthesize(self, elements):key = frozenset(elements)if key not in self.unlocked_reactions:print("未知反应或未解锁!")return Falseproduct = self.unlocked_reactions[key]element_obj = next(e for e in self.create_elements() if e.name == product)if self.energy >= element_obj.energy_cost:for element in elements:if self.inventory.get(element, 0) <= 0:print(f"缺少 {element}!")return Falsefor element in elements:self.inventory[element] -= 1self.inventory[product] = self.inventory.get(product, 0) + 1self.energy -= element_obj.energy_costequation = {frozenset(["Hydrogen", "Oxygen"]): "2H₂ + O₂ → 2H₂O",frozenset(["Carbon", "Oxygen"]): "C + O₂ → CO₂",frozenset(["Water", "Carbon"]): "CH₄ (Methane) formed via complex reaction",frozenset(["Water", "CarbonDioxide"]): "6CO₂ + 6H₂O → C₆H₁₂O₆ (Photosynthesis)"}.get(key, "未知反应")print(f"合成成功:{elements} → {product} ({equation})")return Trueprint("能量不足!")return Falsedef upgrade(self):cost = self.level * 50if self.energy >= cost:self.energy -= costself.level += 1self.unlock_reactions()print(f"实验室升级到等级 {self.level},花费 {cost} 能量。")else:print("能量不足,无法升级!")def unlock_reactions(self):available_reactions = [r for r in self.reactions if r.reactants not in self.unlocked_reactions]if self.level >= 2 and frozenset(["Water", "Carbon"]) not in self.unlocked_reactions:self.unlocked_reactions[frozenset(["Water", "Carbon"])] = "Methane"print("解锁反应:Water + Carbon → Methane")if self.level >= 3 and frozenset(["Water", "CarbonDioxide"]) not in self.unlocked_reactions:self.unlocked_reactions[frozenset(["Water", "CarbonDioxide"])] = "Glucose"print("解锁反应:Water + CarbonDioxide → Glucose")class Game:def __init__(self):self.lab = Lab()self.tasks = []self.reputation = 50self.turn = 0self.max_turns = 30self.game_over = Falsedef run(self):print("欢迎来到《元素大师》!目标:在 30 天内完成所有任务并解锁所有反应。")while not self.game_over:self.display_state()self.generate_tasks()action = self.get_action()if action == "synthesize":self.synthesize_elements()elif action == "upgrade_lab":self.lab.upgrade()elif action == "complete_task":self.complete_task()elif action == "save_game":self.save_game()elif action == "load_game":self.load_game()elif action == "end_turn":self.end_turn()if self.check_win():print("恭喜!你完成了所有任务并解锁所有反应!")self.game_over = Trueif self.check_lose():print("游戏结束。未能在 30 天内达成目标,或声誉过低。")self.game_over = Truetime.sleep(1)def display_state(self):print(f"\n天数 {self.turn + 1}")print(f"实验室等级: {self.lab.level}")print(f"能量: {self.lab.energy}")print(f"声誉: {self.reputation}")print("库存:", {k: v for k, v in self.lab.inventory.items() if v > 0})print("任务:", [f"ID {t.id}: 合成 {t.target_element} ({t.steps} 步), 奖励 {t.reward_energy} 能量, {t.reward_reputation} 声誉" for t in self.tasks])print("已解锁反应:", [f"{list(k)} → {v}" for k, v in self.lab.unlocked_reactions.items()])def get_action(self):print("\n你想做什么?")print("1. 合成元素")print("2. 升级实验室")print("3. 完成任务")print("4. 保存游戏")print("5. 加载游戏")print("6. 结束天数")choice = input("输入选项 (1-6): ")actions = {"1": "synthesize","2": "upgrade_lab","3": "complete_task","4": "save_game","5": "load_game","6": "end_turn"}return actions.get(choice, self.get_action())def synthesize_elements(self):print("可用元素:", self.lab.inventory)elements = input("输入要合成的元素(用空格分隔): ").split()if self.lab.synthesize(elements):self.random_event()def generate_tasks(self):if random.random() < 0.7:task_id = len(self.tasks) + 1available_elements = [e.name for e in self.lab.create_elements() if e.name in self.lab.unlocked_reactions.values()]if available_elements:target = random.choice(available_elements)reward_energy = random.randint(20, 50)reward_reputation = random.randint(5, 15)steps = 2 if target == "Glucose" else 1self.tasks.append(Task(task_id, target, reward_energy, reward_reputation, steps))print(f"新任务 ID {task_id}: 合成 {target} ({steps} 步), 奖励 {reward_energy} 能量, {reward_reputation} 声誉")def complete_task(self):if not self.tasks:print("没有可用任务!")returnprint("可用任务:")for task in self.tasks:print(f"ID {task.id}: 合成 {task.target_element} ({task.steps} 步), 奖励 {task.reward_energy} 能量, {task.reward_reputation} 声誉")try:task_id = int(input("输入任务 ID: "))task = next((t for t in self.tasks if t.id == task_id), None)if not task:print("无效任务 ID!")returnrequired = task.stepsif self.lab.inventory.get(task.target_element, 0) >= required:self.lab.inventory[task.target_element] -= requiredself.lab.energy += task.reward_energyself.reputation += task.reward_reputationself.tasks.remove(task)print(f"任务 ID {task_id} 完成!获得 {task.reward_energy} 能量, {task.reward_reputation} 声誉")else:print(f"库存中缺少 {task.target_element} 或数量不足(需 {required} 单位)!")except ValueError:print("输入错误,请重试。")def random_event(self):event = random.choice(["None", "ExperimentFailure", "EquipmentFailure"])if event == "ExperimentFailure":cost = random.randint(5, 15)self.lab.energy -= costprint(f"实验失败,损失 {cost} 能量!")elif event == "EquipmentFailure":cost = self.lab.level * 20if self.lab.energy >= cost:self.lab.energy -= costprint(f"设备故障,维修费用 {cost} 能量。")else:print("设备故障未修,声誉下降!")self.reputation -= 5def save_game(self):state = {"turn": self.turn,"reputation": self.reputation,"lab": {"level": self.lab.level,"energy": self.lab.energy,"inventory": self.lab.inventory,"unlocked_reactions": {str(list(k)): v for k, v in self.lab.unlocked_reactions.items()}},"tasks": [{"id": t.id, "target_element": t.target_element, "reward_energy": t.reward_energy, "reward_reputation": t.reward_reputation, "steps": t.steps} for t in self.tasks]}with open("savegame.json", "w") as f:json.dump(state, f)print("游戏已保存!")def load_game(self):try:with open("savegame.json", "r") as f:state = json.load(f)self.turn = state["turn"]self.reputation = state["reputation"]self.lab.level = state["lab"]["level"]self.lab.energy = state["lab"]["energy"]self.lab.inventory = state["lab"]["inventory"]self.lab.unlocked_reactions = {frozenset(eval(k)): v for k, v in state["lab"]["unlocked_reactions"].items()}self.tasks = [Task(t["id"], t["target_element"], t["reward_energy"], t["reward_reputation"], t["steps"]) for t in state["tasks"]]print("游戏已加载!")except FileNotFoundError:print("没有找到存档文件!")def end_turn(self):self.turn += 1self.lab.energy += 10for task in self.tasks[:]:if random.random() < 0.2:print(f"任务 ID {task.id} 过期,声誉下降!")self.reputation -= 5self.tasks.remove(task)self.random_event()def check_win(self):return len(self.lab.unlocked_reactions) >= 4 and not self.tasksdef check_lose(self):return self.turn > self.max_turns or self.reputation < 0

main.py

from game import Gameif __name__ == "__main__":game = Game()game.run()