【问题标题】:How should i deal with the card assignment of my game?我应该如何处理我的游戏的卡分配?
【发布时间】:2017-03-08 23:26:11
【问题描述】:

我已经检查了显示的关于我的标题的大部分问题,但它们与我正在寻找的内容无关,所以我开始我自己的问题。

我正在尝试将其重新创建为在线游戏的游戏名为Buraco,不确定你们是否知道大多数人或任何人。

我已经具备了我的游戏的基本功能,例如:

  • 洗牌
  • 分发卡片

我现在陷入困境的是我应该如何处理分配给玩家 A、B、C、D 的牌、留在牌组上的牌、垃圾箱上的牌以及将在如果由 4 名玩家参与,则由两队参与;如果由 2 名玩家参与,则由每名玩家参与。

考虑到我不希望任何玩家在游戏中作弊,我必须将每张分配的卡片保存在数据库中,所以我在想我应该如何创建我的 MySQL 表来适应这个?

我想到的第一件事是创建一个表格,其中包含游戏会话和所有卡片作为一列,但嘿一共有 104 张卡片 ???可能还有很多其他更好的方法来实现这一点。

然后我想到我可以使用 varchar 或 text 来保存所有给定的卡片,这会使得验证每张已经递出的卡片变得有点困难,仍然在甲板上或在垃圾上或在表。


所以我想我的问题是:

  1. 考虑到它是多人游戏(用户创建一个房间来为 2 或 4 名玩家服务),我对这款游戏的最佳选择是什么数据库?

  2. 您将如何使用表来使用 MySQL 或任何其他数据库维护每个游戏?

  3. 您将如何处理更新(如您所见,我将使用 ajax 来更新游戏,是否有任何最佳实践来说明我应该限制每个数据的频率或多少数据或哪种数据?更新,因为它将更新房间中的所有用户,并且很可能不会全部一起作为 1 个请求,这将是对服务器使用影响的一个大问题)?

  4. 您会如何根据您喜欢使用的数据库结构比较卡片(查询示例)?

PS:如果您对此主题有更好的标题,请告诉我这是我当时想到的。

【问题讨论】:

  • 您将来可能会考虑将您的查询分解为单独的问题(因为您已经在问题文本中进行了描述!)。尽管它们(在您的情况下)都与单个任务相关,但整个社区从这些机制中受益更多 - 其他项目将从了解如何设计成员表方案或优化来自 web ui 的 ajax 交互中受益。这可能会提高对您问题的响应率(和兴趣)。
  • 我会牢记这一点,我也相信这可能会导致社区其他人提供更好的意见,谢谢。

标签: mysql database-design logic


【解决方案1】:

这只是部分答案,但关于数字 2(表结构)将其分解并认为所有游戏资产都是卡片。

创建一个表格,其中包含游戏、卡、其值(如果适用)、当前所有者(表示特定玩家、堆栈或弃牌堆的值)的列。为了管理形成的集合,创建两个额外的表:一个用于组或卡组,以及一个链接表,用于显示游戏中的卡成员到给定组(这也可以通过基表中的字符串列来实现和一些逻辑,但对于纯 rdbms 方法,拆分表)。

编辑:

问题 1 - 数据库选项

这里有很多关于 MySQL 性能和优化的问题。您的游戏要考虑的最大特征是读取操作与写入操作的频率。标准 MySQL 配置优化了读取性能——这可能是根据您描述游戏的最佳方式。

问题 2 - 表配置

为了扩展我以前的 cmets,我提出以下建议(请随意调整表名 - 它们只是为了解释):

  • 带有列的game_cards 表(game_idcard_idvalueowner
  • game_sets 表(set_idgame_idowner
  • card_set_membership 表与 (set_id, card_id)

game_cards 表格最初应填充完整的牌组(无论您拥有多少张卡片,也就是您添加到表格中的行数)。所有卡片都应由card_id 标识,其中每张卡片代表套牌 中的唯一卡片,并且对于给定的游戏,game_id 的值都应相同(因为它们是同样的游戏)。

  • game_cards.value 列将代表卡片固有的点数(如果适用于您的游戏)。
  • game_cards.owner 列将包含一个值来指示卡的位置;您游戏中的示例可能是“deck”、“discard”、“p1”、“p2”、“p3”、“p4”

这使您可以存储您拥有的卡片、它们的价值以及它们的位置(谁或什么拥有)。默认情况下,如果所有卡片都从 deck 开始,那么您可以设置 game_cards.owner = 'deck' 的值。当一张牌被“抽到”时,你,比如玩家 3,你可以将抽到的牌的值更新为game_cards.owner = 'p3'

下一个难题是将卡片收集到任意中。为了在典型的 rdbms 中处理这个问题,我使用一个表来创建集合列表 (game_sets),另一个将游戏中的卡片链接到集合 (card_set_membership)。当用户开始将卡片收集到一组中时,在 game_sets 表中创建一条记录,其中包含新的 set_id、来自主 game_cards.game_id 字段的 game_id 以及给玩家(或其他实体)的 owner ,如果可能的话在你的游戏中),其中有集合。如果您已经定义了一个 set,则使用set_idcard_id 将记录添加到card_set_membership 表。您不必在此处保留 game_id,因为您可以通过 game_sets 表了解这一点。

注意:此配置允许单张卡成为多组的一部分。如果您不需要这个(即一张卡片可能只是一组的一部分),那么您可以将 game_id 添加到 card_set_membership 表中,并且根本不使用 game_sets

希望这能更清楚一点!

问题 3 - 数据库更新

简短的回答是,您应该尽量减少客户端和服务器之间的流量。如果您使用的是 ajax,那么请尽量确保消息开销(打包)尽可能小。查看您的用户可以在客户端执行的操作,然后考虑如何将其转化为服务器端的操作。设计一组消息来实现这些动作并查看它们所需的数据(例如一张或多张牌,哪个玩家做出了动作等)。如果您担心作弊,请考虑嵌入一个客户端不容易伪造的密钥(而不仅仅是“p1”或“p2”等)(可能与他们的会话登录有关?)。

【讨论】:

  • Create a table with a column for the game, the card, its value (if applicable), the current owner (which would be a value to indicate either a specific player, the stack, or the discard pile). 所以你说这将是我的基本牌组,每当游戏开始时,我都会填写关于给定游戏会话的所有纸牌属性,然后是第二张表来存储如何卡片被发送到桌子和另一张桌子上存储它属于哪个组?它看起来不错,但有点令人困惑,我试图将它放入 MySQL Workbench 但没有走正确的路。
  • 我已经扩展了我的回复 - 希望这更有意义。基本思想是旋转数据模型,这是 rdbms 配置/数据库建模中的常见策略。
  • 非常感谢 AJ,它现在确实对我有很大帮助 :) 我现在正在考虑使用 fastcgi,这让我觉得我可以丢弃所有数据库关系的东西并拥有用于排名的数据库仅用于处理内存中的游戏状态和表格。
  • 这可能工作得很好——只要注意 cgi 元素的寿命(除非你缓存到一个文件中)——你不希望人们失去他们的游戏状态!此外,您需要考虑如何跨会话共享游戏状态。