Лучший способ хранить многомерный массив на сервере? - PullRequest
2 голосов
/ 29 декабря 2008

Я разрабатываю пошаговую стратегическую игру, которая разворачивается на доске 10х10.

Каждая ячейка представляет собой участок земли и имеет собственный набор статистических данных (например, доход, население, рождаемость, природные ресурсы).

Каждый раз, когда клиент загружает, он загружает всю информацию для игры (т. Е. Загрузка статистики только одной плитки не требуется). Размер доски статичен, то есть всегда есть ровно 100 плиток.

Каков наилучший вариант для хранения этих данных на сервере? (игнорируя ключи и прочее)

  • В базе данных: таблица с (количество статистических данных на плитку) полями и 100 записями для каждой игры.
  • В базе данных: таблица с одной записью для каждой игры и 100 * (num stats / tile) полей
  • В плоском файле.

Ответы [ 7 ]

1 голос
/ 29 декабря 2008

Этот точный вопрос был задан на IRC-канале #django некоторое время назад, хотя он хотел получить игровое поле переменного размера для разных экранов.

Общая рекомендация заключалась в том, чтобы сначала использовать хороший, чистый, нормализованный метод и оптимизировать его до денормализованного состояния при возникновении проблем с производительностью. Основная причина, по которой сначала нужно идти по пути нормализации, заключается в том, что база данных построена так, чтобы довольно легко обрабатывать множество взаимосвязей и может легко кэшировать полученные результаты, если они не меняются слишком часто.

Под нормализованной установкой я подразумеваю (псевдокод):

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 записей на доске, но это того стоит, если вы спросите меня. Это облегчает поиск всех фишек игрового поля. Запись в отдельную ячейку может быть выполнена только с помощью ее идентификатора, без сложной интерпретации строк или чего-либо еще.

1 голос
/ 29 декабря 2008

Перейти с базой данных, по одной строке на плитку. Поскольку каждый ход игры, вероятно, не меняет много фишек на доске, лучше всего их разделять. Точно так же, если вам нужно

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';
0 голосов
/ 29 декабря 2008

Если действия игрока в течение одного «хода» могут повлиять только на одну ячейку (или небольшую группу смежных ячеек), тогда вы захотите сохранить данные таким образом, чтобы частичное обновление не требовалось переписывать всю доску. на диск (и читать всю доску) каждый раз.

Учитывая небольшое количество ячеек в игре, я склонялся бы к базе данных с ключом {идентификатор игры, координата x, координата y}.

0 голосов
/ 29 декабря 2008

Ваш вопрос не завершен.

База данных предназначена для (1) запросов и (2) обновления. Вы не упомянули ни вопросы, ни обновления ваших данных.

Хранение данных не особенно полезно для базы данных. Если вы хотите хранить данные, вы обычно используете простые файлы. Резервное копирование баз данных регулярно выполняется в виде простых файлов для длительного хранения, резервного копирования и восстановления.

Если нет запросов и обновлений, тогда подойдет простой файл.

Если, однако, есть запросы или обновления, то база данных может иметь смысл. Разумеется, конкретная структура будет зависеть от характера запросов или обновлений.

0 голосов
/ 29 декабря 2008

Если вы не собираетесь искать или заказывать данные на досках или что-то подобное, я бы сказал, что плоский файл будет работать. Но ваши пользователи могут «хотеть» жить в базе данных? Тогда данные с доски тоже вписываются туда. Может быть, просто сохраните доску в одном поле varchar в любом формате, который вам больше подходит, в формате XML или в сериализованном виде или в любом другом виде.

0 голосов
/ 29 декабря 2008

начать с диаграммы отношения сущностей между сущностями. Я вижу несколько из вашего краткого описания:

одна доска за игру у игры есть метка времени, показывающая, когда она была начата на доске много тайлов - 10х10 сейчас, может быть произвольным у плитки много статистики

есть другие, от которых ты, кажется, отказался. Повороты подразумевают более одного игрока. В игре будет много игроков.

возможно, вы захотите пометить статистику времени и сохранить историю обновлений.

это объектно-ориентированная система? Вы придумали объектную модель? Я бы начал с этого первым.

0 голосов
/ 29 декабря 2008

Я бы создал таблицу, где каждая строка представляет одну плитку в игре.

Тогда у меня будет столбец для X (от 1 до 10) и Y (от 1 до 10). В зависимости от ваших требований вы также можете сохранить, какая это игра (если вы хотите сохранить несколько игр одновременно), а какая очередь (если вы хотите сохранить историю игр).

Итак, вы бы получили:

Плитка: GameID
Превратить инт X int Y int доход Население фертильность и т.д.

Первичный ключ - это первые 4 столбца. Вероятно, GameID станет внешним ключом игрового стола.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...