Как обеспечить соотношение 1 к n - PullRequest
5 голосов
/ 18 октября 2011

Я работаю над онлайновой настольной игрой muiltiplayer и у меня вопрос по SQL-серверу.

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

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

Моя схема базы данных выглядит следующим образом:

tbGame - contains a list of all games. PrimaryKey is GameId
tbPlayers - contains a list of all registered users. PrimaryKey is PlayerId
tbPlayersInGame - contains a list of all players in each game. Foreign key 
                  relations to tbGame and tbPlayers.

Я чувствую, что мне нужны две вещи:

  1. Способ блокировки tbPlayersInGame на основе идентификатора GameId. Это будет использоваться при добавлении игрока в игру. Из того, что я прочитал, звучит так, что подойдет блокировка диапазона клавиш (на GameId).
  2. Способ принудительного установления отношения 1: 2, чтобы попытки добавить третьего игрока потерпели неудачу.

Ответы [ 2 ]

1 голос
/ 18 октября 2011

Вместо отношения 1 к n вы можете настроить свою таблицу так, чтобы она имела столбцы - вероятно, помеченные host_player и visitor_player или необходимый эквивалент (как в шахматах - black и white ). Преимущество этого состоит в том, чтобы свести к минимуму забавные вещи и показать естественное состояние отношений.

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

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

INSERT INTO game_players (game_id, player_id) 
SELECT VALUES (:GAME_ID, :PLAYER_ID)
WHERE :MAX_PLAYER_COUNT > (SELECT COUNT(*)
                           FROM game_players
                           WHERE game_id = :GAME_ID)

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

1 голос
/ 18 октября 2011

Пара предложений:

1) Когда вы пытаетесь записать в таблицу tbPlayersInGame, сначала выполните SELECT, чтобы убедиться, что игра не заполнена, затем ВСТАВЬТЕ В таблицу.Оберните этот SELECT и INSERT INTO в транзакцию с уровнем изоляции транзакции, установленным на serializable.

2) Не используйте отдельную таблицу tbPlayersInGame, вместо этого в tbGame есть 2 поля: Player1Id, Player2Id

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