【问题标题】:How to save / load this data?如何保存/加载这些数据?
【发布时间】:2013-08-07 03:47:24
【问题描述】:

我有一些需要保存的项目,它们都是地图的价值。因此,每次用户都可以加载旧地图或创建并保存新地图。但我不确定如何或使用什么过程来保存所有数据。

我有

TCube array (1..10000)
Row, Column : integers
NumberOfBlocks : integers

因此,当用户单击保存时,它应该保存数组数据(我不确定这是否重要,但并非所有 10,000 个立方体都已创建)以及 3 个整数。

创建 TCUBE 数组和整数的完整代码。

procedure TForm2.createMap(r:integer;c:integer);
var
 i : integer;
 rows,columns,columnssave : integer;
 x,y,z : single;
 player : tmodel3d;

 begin
 columns := r;
 rows := c;
 i:=1;
 x := 0;
 y := 0;
 z := 0;
 NumberOfRows := rows;
 NumberOfColumns := columns;
 camera1.Position.X := rows/2;
 camera1.Position.Y := columns/2;
 dummy1.Position.X := rows/2;
 dummy1.Position.Y := columns/2;
   while rows>0 do
    begin
      columnssave := columns ;
      while columns >0 do
        begin
           CreateCube[i]:=tcube.Create(self);
           CreateCube[i].Visible := true;
           CreateCube[i].Position.x := x;
           CreateCube[i].Position.Y := y;
           CreateCube[i].Position.Z := z;
           CreateCube[i].Material.Texture.CreateFromFile(gamedir+'\pics\Grass.bmp');
           CreateCube[i].Material.Modulation := TTextureMode.tmReplace;
           CreateCube[i].Parent := viewport3d1;
           CreateCube[i].OnClick := cubeClick;
           CreateCube[i].OnMouseDown := mousedown;
           y:= y+1;
           i:=i+1;
           //z:=z-1;
           columns := columns -1;
        end;
      y:=0;
      x:= x+1;
      z:=0;
      columns := columnssave;
      rows:= rows-1;
    end;
    totalblocks := i;

 setblocks := false;
 label2.Text := inttostr(totalblocks);


 end;

谢谢 格伦

【问题讨论】:

  • 你能显示真实的代码吗?
  • @MBo 目前我没有要保存或加载的代码,只能创建新的...因为我不确定如何保存/加载,但添加了代码以显示我如何创建数组跨度>
  • 如果有人回答建议您保存到 INI 文件或 JSON 格式,您会怎么说?你会说,“我不想要一个人类可读的文本文件”。然后回答者将浪费他们的时间。所以是的,如果您有要求,它们必须出现在 Q 中。
  • -1 因为您一直 忽略所有 cmets 要求您提供更多详细信息在您的问题中。如果您甚至无法提供有关您尝试保存的数据结构的信息,那么就不可能为您提供有关如何保存它的答案。 question 中需要提供更多详细信息,而不是隐藏在杂乱无章的 cmets 中。你有能力edit你的帖子来改进或澄清事情,但你一直无视要求你这样做的请求。如果您希望删除“-1s”,您需要改进您的问题。
  • 来自 cmets 的新信息:致 David “存储在用户无法打开的文件类型(如 ini)中”,以及“首选项是不可读的文本文件”(无论这意味着什么)。对尼克:“每个 TCube 的位置 x,y,z 然后是 3 个整数值”(以及更多)。所有这些都是新信息,不在您的问题中(您所说的只是“保存数组数据......连同整数”)。在您的问题中也没有任何努力自己做任何事情来保存它,包括至少努力将它保存到文本文件中。

标签: delphi delphi-xe2 firemonkey


【解决方案1】:

有很多方法可以将数据保存到文件中。通常我使用NativeXML 来读写XML 文档。这可能不是最好的方法,但它对我有用,并且到目前为止一直适用于我的项目。

  • 它是人类可读的,因此您可以看到正在发生的事情。非常适合在某些事情无法正常工作时进行调试。
  • 它是结构化的。当您需要为其他对象包含的对象保存数据时,这会有所帮助。例如,在你的游戏世界中,有一个村庄,村庄包含 10 座建筑物,1 号建筑物包含 7 盏灯,2 号建筑物包含 3 把剑,等等。
  • 这是一种标准且常用的格式。您的游戏数据文件可以在其他程序中读取和操作。
  • 可以对 XML 文件进行加密,以防止用户修改数据。

保存代码的示例:

procedure TMyGame.SaveToFile(const FileName: string);
var
  XML : TNativeXML;
  RootNode : TXmlNode;
  CubeNode : TXmlNode;
begin
  XML := TNativeXML.CreateName('root');
  try
    RootNode := XML.Root;

    for c1 := 0 to NumberOfCubes-1 do
    begin
      CubeNode := RootNode.NodeNew('Cube');

      CubeNode.NodeNew('XPos').ValueAsInteger := 10;
      CubeNode.NodeNew('YPos').ValueAsInteger := 2;
    end;

    XML.SaveToFile(FileName);
  finally
    XML.Free;
  end;
end;

【讨论】:

    【解决方案2】:

    我强烈主张使用人类可读的数据,例如 XML 或 .ini 文件。如果您需要阻止用户编辑/修改数据,您可以通过“签署”数据并添加验证密钥来实现。您的程序可以通过获取您的敏感数据、附加只有您知道的内容、然后生成 MD5 散列或对其进行加密来生成密钥。 MD5 结果,或加密字符串的前 100 个字节,将成为您存储在 .ini 或其他文件中的密钥。
    例如:

    [MAPSTUFF]
    SecretCoordinates=1,2,3,PIRATE TREASURE IS HERE
    SignedKey=00042055215e2c6c0d751cb5b086e653
    

    SignedKey 实际上是 SecretCoordinates 字符串 + :XYZZY 的 MD5: 即我通过MD5运行这个: 1,2,3,海盗宝藏在这里:XYZZY: 并得到: 00042055215e2c6c0d751cb5b086e653

    所以要签入程序,你从 .ini 文件中读取 SecretCoordinates,添加 :ZYZZY: 到它(在程序中,所以用户看不到(但如果他们有调试器,他们仍然可以))。看看你是否得到相同的MD5。如果是比赛,那你很好。如果不匹配,则 SecretCoordinates 字符串已被篡改,您拒绝它。很简单。

    【讨论】:

    • +1 用于必要的加盐,否则这将相对容易被击败;-) OP 可以选择在开发过程中忽略 MD5 以便于测试。
    【解决方案3】:

    保存此类数据的最佳方法之一是创建记录并保存记录。然后它也不是人类可读的东西。 sof 先创建一个新类型

      TCubeSave = record
         number : integer;
         x : single;
         y : single;
         z : single;
         texture : string[20];
      end;
    

    在这种情况下,我们希望将数字连同数据 x、y、z 和纹理一起保存在数组中? 如果做任何字符串,请确保它是一个数组,否则你会得到一个错误。

    接下来分配您的变量和文件并使其准备就绪。

    var
     myfile : File of TCubeSave;
     cube : TcubeSave;
     i : integer;
    begin
      assignfile(myfile, gamedir+'\maps\test.map');
      ReWrite(myfile);
      i:=0;
    

    现在写数组的每个组件, while (i

    检查组件是否存在,以防您已将其删除或未创建。

       if FindComponent('cubename'+inttostr(i)) <> nil then
           begin
    

    将数据写入文件立方体

            cube.number := i;
            cube.x := createcube[i].Position.X;
            cube.y := createcube[i].Position.Y;
            cube.z := createcube[i].Position.Z;
            cube.texture := createcube[i].Material.Texture.ToString;
            Write(myfile, cube);
           end;
          i := i+1;
       end;
    

    完成后关闭文件。

       CloseFile(myfile);
       showmessage('Map Saved');
    end;
    

    准备读取文件时..

      // Reopen the file in read only mode
      FileMode := fmOpenRead;
      Reset(myFile);
    
      // Display the file contents
      while not Eof(myFile) do
      begin
        Read(myFile, cube);
    
          i:= cube.number;
    
          CreateCube[i]:=tcube.Create(self);
          createCube[i].Position.x := cube.x;
          createcube[i].position.y := cube.y;
           ect.....
      end;
    
      // Close the file
      CloseFile(myFile);
    

    【讨论】:

    • -1:恕我直言,保存文件如果是人类可读的会更好。它使调试保存/加载问题变得更容易,更容易维护不同应用程序版本之间的兼容性等等......
    • @Glen 如果您不希望读者编辑数据,那么这个解决方案是不够的。文件中重复的 TCubeSave 结构很容易识别,任何有点计算机知识的人都可以尝试使用十六进制编辑器。
    猜你喜欢
    • 1970-01-01
    • 2020-02-15
    • 1970-01-01
    • 2014-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-29
    • 1970-01-01
    相关资源
    最近更新 更多