C++ 设计模式-备忘录模式

news2025/2/22 17:34:12

游戏存档实现,包括撤销/重做、持久化存储、版本控制和内存管理

#include <iostream>
#include <memory>
#include <deque>
#include <stack>
#include <chrono>
#include <fstream>
#include <sstream>
#include <ctime>

// ================ 1. 增强版备忘录类 ================
class GameMemento {
private:
    const int level;
    const int health;
    const std::string weapon;
    const std::chrono::system_clock::time_point timestamp;

    friend class GameCharacter;

public:
    GameMemento(int lv, int hp, std::string wp, std::chrono::system_clock::time_point ts)
        : level(lv), health(hp), weapon(std::move(wp)), timestamp(ts) {}

    // 序列化为字符串
    std::string serialize() const {
        std::time_t ts = std::chrono::system_clock::to_time_t(timestamp);
        std::stringstream ss;
        ss << level << "," << health << "," << weapon << "," << ts;
        return ss.str();
    }

    // 从字符串反序列化
    static std::unique_ptr<GameMemento> deserialize(const std::string& data) {
        std::stringstream ss(data);
        int lv, hp;
        std::string wp;
        time_t ts;

        char comma;
        ss >> lv >> comma >> hp >> comma;
        std::getline(ss, wp, ',');
        ss >> ts;

        return std::make_unique<GameMemento>(
            lv, hp, wp, std::chrono::system_clock::from_time_t(ts)
        );
    }

    void print() const {
        auto ts = std::chrono::system_clock::to_time_t(timestamp);
        char buffer[26];
        strftime(buffer, sizeof(buffer), "%a %b %d %H:%M:%S %Y", std::localtime(&ts));
        std::cout << "Lv." << level << " HP:" << health
          << " Weapon:" << weapon << " (" << buffer << ")\n";
    }
};

// ================ 2. 游戏角色类 ================
class GameCharacter {
private:
    int level = 1;
    int health = 100;
    std::string weapon = "Fist";

public:
    void levelUp() { level++; health += 20; }
    void takeDamage(int dmg) { health -= dmg; }
    void equipWeapon(std::string wp) { weapon = std::move(wp); }

    std::unique_ptr<GameMemento> save() const {
        return std::make_unique<GameMemento>(
            level, health, weapon,
            std::chrono::system_clock::now()
        );
    }

    void load(const GameMemento& memento) {
        level = memento.level;
        health = memento.health;
        weapon = memento.weapon;
    }

    void status() const {
        std::cout << "Current State: Lv." << level
                  << " HP:" << health
                  << " Weapon:" << weapon << "\n";
    }
};

// ================ 3. 增强版存档管理器 ================
class SaveManager {
private:
    std::deque<std::unique_ptr<GameMemento>> undoStack;  // 使用deque方便限制数量
    std::stack<std::unique_ptr<GameMemento>> redoStack;  // 重做栈
    const size_t MAX_SAVES = 5;  // 最大存档数量

    void trimHistory() {
        while (undoStack.size() > MAX_SAVES) {
            undoStack.pop_front();  // 移除最旧的存档
        }
    }

public:
    // 保存新状态
    void saveState(const GameCharacter& character) {
        undoStack.push_back(character.save());
        redoStack = std::stack<std::unique_ptr<GameMemento>>(); // 清空重做栈
        trimHistory();
    }

    // 撤销
    bool undo(GameCharacter& character) {
        if (undoStack.size() < 2) return false;

        redoStack.push(std::move(undoStack.back()));
        undoStack.pop_back();

        character.load(*undoStack.back());
        return true;
    }

    // 重做
    bool redo(GameCharacter& character) {
        if (redoStack.empty()) return false;

        character.load(*redoStack.top());
        undoStack.push_back(std::move(redoStack.top()));
        redoStack.pop();
        return true;
    }

    // 保存到文件
    bool saveToFile(const std::string& filename) const {
        std::ofstream file(filename);
        if (!file) return false;

        for (const auto& memento : undoStack) {
            file << memento->serialize() << "\n";
        }
        return true;
    }

    // 从文件加载
    bool loadFromFile(const std::string& filename, GameCharacter& character) {
        std::ifstream file(filename);
        if (!file) return false;

        undoStack.clear();
        redoStack = std::stack<std::unique_ptr<GameMemento>>();

        std::string line;
        while (std::getline(file, line)) {
            auto memento = GameMemento::deserialize(line);
            if (memento) {
                undoStack.push_back(std::move(memento));
            }
        }

        if (!undoStack.empty()) {
            character.load(*undoStack.back());
        }
        return true;
    }

    // 显示版本历史
    void showHistory() const {
        std::cout << "\n=== Version History (" << undoStack.size() << "/"
            << MAX_SAVES << ") ===\n";
        int i = 1;
        for (const auto& memento : undoStack) {
            std::cout << "Version " << i++ << ": ";
            memento->print();
        }
    }
};

// ================ 使用示例 ================
int main() {
    GameCharacter hero;
    SaveManager saveManager;

    // 初始状态
    hero.status();
    saveManager.saveState(hero);

    // 查看历史版本
    saveManager.showHistory();

    // 进行一系列操作
    hero.levelUp();
    hero.equipWeapon("Sword");
    saveManager.saveState(hero);

    hero.takeDamage(30);
    saveManager.saveState(hero);

    hero.levelUp();
    hero.equipWeapon("Axe");
    saveManager.saveState(hero);

    // 查看历史版本
    saveManager.showHistory();

    // 持久化存储
    saveManager.saveToFile("game_save.txt");

    // 连续撤销两次
    std::cout << "=== Undo x2 ===\n";
    saveManager.undo(hero);
    saveManager.undo(hero);
    hero.status();

    // 重做一次
    std::cout << "=== Redo x1 ===\n";
    saveManager.redo(hero);
    hero.status();

    // 从文件加载
    GameCharacter loadedHero;
    SaveManager loadManager;
    loadManager.loadFromFile("game_save.txt", loadedHero);
    std::cout << "=== Loaded Character ===\n";

    loadedHero.status();
    loadManager.showHistory();

    hero.takeDamage(-30);
    saveManager.saveState(hero);
    hero.status();
    // 查看历史版本
    saveManager.showHistory();


    return 0;
}

功能实现说明:

  1. 撤销/重做系统

    • 使用双栈结构(undoStack + redoStack)
    • undo() 保留最近两个状态以实现状态对比
    • 每次保存时清空重做栈
  2. 持久化存储

    • 使用CSV格式存储:level,health,weapon,timestamp
    • 支持从文件恢复完整历史记录
  3. 版本控制

    • 每个存档包含精确到秒的时间戳
    • showHistory() 显示带时间的版本信息
  4. 内存优化

    • 限制最大存档数量(MAX_SAVES = 5)
    • 自动移除最早的存档
  5. 附加功能

    • 版本历史浏览
    • 完整的异常安全设计
    • 使用现代C++特性(chrono时间库、智能指针等)

执行结果示例:

Current State: Lv.1 HP:100 Weapon:Fist

=== Version History (1/5) ===
Version 1: Lv.1 HP:100 Weapon:Fist (Fri Feb 21 12:10:21 2025)

=== Version History (4/5) ===
Version 1: Lv.1 HP:100 Weapon:Fist (Fri Feb 21 12:10:21 2025)
Version 2: Lv.2 HP:120 Weapon:Sword (Fri Feb 21 12:10:21 2025)
Version 3: Lv.2 HP:90 Weapon:Sword (Fri Feb 21 12:10:21 2025)
Version 4: Lv.3 HP:110 Weapon:Axe (Fri Feb 21 12:10:21 2025)
=== Undo x2 ===
Current State: Lv.2 HP:120 Weapon:Sword
=== Redo x1 ===
Current State: Lv.2 HP:90 Weapon:Sword
=== Loaded Character ===
Current State: Lv.3 HP:110 Weapon:Axe

=== Version History (4/5) ===
Version 1: Lv.1 HP:100 Weapon:Fist (Fri Feb 21 12:10:21 2025)
Version 2: Lv.2 HP:120 Weapon:Sword (Fri Feb 21 12:10:21 2025)
Version 3: Lv.2 HP:90 Weapon:Sword (Fri Feb 21 12:10:21 2025)
Version 4: Lv.3 HP:110 Weapon:Axe (Fri Feb 21 12:10:21 2025)
Current State: Lv.2 HP:120 Weapon:Sword

=== Version History (4/5) ===
Version 1: Lv.1 HP:100 Weapon:Fist (Fri Feb 21 12:10:21 2025)
Version 2: Lv.2 HP:120 Weapon:Sword (Fri Feb 21 12:10:21 2025)
Version 3: Lv.2 HP:90 Weapon:Sword (Fri Feb 21 12:10:21 2025)
Version 4: Lv.2 HP:120 Weapon:Sword (Fri Feb 21 12:10:21 2025)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2303539.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

复习dddddddd

1. 思路&#xff1a;用队列先进先出的特性 #include <iostream> #include <vector> #include <stack> #include <cstdio> #include <algorithm> #include <cstring> #include <climits> #include <cstdlib> #include <cma…

大数据技术Kafka详解 ⑥ | Kafka大厂面试题

目录 1、为什么要使用kafka? 2、kafka消费过的消息如何再消费? 3、kafka的数据是放在磁盘上还是内存上&#xff0c;为什么速度会快? 4、kafka数据怎么保障不丢失? 4.1、生产者数据的不丢失 4.2、消费者数据的不丢失 4.3、kafka集群中的broker的数据不丢失 5、采集数…

Jupyter里面的manim编程学习

1.Jupyterlab的使用 因为我之前一直都是使用的vscode进行manim编程的&#xff0c;但是今天看的这个教程使用的是Jupyter&#xff0c;我也很是好奇这个manim在Jupyter这样的交互式下面会生成怎么样的效果&#xff0c;所以今天尝试了jupyter&#xff0c;并且对于两个进行比较和说…

hot100_19. 删除链表的倒数第 N 个结点

hot100_19. 删除链表的倒数第 N 个结点 思路 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5] 示例 2&#xff1a; 输入&#xff1a;head […

✨1.HTML、CSS 和 JavaScript 是什么?

✨✨ HTML、CSS 和 JavaScript 是构建网页的三大核心技术&#xff0c;它们相互协作&#xff0c;让网页呈现出丰富的内容、精美的样式和交互功能。以下为你详细介绍&#xff1a; &#x1f98b;1. HTML&#xff08;超文本标记语言&#xff09; 定义&#xff1a;HTML 是一种用于描…

机器学习的数学基础(三)——概率与信息论

目录 1. 随机变量2. 概率分布2.1 离散型变量和概率质量函数2.2 连续型变量和概率密度函数 3. 边缘概率4. 条件概率5. 条件概率的链式法则6. 独立性和条件独立性7. 期望、方差和协方差7.1 期望7.2 方差7.3 协方差 8. 常用概率分布8.1 均匀分布 U ( a , b ) U(a, b) U(a,b)8.2 Be…

flutter将utf-8编码的字节序列转换为中英文字符串

这里遇到的问题是&#xff0c;我通过某种方式拿到了utf-8编码的字节序列&#xff0c;我只知道他们对应的是中英文字符。怎么将其转成中英文&#xff0c;并打印&#xff0c;让我对utf-8编码有了些许许的了解。 这里记录一下转换代码&#xff1a; String wifiName \xE9\xA1\xB…

IM聊天系统架构实现

一、IM系统整体架构 二、企业级IM系统如何实现心跳与断线重连机制&#xff1b; 1、重连机制&#xff08;服务端下线&#xff09; 服务端下线&#xff0c;客户端netty可以感知到&#xff0c;在感知的方法中进行重连的操作&#xff0c;注意重连可能连接到旧的服务器继续报错&…

基于腾讯云大模型知识引擎×DeepSeek构建八字、六爻赛博算卦娱乐应用

引言 随着DeepSeek的火爆&#xff0c;其强大的思维链让不少人越用越香&#xff0c;由于其缜密的思维和推理能力&#xff0c;不少人开发出了不少花里胡哨的玩法&#xff0c;其中一种就是以八字、六爻为代表的玄学文化正以“赛博玄学”的新形态席卷年轻群体。 针对于八字、六爻…

linux文件管理命令ln

linux文件管理命令ln 1、软链接2、硬链接3、命令参数3.1、必要参数3.2、选择参数 4、应用示例4.1、创建硬链接4.2、创建软链接&#xff08;符号链接&#xff09;4.3、 对目录创建软链接4.4、强制覆盖目标文件 5、应用场景 它的功能是为某一个文件在另外一个位置建立一个同步的链…

CT dicom 去除床板 去除床位,检查床去除

1. 前言 医院拍摄患者CT与MRI 图像&#xff0c; 但是CT图像中就会出现检查床的区域&#xff0c;来看CT扫描设备是什么样子的&#xff0c;红色标出区域 可以在图中看到&#xff0c;在头部位置安装有固定头部的类似支架的东西&#xff0c;这个东西拍摄出来时什么样子呢&#xff…

扩散模型中,Flow Matching的训练方式相比于 DDPM 训练方法有何优势?

在扩散模型中,Flow Matching(FM)相比DDPM(Denoising Diffusion Probabilistic Models)的训练方法具有以下核心优势: 1. 更简单的训练目标 DDPM:通过逐步预测噪声来间接优化数据分布的变分下界(ELBO),需要设计多步的噪声调度策略,训练目标依赖马尔可夫链的分解。Flow…

【用deepseek和chatgpt做算法竞赛】——还得DeepSeek来 -Minimum Cost Trees_5

往期 【用deepseek和chatgpt做算法竞赛】——华为算法精英实战营第十九期-Minimum Cost Trees_0&#xff1a;介绍了题目和背景【用deepseek和chatgpt做算法竞赛】——华为算法精英实战营第十九期-Minimum Cost Trees_1&#xff1a;题目输入的格式说明&#xff0c;选择了邻接表…

Python实现GO鹅优化算法优化随机森林分类模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后关注获取。 1.项目背景 在当今数据驱动的世界中&#xff0c;机器学习技术被广泛应用于各种领域&#xff0c;如金融、医疗、…

【目标检测】【YOLOv4】YOLOv4:目标检测的最佳速度与精度

YOLOv4&#xff1a;目标检测的最佳速度与精度 0.论文摘要 有许多特征被认为可以提高卷积神经网络&#xff08;CNN&#xff09;的准确性。需要在大规模数据集上对这些特征的组合进行实际测试&#xff0c;并对结果进行理论上的验证。某些特征仅适用于特定模型和特定问题&#…

常用电脑,护眼软件推荐 f.lux 3400K | 撰写论文 paper

常用电脑&#xff1f;平均每天用 5 个小时&#xff1f;你就要考虑用一个护眼软件了&#xff0c;对皮肤也好。因为电脑屏幕有辐射&#xff0c;比如蓝光。 f.lux 作为一款专业护眼软件&#xff0c;值得使用。之前用了三年的 Iris Pro&#xff0c;现在 f.lux 做的更好了。 使用…

新手小白如何挖掘cnvd通用漏洞之存储xss漏洞(利用xss钓鱼)

视频教程和更多福利在我主页简介或专栏里 &#xff08;不懂都可以来问我 专栏找我哦&#xff09; 如果对你有帮助你可以来专栏找我&#xff0c;我可以无偿分享给你对你更有帮助的一些经验和资料哦 目录&#xff1a; 一、XSS的三种类型&#xff1a; 二、XSS攻击的危害&#x…

ros通信与回调函数多线程应用

一、ros topic通信流程 参考资料: 一个ros节点至少有几个线程(1058): https://zhuanlan.zhihu.com/p/680188065 鱼香rostopic底层流程(1005~1008): https://zhuanlan.zhihu.com/p/656716718 王方浩-ROS发布订阅实现(二): https://zhuanlan.zhihu.com/p/439208597 基础的topic…

智能交通系统(Intelligent Transportation Systems):智慧城市中的交通革新

智能交通系统&#xff08;Intelligent Transportation Systems, ITS&#xff09;是利用先进的信息技术、通信技术、传感技术、计算机技术以及自动化技术等&#xff0c;来提升交通系统效率和安全性的一种交通管理方式。ITS通过收集和分析交通数据&#xff0c;智能化地调度、控制…

基于LM Arena 的 LLM 基准测试排行榜:DeepSeek-R1 排名第 5

打开 Arena 网站&#xff1a;https://lmarena.ai/&#xff0c;点开 Leaderboard 可以看到上图的排行榜&#xff0c;可以看到 DeepSeek-R1 排名第 5。