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

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

#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.rhkb.cn/news/22672.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

后“智驾平权”时代,谁为安全冗余和体验升级“买单”

线控底盘&#xff0c;正在成为新势力争夺下一个技术普及红利的新赛点。 尤其是进入2025年&#xff0c;比亚迪、长安等一线传统自主品牌率先开启高阶智驾的普及战&#xff0c;加上此前已经普及的智能座舱&#xff0c;舱驾智能的「科技平权」进一步加速行业启动「线控底盘」上车窗…

【Node.js】express框架

目录 1初识express框架 2 初步使用 2.1 安装 2.2 创建基本的Web服务器 2.3 监听方法 2.3.1 监听get请求 2.3.2 监听post请求 2.4 响应客户端 2.5 获取url中的参数(get) 2.5.1 获取查询参数 2.5.2 获取动态参数 2.6 托管静态资源 2.6.1 挂载路径前缀 2.6.2 托管多…

树形DP(树形背包+换根DP)

树形DP 没有上司的舞会 家常便饭了&#xff0c;写了好几遍&#xff0c;没啥好说的&#xff0c;正常独立集问题。 int head[B]; int cnt; struct node {int v,nxt; }e[B<<1]; void modify(int u,int v) {e[cnt].nxthead[u];e[cnt].vv;head[u]cnt; } int a[B]; int f[B]…

REACT--组件通信

组件之间如何进行通信&#xff1f; 组件通信 组件的通信主要借助props传递值 分为整体接收、解构接收 整体接收 import PropTypes from prop-types;//子组件 function Welcome(props){return (<div>hello Welcome,{props.count},{props.msg}</div>) }// 对 We…

【排序算法】六大比较类排序算法——插入排序、选择排序、冒泡排序、希尔排序、快速排序、归并排序【详解】

文章目录 六大比较类排序算法&#xff08;插入排序、选择排序、冒泡排序、希尔排序、快速排序、归并排序&#xff09;前言1. 插入排序算法描述代码示例算法分析 2. 选择排序算法描述优化代码示例算法分析 3. 冒泡排序算法描述代码示例算法分析与插入排序对比 4. 希尔排序算法描…

纠错检索增广生成论文

一、摘要 动机&#xff1a;RAG严重依赖于检索文档的相关性&#xff0c;如果检索出错&#xff0c;那么LLM的输出结果也会出现问题 解决方案&#xff1a;提出纠正性检索增强生成&#xff08;CRAG&#xff09;即设计一个轻量级的检索评估器&#xff0c;用来评估针对某个查询检索…

Java NIO与传统IO性能对比分析

Java NIO与传统IO性能对比分析 在Java中&#xff0c;I/O&#xff08;输入输出&#xff09;操作是开发中最常见的任务之一。传统的I/O方式基于阻塞模型&#xff0c;而Java NIO&#xff08;New I/O&#xff09;引入了非阻塞和基于通道&#xff08;Channel&#xff09;和缓冲区&a…

easelog(1)基础C++日志功能实现

EaseLog(1)基础C日志功能实现 Author: Once Day Date: 2025年2月22日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 注&#xff1a;本简易日志组件代码实现参考了Google …

Vue面试2

1.跨域问题以及如何解决跨域 跨域问题&#xff08;Cross-Origin Resource Sharing, CORS&#xff09;是指在浏览器中&#xff0c;当一个资源试图从一个不同的源请求另一个资源时所遇到的限制。这种限制是浏览器为了保护用户安全而实施的一种同源策略&#xff08;Same-origin p…

MongoDB应用设计调优

应用范式设计 什么是范式 数据库范式概念是数据库技术的基本理论&#xff0c;几乎是伴随着数据库软件产品的推出而产生的。在传统关系型数据库领域&#xff0c;应用开发中遵循范式是最基本的要求。但随着互联网行业的发展&#xff0c;NoSQL开始变得非常流行&#xff0c;在许多…

Mac安装配置Tomcat 8

一、官网下载 Index of /disthttps://archive.apache.org/dist/ 1、进入界面如下&#xff1a; 2、我们找到Tomcat文件夹并进入 3、找到Tomcat 8并打开 4、找到对应的版本打开 5、打开bin 6、找到“apache-tomcat-8.5.99.tar.gz”并下载 二、配置Tomcat 1、解压已经下载好的…

【论文精读】VLM-AD:通过视觉-语言模型监督实现端到端自动驾驶

论文地址&#xff1a; VLM-AD: End-to-End Autonomous Driving through Vision-Language Model Supervision 摘要 人类驾驶员依赖常识推理来应对复杂多变的真实世界驾驶场景。现有的端到端&#xff08;E2E&#xff09;自动驾驶&#xff08;AD&#xff09;模型通常被优化以模仿…

百度搜索,能否将DeepSeek变成“内功”?

最近&#xff0c;所有的云平台和主流APP都在努力接入DeepSeek。其中&#xff0c;搜索类APP与搜索引擎更是“战况激烈”。那么问题来了&#xff0c;接入DeepSeek已经变成了标准配置&#xff0c;到底应该如何做出差异化&#xff1f;接入DeepSeek这件事能不能实现11大于2的效果&am…

Flask实现高效日志记录模块

目录 一. 简介&#xff1a; 1. 为什么需要请求日志 二. 日志模块组成 1. 对应日志表创建&#xff08;包含日志记录的关键字段&#xff09; 2. 编写日志记录静态方法 3. 在Flask中捕获请求日志 4. 捕获异常并记录错误日志 5. 编写日志接口数据展示 6. 写入数据展…

25轻化工程研究生复试面试问题汇总 轻化工程专业知识问题很全! 轻化工程复试全流程攻略 轻化工程考研复试真题汇总

轻化工程复试心里没谱&#xff1f;学姐带你玩转面试准备&#xff01; 是不是总觉得老师会问些刁钻问题&#xff1f;别焦虑&#xff01;其实轻化工程复试套路就那些&#xff0c;看完这篇攻略直接掌握复试通关密码&#xff01;文中有重点面试题可直接背~ 目录 一、这些行为赶紧避…

查看已经安装的Python库,高效管理自己的Python开发环境

在日常的Python开发中&#xff0c;掌握如何管理和查看已经安装的库是非常重要的。这不仅能帮助你了解当前项目的依赖关系&#xff0c;还能避免出现版本冲突等问题。在这篇文章中&#xff0c;我们将详细介绍查看已安装Python库的方法&#xff0c;并提供一些实用的工具和技巧。 …

Selenium实战案例1:论文pdf自动下载

在上一篇文章中&#xff0c;我们介绍了Selenium的基础用法和一些常见技巧。今天&#xff0c;我们将通过中国科学&#xff1a;信息科学网站内当前目录论文下载这一实战案例来进一步展示Selenium的web自动化流程。 目录 中国科学&#xff1a;信息科学当期目录论文下载 1.网页内…

Visual Studio Code 2025 安装与高效配置教程

一、软件简介与下载 1. Visual Studio Code 是什么&#xff1f; Visual Studio Code&#xff08;简称VS Code&#xff09;是微软推出的免费开源代码编辑器&#xff0c;支持 智能代码补全、Git集成、插件扩展 等功能&#xff0c;适用于前端开发、Python、Java等多种编程场景。…

工业路由器和工业交换机,打造高效稳定的工业网络?

工业路由器和工业交换机各有千秋&#xff0c;但如何将它们完美结合&#xff0c;构建稳定高效的工业网络&#xff1f;答案就在这里&#xff01; 工业物联网&#xff08;IIoT&#xff09;是高效、稳定的工业网络成为智慧工厂、工业自动化和远程监控等场景的基础支撑。工业路由器…

DeepSeek 助力 Vue 开发:打造丝滑的二维码生成(QR Code)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…