数据库设计帮助游戏/用户级别/进度

时间:2011-01-29 19:52:43

标签: database-design

对不起,这很长,所有的散文。我正在创建我的第一个真正游戏化的Web应用程序,可以使用一些帮助来思考如何构建数据。

设置

用户需要先完成几个类别中的任务才能升级。我有UsersTasksCategories表,以及一个加入三个表的UserTasks表。 (“用户3在类别8中添加了任务42。现在他们已经完成了它。”)这一切都很好并且工作得非常好。

挑战

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

  1. 您必须在每个类别中获得一定数量的积分才能向上移动。
  2. 如果您获得了Cat 8所需的分数,但仍有其他工作要做,以完成该等级,任何新的Cat 8分都计入您的总分,但不要“翻身”到下一个级别
  3. 类别数量很少(目前为五个)且不太可能经常变化,但绝不是绝对固定的。
  4. 升级所需的点数会因每个级别而异,可能是公式或查找表。
  5. 因此,挑战在于跟踪每个用户在每个类别中向下一级别的进度。我想到了一些潜在的方法:

    可能的解决方案

    1. 为每个类别的users表添加一列,并在每次用户升级时将它们全部重置为零。
    2. 有一个单独的UserProgress表,每个用户的每个类别都有一行,以及它们拥有的点数。 (基本上是#1的多对多版本。)
    3. userLevel列添加到UserTasks表,并使用该列通过某种SUM语句推导出它们的进度。
    4. 他们当前的级别将是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,但我会喜欢任何意见,建议或其他想法。

2 个答案:

答案 0 :(得分:1)

我将投票给第3名。

任何时候我都可以聚合现有数据而不是单独存储“运行总计”,我抓住机会。对于像StackOverflow这样的大型网站,由于性能原因,这可能是不可行的,但对于中小型网络游戏,它应该可以很好地工作。

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

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

答案 1 :(得分:0)

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

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

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

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

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

如果您希望在以后的某个日期使用分数,只需使用sql的sum函数来获取用户的总分,然后将其与所需的总计分数相比较,并将其减去给定的分类。