多人/单人测验游戏的数据库设计

Posted

技术标签:

【中文标题】多人/单人测验游戏的数据库设计【英文标题】:Database Design for a Multiplayer/Single Quiz game 【发布时间】:2019-06-08 09:56:44 【问题描述】:

我在这里看到了很多问题,但没有一个适合我的问题。我正在尝试创建一个可扩展的 ER 模型,如果我想添加更多数据,几乎不会破坏任何东西,所以我试图创建的是:

有两种类型的用户,比如说 Admin 和 Worker,他们有不同的角色。

管理员可以对问题进行 CRUD,也可以创建一个用户可以加入一起玩的房间(这只是一个名称,就像 Kahoot!一样),但在内部创建更多属性可能是个好主意就像,谁在这个房间里玩,给每个人点,但等我给你看设计后再说吧。

好吧,在我的设计中,我有:

表用户包含:

_id
username
password
date_creation

这是一个默认值,但是我想知道如果角色是管理员或工作人员,我该如何定义角色,比如 isAdmin:true 然后我检查这个布尔值?或者我可以创建另一个角色表并将其连接到用户表?

但也许我必须为两者创建一个表,我的意思是有一个管理员,它有一个密码和一些功能,然后是用户 Worker,它有另一个密码和另一个功能。

然后我想要问题表,其中包含:

_id
question_name
answers[1,2,3,4]
correctAnswer or answers because it can be multi option chooser
topic
isExamQuestion
dificulty

那么 Room 表应该包含:

_id
name
capacity
type (game can be as a group or solo) that's why this attribute
exam (This should be a flag to know if this question is for an exam or not (It can be for EXAM or PRACTISE)
ranking (This is the top X from 1 to X)
don't think if I have to add the winner here because if I get the position 0 from ranking I get the winner...

还有一个名为 Topic 的表格,如果我的问题有一个主题,那么我可以按主题选择问题。主题的示例应该是数学,因此用户只能进行考试或使用数学问题进行测试。

_id
Name
Questions[...]
Then I have to store like a historic about what are the questions worker has answered correct and what did not, to make some statistics, but I need to store some historicals for Admin to see in this topic the average that Workers have failed more is : Question23 (for instance) something like that.

我缺少什么,你能帮我弄清楚如何让这个设计更好吗?

注意:我将 Spring 用于服务器端,Angular 用于前端,android 用于应用程序,但我可以更改任何内容以更快/更好地使用此数据库。

编辑

如果您需要更多详细信息并且我的解释有误,请按照游戏流程进行。

管理流程

    创建问题(使用不同类型的答案,如真/假、复选框(单答案和多答案)、文本等...) 创建一个工人可以加入的“游戏”(这主要是编程的东西),但它应该是一个带有属性的房间,比如房间的 id、maxNumber、类型(考试)和存储历史记录,还有一个类型游戏(例如,图像、视频等) 查看有关 Worker 的统计数据,这意味着查看他们回答正确、失败的答案数量,查看每个主题(这类似于连接之类的东西,但设计必须做得很好) 查看他之前参加的考试的历史记录以及所有信息(参与者、分数、时间、资料)

而Worker流程是

他可以练习意味着他随机或按主题回答问题(每个答案都应保存以供统计,以避免重复他回答正确的答案),他也可以进行考试(不是多人游戏),这只是管理员可以选择的选项检查问题是否是考试的一部分。

然后房间的东西,他可以加入Id。

如果您需要进一步说明,请告诉我,我会尽快回复您。

【问题讨论】:

“更好”是什么样的?快点?更容易编码?更容易改变? 您好@NevilleKuyt 感谢您的关注,是的,从一开始我就有类似于MaximFedorov answer 的东西,我正在寻找另一种可能的解决方案,它可以让我更具可扩展性意味着如果我想添加更多的东西我不需要改变很多表。 【参考方案1】:

实际上,您的系统具有三个逻辑部分(模块):

users 模块,包含用户数据并实现用户操作的身份验证和授权 问卷模块,包括问题和答案的管理 问卷历史模块,包含每个用户的历史记录

这些模块的数据库设计如下

用户模块:

角色 - 包含系统中的用户角色

id - 角色的唯一标识符 name - 角色名称,例如admin、worker等

用户 - 包含用户和分配给他们的角色信息

id - 用户的唯一标识符 用户名 密码 role_id - 角色分配给用户的标识符

问卷调查模块:

主题 - 包含问题主题

id - 主题的唯一标识符 name - 主题的名称

问题 - 包含问题

id - 问题的唯一标识符 topic_id - 问题的主题标识符 文本 - 问题的内容 is_exam_question - 考试题与否 type - 答案类型(布尔值、复选框等) 难度

answer - 包含所有问题的答案

id - 答案的唯一标识符 question_id - 包含答案的问题的标识符 文本 - 问题的内容 is_correct - 表示答案为真或假的标志

房间 - 包含房间信息

id - 朗姆酒的唯一标识符 name - 朗姆酒的名称 容量 - 可以加入房间的最大工人数 类型 - 房间类型:团体、单人或等等。 learning_type - 房间类型:考试、练习等

user_in_room - 包含有关加入房间的用户的信息

user_id - 加入房间的用户的标识符 room_id - 房间标识符 score - 房间内用户的当前分数

历史模块:

user_question_history - 包含有关用户回答的问题的信息

user_id - 用户的标识符 room_id - 用户回答问题的房间的标识符 question_id - 用户回答的问题的标识符 score - 用户按问题得分

user_answer_history - 包含有关用户选择的答案的信息

user_id - 用户的标识符 room_id - 用户回答问题的房间的标识符 question_id - 用户回答的问题的标识符 answer_id - 用户选择的答案的标识符

使用此架构可以构建不同的报告。比如可以按房间显示所有用户的结果

SELECT r.id,
    r.name,
    u.username,
    ur.score
FROM room as r
LEFT JOIN user_in_room as ur ON ur.room_id = r.id
LEFT JOIN user as u ON u.id = ur.user_id
WHERE r.id = <id>

或者你可以查看用户回答的详细信息

SELECT 
    q.text,
    a.text
FROM user_in_room as ur ON ur.room_id = r.id
LEFT JOIN user_question_history as uqh ON ugh.user_id = ur.user_id AND ugh.root_id = ur.room_id
LEFT JOIN question as q ON q.id = ugh.question_id
LEFT JOIN user_answer_history as uah ON uah.user_id = ugh.user_id AND uah.room_id = ugh.room_id AND uah.question_id = ugh.question_id
LEFT JOIN answer as a ON a.id = uah.answer_id
WHERE ur.room_id = <id> AND ur.user_id = <id>

【讨论】:

感谢您的回答,我正在等待更多建议,但我想知道例如如何获取房间的历史记录? @Skizo-ozᴉʞS 历史记录应该包含哪些数据? 假设你是一名老师,然后你做了一个考试,10天前你想再检查一次,那么你想在那里看到什么?像数据一样,有多少学生参与,笔记,每个学生对每个问题的回答等等......这就是我的意思,但我想知道这是否是关于数据库设计的连接和东西...... @Skizo-ozᴉʞS 我在答案中附加了几个查询 太棒了,让我看看并深入了解是否缺少某些东西,感谢您抽出宝贵时间 Maxim :D【参考方案2】:

老实说,如果您确定只需要可能的类型(现在和将来),用户表中的简单 bool isAdmin 就可以很好地工作。管理员所做的所有其他事情都可以从编程方面处理。无需堵塞您的数据库。

也就是说,如果将来您有其他类型的用户的可能性很小,Maxim 的答案就是要走的路。这样,添加另一个角色,例如“编辑”,就像在“角色”表中添加一条记录一样简单。实际上,添加 1000 个新类型的用户就像在“角色”表中添加记录一样简单。因为您已经有一个要查找该角色的表,所以您的代码不必担心所有可能的用户类型(如果您有很多用户,这会很痛苦),只需担心它需要的那些。数据库正在处理其余部分。

Maxim 的答案的一个缺点是在数据库中实现需要更多的工作,并且查看/更新用户角色需要更多的工作。

要在数据库中实现,您需要创建一个完整的额外表并确保它正确链接。这并不难,但是,特别是如果您是 dbs 新手,这可能是对您来说不值得的额外工作。这也意味着,从维护方面来看,您有另一个表可以密切关注。没什么大不了的,但还是要考虑一些事情。

从代码方面来看,这也会产生额外的琐事。一方面,用户类型不再直接在您的用户表中——ID 是。这意味着当您想知道用户类型的名称时,您必须 a) 根据您拥有的 ID 查询该用户类型的数据库,或者 b) 加入 2 个表,这有时会很棘手。更新角色也有类似的杂务。

同样,这些都不是大问题,只是需要考虑的事情。如果您只有两种可能的选择,那么额外的工作可能不值得。

因此,简而言之,布尔值可以工作并且易于实现,但不可扩展。马克西姆的答案是相当可扩展的,并且使未来的扩展更容易,但实施和维护有点困难。您必须根据自己的喜好做出决定。

【讨论】:

更难。不是太难。要实现,您需要创建一个完整的其他表(“角色”)并正确链接它等等。然后,每次您想知道用户的角色或更新用户的角色时,您都必须将表连接在一起。这不是太难,每次只是和额外的步骤。我会更新我的答案。【参考方案3】:

您需要一个Profile 表和one-to-manyUser 表,这样如果您想申请另一个权限,只需添加新的个人资料条目:

User表:

Id
Username
Fullname
Profile_id
...

Profile表:

Id
Name
Description

ExamQuestion 表与many-to-many 相关,要打破它,您将拥有第三个表Question_Exam

Question_Exam:

 id_exam
 Id_Question
 Answer(provided)
 Id_user(taking the exam)
 IsCorrect(boolean, to avoid farther queries )
 date

TopicQuestionone-to-many

Question表:

 Id
 Name
 Answer(The correct one)
 Id_topic

其他结构没问题。

【讨论】:

以上是关于多人/单人测验游戏的数据库设计的主要内容,如果未能解决你的问题,请参考以下文章

服务端构架干货:快节奏多人游戏的技术实现

两年游戏经历

JAVA面向对象编程课程设计——多人扫雷对战

Java多人博客系统-2.0版本

大型多人在线游戏服务器架构设计

XMPP 多人游戏功能 - 设计问题