【问题标题】:C# - Saving Console Game ValuesC# - 保存控制台游戏值
【发布时间】:2013-11-15 21:15:59
【问题描述】:

我正在制作一个基于文本的游戏的控制台应用程序,我需要保存诸如 HP 和 Money 之类的值,以便以后能够检索它们。

我尝试过使用设置,但问题是它们依赖于文件名和文件路径,这意味着如果其中一个更改,则不会加载整个保存(这是一个问题,因为大多数玩家会更改文件名)。

所以我希望能够将变量的所有值保存到一个文本文件中并在以后检索它们。

有没有可能有效地做这样的事情?

如果有人可以提供帮助,谢谢。

【问题讨论】:

    标签: c# variables save


    【解决方案1】:

    您可以使用 IO 命名空间提供的简单类进行文件操作。
    在这里你可以找到很多例子

    Common I/O Tasks

    但总而言之,我建议遵循这个伪代码

    • 找到您要存储数据的文件夹
    • 在此文件夹中创建一个文件
    • 使用要写入的变量准备一个缓冲区
    • 关闭文件

    让我们从第一个任务开始

    string folder = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
    string folder = Path.Combine(folder, "myappNameDataFolder");
    Directory.CreateDirectory(folder);
    string dataFile = Path.Combine(folder, "myappNameDataFile");
    

    这里我们尝试在windows保留的特殊文件夹中建立一个文件夹,用于这台计算机的所有用户共有的应用程序数据。请参阅枚举 Environment.SpecialFolder。这是存储值的最佳位置,因为您拥有在那里读/写文件的所有正确权限。

    现在您可以使用通用 StreamWriter 类在该文件夹中创建文件

    using(StreamWriter sw = new StreamWriter(dataFile, true))
    {
       ....
    

    在上面的语句中,StreamWriter 是在 using 块内创建的,以确保它在封闭块的末尾关闭和销毁。

    现在您可以构建缓冲区来存储变量。这里我只展示了一个变量,我想这些变量在代码的这一点是可用的

       StringBuilder sb = new StringBuilder();
       sb.Append("HP=" + valueForHPToSave.ToString();
       .... other variables follow this line
    

    将缓冲区写入流并关闭并释放流

        sw.Write(sb.ToString());
    }
    

    逆运算(在应用启动时读回值)只需使用 StreamReader、ReadAllLines 并在等号处拆分每一行以恢复原始值

    另一种方法是使用框架提供的内置serialization mechanism
    在这种情况下,您将构建一个名为 AppState 的类,并使用 Serializable 属性对其进行标记

    using System.IO;
    using System.Runtime.Serialization.Formatters.Binary;
    
    [Serializable()]
    public class AppState
    {
         public int HPValue {get; set;}
         .... other variables to store/read from the serialization stream
    }
    

    目的是从磁盘写入和加载此类的实例,在磁盘中存储恢复应用程序状态所需的所有变量。

    现在您可以在主类中声明AppState 类的全局实例,并在应用执行期间开始存储这些值。

    public class Program
    {
         public static AppState stateVariables = new AppState();
    
         public static void Main()
         {
              // read back the values of stateVariables here... (see later)
              ...
              stateVariables.HPValue = 100;
              ...
         }
    }
    

    当应用程序关闭时,您可以使用这样的代码编写类的实例

    string folder = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
    string folder = Path.Combine(folder, "myappNameDataFolder");
    Directory.CreateDirectory(folder);
    string dataFile = Path.Combine(folder, "myappNameDataFile");
    using(Stream stateStream = File.Create(dataFile))
    {
        BinaryFormatter serializer = new BinaryFormatter();
        serializer.Serialize(stateStream, stateVariables);
    }
    

    当应用程序启动时,您使用类似的方法读回这些值

    public class Program
    {
         public static AppState stateVariables = new AppState();
    
         public static void Main()
         {
              string folder = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
              string folder = Path.Combine(folder, "myappNameDataFolder");
              Directory.CreateDirectory(folder);
              string dataFile = Path.Combine(folder, "myappNameDataFile");
              if (File.Exists(dataFile))
              {
                  using(Stream stateStream = File.OpenRead(dataFile))
                  {
                      BinaryFormatter deserializer = new BinaryFormatter();
                      stateVariables = (AppState)deserializer.Deserialize(stateStream);
                  }
              }
         }
    }
    

    请注意我没有测试过这段代码,要完全理解,请阅读更多关于Serialization on MSDN的信息

    【讨论】:

    • 非常感谢,但是没有更简单的方法吗?例如,我见过有人使用 数据和类似的东西来更快地将值写入文本文件。
    • +1。用于构建保存位置的示例。我会避免发明自定义文本格式,而不是使用标准 JSON/XML... 同样基于 cmets 可能需要一些自定义二进制序列化来实现一些(未定义的)性能目标。
    • @AlexeiLevenkov 可能你是对的。缺少太多细节,这只是 OP 的起点
    • 不清楚 是什么意思,但是有很多方法可以将数据写入磁盘和多种格式(XML、JSON、二进制)。这个例子只是为了展示写入文本数据的基础知识,它不是最快的方法,但是,它很简单,除非你有数千兆字节的存储空间,否则它不会改变性能的好坏。
    • 那么将所有变量写入文本文件并稍后检索它们的最短方法是什么?我知道你已经向我展示了,但可能有一条更短的方法。
    【解决方案2】:

    一种选择是保存到“我的文档”中的文件(或子文件夹中的文件)中。

    获取路径 - Environment.GetFolderPathMyDocuments

     var root = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
     var fileName = Path.Combine(root, "MyGame.sav");
    

    比以任何你喜欢的方式读/写你的设置。

    您也可以考虑使用其他文件夹,例如LocalApplicationData...

    【讨论】:

    • 读/写是我的主要问题......是否有一种高效但不太复杂的方法来处理所有变量?
    • @BlueRay010... 存储 JSON 或使用 XmlSerialization 非常简单,但从大多数角度来看并不是“高效”(除了正确性、数据可读性和易于编写代码)。您需要提供更多信息才能为问题的“高效”部分提供良好的答案。
    • 好的,我的意思是将所有变量保存到 .txt 文件中,然后从文本文件中检索它们。我想尽可能短地做到这一点。我该怎么做?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-09
    • 2022-06-23
    • 2023-04-11
    • 2018-07-02
    • 1970-01-01
    相关资源
    最近更新 更多