什么是为文字冒险游戏存储区域数据的最佳方式?

5
我正在使用C#开发一个“Zork”风格的文字冒险游戏,它将有相当多的不同区域和描述以及环境修饰符。除非数据库确实是最佳方式,否则我不想使用数据库。
我需要关于存储/加载这些数据的最佳方法的建议。
它将包括:
- 区域描述 - 环境修饰符(窗户打开/破损,门关闭) - 默认情况下存在的物品

有些“数据库”比其他的更轻,sqlite这样的东西不适合您有什么原因吗? - Textmode
8个回答

13

我会建议你放弃使用C#,改用Inform7来编写程序。Inform7是我曾经见过的最令人惊叹的编程语言,而且它专门设计用于解决您的问题。

关于Inform7最棒的事情在于,你可以使用类似文本冒险游戏的语言来编写自己的文本冒险游戏。例如,这是一个示例冒险游戏源代码的片段:

The iron-barred gate is a door. 
"An iron-barred gate leads [gate direction]." 
It is north of the Drawbridge and south of the Entrance Hall. 
It is closed and openable. 
Before entering the castle, try entering the gate instead. 
Before going inside in the Drawbridge, try going north instead. 
Understand "door" as the gate.

这将向游戏中添加一个对象——门,这个门被称为“铁栅栏大门”。门被理解为连接两个房间,在这种情况下是吊桥和入口大厅。如果玩家尝试“进入吊桥”,那么游戏逻辑会知道这与“向北走”相同,然后门的逻辑将确定门是否关闭等等。这使得编写文本冒险游戏变得非常容易。

您有特别的原因想要使用C#而不是像Inform7这样的领域特定语言吗?如果您的目标是学习如何编写C#代码或构建解析器等,那么请自行进行。如果您的目标是编写文本冒险游戏,那么我建议使用专为此设计的语言。


1
取决于你写它的目的。如果你想学习如何构建一个文本冒险游戏来自学,那么这并不是很相关。不过,它确实是一个很棒的工具。 - Rushyo
我知道这已经过时了,但是我还是想说一下我的看法。使用像这样的工具构建文本冒险游戏似乎很廉价且受限制。你并没有真正制作游戏,而只是在改变别人的游戏。这会带来一个问题,如果你想做一些超出Inform7允许范围之外的事情,那就太遗憾了。我并不是说没有人应该使用这个工具,但是如果你自己编写代码,你将会学到更多,并且同时制作出更好的游戏。 - rshea0
7
你是在谈论你了解的事情,还是只是发表一个无知的观点?如果你不了解,那么你确实应该看看在Inform7中可实现的广泛行为深度。它绝对不会限制你,而且廉价就是好。如果你的目标是学习C#编程中的冒险游戏,那么请务必使用C#构建自己的系统。如果你的目标是编写冒险游戏,那么请使用最好的可用工具来编写冒险游戏。如果你喜欢航行,那么不要建造船只。去航行吧! - Eric Lippert
4
@ryansworld10: 嗯,那很好,但让我们来扮演魔鬼的代言人吧:为什么要使用[插入你所使用的编程语言],而不是使用[在此处插入更低级别的编程语言]? 每一种高级语言都是由做出关于什么易于处理和什么难以处理的折衷的人设计的。 - Eric Lippert
1
@ryansworld10。Inform7具有完全足够的命令结构,如果情况变得更糟,您可以切换到i6并在其中编码。而且,在Inform7扩展页面上已经列出了一个RPG框架。(别误会,我认为i7很糟糕,但它绝不是无能的) - Textmode
显示剩余2条评论

7
将所有数据序列化到文件中。这将确保在用户安装游戏时占用最小的空间,没有任何真正的劣势。当你有大量数据时,数据库是很好的选择,但是你要考虑一个文本冒险游戏,其中你需要将整个游戏内容加载到内存中。一个简单的文件将非常适合这个需求。
注意,我不是在谈论xml,而是二进制序列化。任何类型的文本序列化都会允许用户查看你的数据,并作弊或破解游戏。无论是文本还是二进制,你都可以轻松地交换/替换序列化数据文件。记住,你的整个“文本”可能只有几百千字节。

其实那是个好计划,二进制序列化。我不知道为什么我没想到。 - Liggi
不禁感到有点委屈,在此之前已经建议过了...啊,算了。 - Rushyo
抱歉Rushyo,如果你先提出了建议。我并没有真正理解你在回答中所说的话。 - Liggi
说实话,你对“如何存储数据”的回答是:“嗯,我想那完全取决于个人主观看法 - 不是一个有效的问题。”。 - Kirk Broadhurst
不,我对问题的另一种解释的回答已经在上面了。我在答案部分给出的实际答案与那无关。请在引用我的话之前考虑上下文。 - Rushyo

2

1

我知道你不希望使用数据库,但是你看过SQL Server Compact Edition了吗?它可能正好可以满足你的需求。


有没有办法防止任何人查看数据库?可能是个愚蠢的问题。 - Liggi
那是完全不同的问题...我会说,最终答案是否定的。如果数据存储在客户端机器上,无论你采取什么编码/加密/保护措施,你的应用程序都需要访问这些数据,因此一个有决心的用户也可以这样做。虽然相比XML序列化来说,这可能会更棘手一些。 - spender
如果数据最终存储在他们的计算机上,那么阻止他们读取数据就是不可能的 - 因为如果他们的计算机可以读取数据,那么他们也可以读取 :) - Rushyo

0

将您的冒险脚本化为一个大文本文件,听起来怎么样?然后让您的应用程序解析此文件,在类中构建冒险并从那里运行?

这意味着您可以使用简单的文本编辑器编辑冒险。我想象当多个决策可以从单个源中进行时,可能会变得棘手难以可视化链接。但是,在没有一些专门的前端的情况下,这在数据库中也很棘手。

更新:

或者您考虑过XML吗?

<area id="DarkRoom1">
  <description>Dark Room</description>
  <item>Bucket</item>
  <item>Spade</item>
</area>

然后使用它来填充内存中的类。


0
我认为C#为您提供了恰到好处的工具。只需将您的结构封装成类即可。我们在大学里的第一个面向对象编程项目就是这个问题!这是面向对象编程的完美案例研究。
然后,您可以使用C#的许多序列化方法来以任何您认为合适的方式进行持久化存储(加载/保存)。

1
但问题也在于“存储在哪里”,将结构封装在_classes_中并没有说明在实例化_objects_之前,将填充_objects_的数据存储在哪里。 - Rune FS
1
我想这完全是主观的 - 并不是一个有效的问题。一个平面文本文件?这并不重要。它不会成为一个瓶颈,也没有正确答案。只需以任何你认为合适的方式进行存储即可。个人而言,我倾向于为我开发的每个游戏发明一个新格式,并针对问题使用适当的语义。一旦它们被创建,序列化和反序列化就可以在未来检索它们。 - Rushyo
1
@Filburt 是的,OP正在寻求建议。 - Rune FS
1
除了当然接受的答案确切地做到了我建议你做的事情,解释了如何序列化,使用哪种格式和存储类型,并解释了原因。 - Rune FS
它仍然不重要。如果您愿意,可以将其存储在自己的自定义文件类型中,使用自己的自定义文档格式,在自己的自定义文件系统中进行存储,这并没有实际区别。在此上下文中,这些方法之间没有明显的区别。结构仅在程序内部有影响。这就是串行化的全部意义! - Rushyo
显示剩余3条评论

0

你可以将数据存储在文件系统中(zip文件或文件夹)。

每个选项都可以存储为一个文件夹,而所有描述、修饰符和其他数据都可以存储为文本文件(XML?)。当用户做出决定时,您可以进入相应的文件夹并按照情节进行操作。

例如:

你想要:

  • 打开门(door)
  • 离开(leave)

如果用户选择打开门,您就会进入门文件夹,并从该文件夹中的数据文件中读取数据。

优点:

  • 简单易懂
  • 不需要数据库
  • 容易添加新的冒险故事

缺点:

  • 回滚决策存在问题(返回到起点或情节的某个特定点)

0
个人而言,在这种情况下,我会避免使用数据库,而是选择文本文件格式(可能是两个不同的文件,一个用于初始状态(如地形等),永远不会被修改,另一个用于在游戏过程中要修改的状态(如破碎的窗户等);或者将整个内容分成每个区域的一对静态/动态数据)。
原因如下:
  • 文本文件可读性强,因此您可以创建内容而无需专用编辑器,而使用数据库方法,则必须通过查询输入数据,或编写关卡编辑器
  • 假设是单人游戏场景,那么并发不是问题
  • 保存游戏是将修改后的状态文件复制到保存游戏文件夹中,或将它们打包成单个文件的问题
  • 您可以轻松嵌入脚本
  • 您正在处理的数据结构可能足够简单,以至于数据完整性不是严重问题

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接