【问题标题】:Best way to store multi-dimensional array on a server?在服务器上存储多维数组的最佳方法?
【发布时间】:2010-09-28 15:49:30
【问题描述】:

我正在开发一款基于网络的回合制策略游戏,该游戏在 10x10 棋盘上进行。

每个图块代表一块土地,并有自己的一组统计数据(例如,收入、人口、生育率、自然资源)。

客户端每次加载时都会下载游戏的所有信息(即,无需加载仅一个图块的统计数据)。棋盘大小是静态的,即总是正好有 100 个棋子。

在服务器上存储这些数据的最佳选择是什么? (忽略键等)

  • 在数据库中:包含(每个图块的统计数据数量)字段和每个游戏 100 条记录的表。
  • 在数据库中:每场比赛有一条记录和 100*(num stats/tile) 字段的表
  • 在平面文件中。

【问题讨论】:

  • 或者,如果我没有考虑过第 4(第 5、第 6...)个替代方案,也请提出建议!
  • 您计划支持多少次会议?

标签: database arrays


【解决方案1】:

这个确切的问题是不久前在#django IRC 频道上提出的,尽管提问者想要一个用于不同屏幕的可变大小的游戏板。

总体建议是首先使用一个不错的、干净的、规范化的方法,如果遇到性能问题,则优化到非规范化状态。首先走规范化路线的主要原因是,数据库被构建为相当容易地处理大量关系,并且如果它们不经常更改,可以轻松缓存它获得的结果。

我所说的规范化设置是(伪代码):

Table Board
{
    BigInt id;
    String name;
    Date date_played;
    etc...
}

Table Tile
{
    BigInt id;
    ForeignKey board;  // what board the tile belongs to
    ManyToMany items;  // items on this tile
    ManyToMany players;   // players on this tile
    etc...
}

Table Item
{
    BigInt id;
    String name;
}

Table Player
{
    BigInt id;
    String name;
}

// many-to-many link table
Table TileItem
{
    BigInt id;
    BigInt tile; // tile id
    BigInt item;  // item id
}

// do the same thing for players
Table TilePlayer
{
    BigInt id;
    BigInt tile;
    BigInt player;
}

您将在每个板上存储 100 条记录,但如果您问我,这是值得的。这使得查找所有游戏板图块变得容易。可以仅使用其 ID 写入单个磁贴,无需复杂的行解释或任何其他操作。

【讨论】:

    【解决方案2】:

    使用数据库,每个图块一行。由于每个游戏回合可能不会修改很多棋盘图块,因此最好将它们分开。同样,如果您需要

    Tiles (
        tile_id bigint autoincrement;
        game_id bigint; // foreign key to game table
        x tinyint;
        y tinyint;
        fertility type;
        // etc.
        primary key (tile_id)
        unique key (game_id, x, y)
    );
    
    Games (
       game_id bigint autoincrement;
       status enum(pendingplayers, started, finished, pendingdeleteorarchive)
       turn_number int;
       date_started date;
       date_ended date;
    );
    

    将这些内容保存在数据库中的好处之一是它可以在更新内容时为您节省一些精力。例如,如果您的土地的一个特征每回合都发生变化,您可以只更新数据库,而不是循环遍历图块:

    Update tiles set fertility = fertility * 0.99 where game_id = :x and land_type = 'forest';
    

    【讨论】:

      【解决方案3】:

      我会创建一个表格,其中每一行代表游戏中的单个图块。

      然后,我将有一列用于 X(从 1 到 10)和 Y(从 1 到 10)。根据您的要求,您还可以存储它是哪个游戏(如果您想同时保留多个游戏)以及它是哪个回合(如果您想保留游戏的历史)。

      所以你会:

      瓷砖: 游戏ID
      转整数 X 整数 整数 收入 人口 生育能力 等等

      主键是前 4 列。 GameID 可能最终会成为 Game 表的外键。

      【讨论】:

        【解决方案4】:

        从实体之间的实体关系图开始。从你的简要描述中我可以看出一些:

        每场比赛一个棋盘 游戏有一个时间戳显示它何时开始 棋盘有很多瓷砖 - 现在 10x10,可能是任意的 一个图块有很多统计数据

        您似乎忽略了其他一些内容。转牌意味着不止一名玩家。一个游戏会有很多玩家。

        您可能希望为统计数据加上时间戳并保留更新历史记录。

        这是一个面向对象的系统吗?你有没有想出一个对象模型?我会先从那个开始。

        【讨论】:

          【解决方案5】:

          如果您不打算搜索或订购板上的数据或其他类似的数据,我会说平面文件可以工作。但是您的用户可能“想要”住在数据库中?然后董事会数据也适合那里。也许只需将板以最适合您的格式存储在一个 varchar 字段中,XML 或序列化或其他格式。

          【讨论】:

            【解决方案6】:

            您的问题不完整。

            数据库用于 (1) 查询和 (2) 更新。您没有提到对数据的查询或更新。

            存储数据对于数据库来说并不是一个特别好的用途。如果要存储数据,通常使用简单文件。数据库会定期备份到简单文件,以便长期存储、备份和恢复。

            如果没有查询和更新,那么一个简单的文件就可以了。

            但是,如果有查询或更新,那么数据库可能是有意义的。当然,具体结构取决于查询或更新的性质。

            【讨论】:

              【解决方案7】:

              如果玩家在单个“回合”上的操作只能影响单个单元格(或一小组相邻单元格),那么您需要以允许部分更新而无需重写整个棋盘的方式存储数据每次都写入磁盘(并读取整个电路板)。

              鉴于每场比赛的单元格数量较少,我倾向于使用 {game ID, x 坐标, y 坐标} 键的数据库。

              【讨论】:

                猜你喜欢
                • 2014-05-02
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2020-04-28
                • 2012-08-13
                • 2021-06-19
                • 2011-01-14
                • 1970-01-01
                相关资源
                最近更新 更多