【问题标题】:database design help for game / user levels / progress游戏/用户级别/进度的数据库设计帮助
【发布时间】:2011-01-30 15:35:22
【问题描述】:

对不起,这太长了,而且都是散文。我正在创建我的第一个真正游戏化的网络应用程序,并且可以使用一些帮助来思考如何构建数据。

设置

用户需要完成多个类别中的每一个任务才能升级。我有我的UsersTasksCategories 表,还有一个连接三者的UserTasks 表。 (“用户 3 在类别 8 中添加了任务 42。现在他们已经完成了。”)这一切都很好,而且工作得很好。

挑战

我不确定跟踪各个类别中每个级别的进度的最佳方法。 “业务”规则是:

  1. 您必须在每个类别中达到一定数量的分数才能向上移动。
  2. 如果您获得了 Cat 8 所需的分数,但仍有其他工作要做以完成该级别,则任何新的 Cat 8 分数都会计入您的总分,但不要“滚动”到下一个级别.
  3. 类别的数量很少(目前为 5 个),不太可能经常更改,但绝不是绝对固定的。
  4. 升级所需的点数因级别而异,可能由公式或查找表决定。

因此,挑战在于跟踪每个用户在每个类别中迈向下一级别的进度。我想到了一些可能的方法:

可能的解决方案

  1. 在用户表中为每个类别添加一列,并在每次用户升级时将它们全部重置为零。
  2. 有一个单独的UserProgress 表,每个用户的每个类别都有一行,以及他们拥有的点数。 (基本上是 #1 的多对多版本。)
  3. userLevel 列添加到UserTasks 表中,并使用它通过某种SUM 语句推导出进度。

他们当前的级别将是 User 表中的一个简单 int。

优点和缺点

(1) 似乎是迄今为止最简单的,但它也是最不灵活的。也许我可以使用基于类别 ID 的命名约定来帮助克服其中的一些问题。 (使用“select cats; for each cat, get the value from Users.progress_{cat.id}”之类的代码。)这也是我丢失数据最多的地方——我不知道哪些点数计入升级。我没有这个需要,所以也许我不在乎。

(2) 看起来很复杂:每次我添加或减去一个用户或一个类别时,我都必须维护另一个表。我预见到同步挑战。

(3) 介于两者之间——比 #2 更清晰,但不如 #1 直观。为了找出用户的位置,我会使用稍微复杂的 SQL,例如:

SELECT categoryId, SUM(points) from UserTasks WHERE userId={user.id} & countsTowardLevel={user.level} groupBy categoryId

嗯……这似乎还不错。我想我在这里是在谈论自己进入#3,但我会喜欢任何意见、建议或其他想法。

【问题讨论】:

  • 是的,就像我在那边说的:我记得在我把它贴在这里之后就存在了。但坦率地说,我宁愿把它关在那里而不是在这里。这个社区的规模是这个社区的 1/100,这个问题当然足够普遍,可以适用。无论如何,如果我没有得到任何答案,我不会感到惊讶:这个问题太长了,我几乎在最后回答了它。我们拭目以待......
  • 祝你的游戏好运!计划这些事情总是那么有趣。

标签: database-design


【解决方案1】:

我会投票给 3 号。

只要我可以聚合现有数据而不是单独存储“运行总计”,我就会抓住这个机会。对于像 StackOverflow 这样的大型网站,由于性能原因,这可能不可行,但对于中小型网页游戏,它应该可以完美运行。

通过避免保持“运行总数”,您通常可以避免不得不在多个地方执行相同(或类似)的操作。举一个非常简单的例子,在论坛中,如果手动更新post_count 而不是计算为COUNT,那么删除帖子需要更新post_count。您遇到的这种情况越多,您就越有可能出现错误或“WTF?”为您的游戏玩家注意到两个或多个不完全相加的数字的时刻。

除了表单性能之外,使用简单聚合的一个主要缺点是您有时希望现有总计受到所做更改的影响。我从来没有遇到过这样的案例,但我确信它们存在。

【讨论】:

    【解决方案2】:

    我绝对不会选择 1。我想提供第 4 种方法。

    如果我理解正确,用户需要在给定类别/级别中获得 5 分才能访问下一个类别,但在那里总共可以获得 10 分,其中额外的 5 分不计入下一个类别类别。最简单的方法是制作这样的表格:

    | user_id | category_id | score |   (primary key = user_id, category_id)
    

    不要害怕存储总分,如果“从 user_id = ? 和 category_id = ? 的表中选择分数”,您可以检查查找表/公式够高了。

    这样您的查询非常简单,数据库设计非常简单且可扩展(添加新类别或更改评分没有问题)。

    如果您想在以后结转分数,只需使用 sql 的 sum 函数获取用户的总分,然后将其减去所需的总分到给定类别。

    【讨论】:

    • 这听起来有点像我的#2,但我不明白的是,如果他们有六个pt,并且每个级别需要五个,我不知道第六个pt是不是超过 1 级,或计入 2 级,除非我在每次升级时重置所有值。
    • 啊,所以你做超车点,在这种情况下,而不是阶段存储每个级别的积分,然后你会得到:第 1 阶段有 lvl1、2、3 和 4。要完成第 1 阶段,玩家需要至少15分。因此,您可以在数据库中查询 stage1、2、3、4 的总和点,如果 > 15 则解锁第 2 阶段。
    • 我没有舞台。我有级别和类别。我不确定您是否建议我也添加阶段,或者只是使用不同的术语。无论如何,我选择了我的#3。它似乎工作得很好,但无论如何感谢您的帮助。
    • 嘿,我的解决方案实际上接近#3,我想你会很好的!祝你的网络游戏好运!
    • 哇,你的意思是会有类别 id 名称分数并将其链接到用户表并添加每个用户的总分,因此表中会有很多类别 id 你现在如何保存这些或在 json 中您将如何通过积分或分数来对您的用户进行分级?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-22
    • 2011-07-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多