以下是使用C++20协程实现武侠内力运行周天的具体实现方案,包含完整代码和详细解释:
完整协程实现代码
#include <coroutine>
#include <iostream>
#include <optional>
// 协程生成器模板
template<typename T>
class Generator {
public:
struct promise_type {
T value;
std::suspend_always initial_suspend() { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
Generator get_return_object() { return Generator{Handle::from_promise(*this)}; }
void return_void() {}
void unhandled_exception() { std::terminate(); }
std::suspend_always yield_value(T val) {
value = val;
return {};
}
};
using Handle = std::coroutine_handle<promise_type>;
explicit Generator(Handle coro) : coro_(coro) {}
~Generator() { if (coro_) coro_.destroy(); }
Generator(Generator&& other) noexcept : coro_(other.coro_) {
other.coro_ = nullptr; // 置空原对象句柄
}
Generator& operator=(Generator&& other) noexcept {
if (this != &other) {
if (coro_) coro_.destroy();
coro_ = other.coro_;
other.coro_ = nullptr; // 置空源句柄
}
return *this;
}
T next() {
if (!coro_ || coro_.done()) return T{};
coro_.resume();
return coro_.promise().value;
}
private:
Handle coro_;
};
// 内力运行周天协程
Generator<int> yun_neili(int base_neili, int cycles) {
int total = base_neili;
for(int i = 1; i <= cycles; ++i) {
// 模拟每个周天的运行过程
total += 10;
// 每三个周天会有额外突破
if (i % 3 == 0) {
total += 15;
std::cout << "【奇经八脉贯通】";
}
// 产生当前内力总值
co_yield total;
// 模拟可能的中断点
if (i % 5 == 0) {
std::cout << "\n(运功暂停,可进行其他操作)\n";
co_await std::suspend_always{};
}
}
}
// 武侠角色类
class WulinRole {
public:
explicit WulinRole(std::string name) : name_(std::move(name)) {}
void start_yun_neili(int cycles = 9) {
neili_process_ = yun_neili(neili_, cycles);
}
void continue_neili() {
if (neili_process_) {
neili_ = neili_process_->next();
std::cout << name_ << "当前内力:" << neili_ << std::endl;
}
}
int get_neili() const { return neili_; }
private:
std::string name_;
int neili_ = 100;
std::optional<Generator<int>> neili_process_;
};
int main() {
WulinRole xiao_longnv("小龙女");
// 开始运行九周天
xiao_longnv.start_yun_neili(9);
// 分步执行内力运行
for (int i = 0; i < 10; ++i) {
xiao_longnv.continue_neili();
// 模拟中途事件(例如第4步时发生战斗)
if (i == 3) {
std::cout << "\n⚠️ 遭遇敌人,中断运功进行战斗!\n";
// 此处可以暂停协程处理其他逻辑
}
}
std::cout << "最终内力值:" << xiao_longnv.get_neili() << std::endl;
return 0;
}
运行示例输出
小龙女当前内力:110
小龙女当前内力:120
【奇经八脉贯通】小龙女当前内力:145
小龙女当前内力:155
⚠️ 遭遇敌人,中断运功进行战斗!
小龙女当前内力:165
(运功暂停,可进行其他操作)
小龙女当前内力:165
【奇经八脉贯通】小龙女当前内力:190
小龙女当前内力:200
小龙女当前内力:210
【奇经八脉贯通】小龙女当前内力:235
最终内力值:235
关键实现解析
-
协程生成器模板:
- 使用
promise_type
定义协程控制流 yield_value
实现内力值的暂停返回- RAII管理协程句柄生命周期
- 使用
-
内力运行逻辑:
Generator<int> yun_neili(int base_neili, int cycles) { int total = base_neili; for(int i = 1; i <= cycles; ++i) { total += 10; // 基础增长 if (i % 3 == 0) total += 15; // 周天突破 co_yield total; // 暂停并返回当前值 if (i % 5 == 0) co_await std::suspend_always{}; // 主动暂停点 } }
- 每完成一个周天
yield
当前内力 - 每5个周天设置可中断点
- 每3个周天触发奇经八脉突破
- 每完成一个周天
-
角色类集成:
class WulinRole { std::optional<Generator<int>> neili_process_; //... void continue_neili() { if (neili_process_) { neili_ = neili_process_->next(); // 更新显示... } } };
- 使用
std::optional
管理协程状态 - 分步执行协程推进内力增长
- 使用
-
中断处理机制:
- 通过
co_await std::suspend_always
实现可中断点 - 在main函数中模拟战斗中断场景:
if (i == 3) { std::cout << "遭遇敌人,中断运功!"; // 此处可保存协程状态,转去处理战斗逻辑 }
- 通过
协程控制流程图
开始运功
│
↓
[周天循环]
│
├─→ 内力增长 → 周天突破判断 → 产生当前值 → 暂停(yield)
│ │
│ ↓
│ 等待继续指令/处理中断
│ │
└───────────────────────────────┘
高级应用扩展
- 走火入魔异常处理:
try {
while (neili_process_.has_value()) {
neili_ = neili_process_->next();
if (neili_ > 500) throw std::runtime_error("走火入魔!");
}
} catch (const std::exception& e) {
std::cout << "⚠️警告:" << e.what();
neili_process_.reset();
}
- 多功法并行运行:
class WulinRole {
std::vector<Generator<int>> active_processes_;
void update_processes() {
for (auto& process : active_processes_) {
neili_ += process.next();
}
}
};
- 与游戏主循环集成:
void game_loop() {
while (true) {
handle_input(); // 处理玩家输入
update_effects(); // 更新协程状态
render(); // 渲染画面
std::this_thread::sleep_for(33ms); // 30fps
}
}
该实现充分利用C++20协程的特性,实现了:
- 可暂停/恢复的内力修炼过程
- 多阶段突破机制
- 安全的中断处理
- 灵活的状态管理
- 与游戏主循环的自然集成
可以通过扩展Generator模板、增加异常处理、添加更多协程交互点等方式,构建更复杂的武侠内功系统。