OO与简洁性在用户交互方面的比较

9
作为一个暑假项目,我想在大学休息期间制作一个大富翁游戏。然而,这个问题更多的是关于问题的一般思路,而不是我正在尝试完成的具体任务。
我决定采用自下而上的方法进行构建,首先只创建一个四十个空间的棋盘并围绕它进行移动,然后再转移到与空间交互。我意识到我对最佳处理方式很不确定,并且我在两种设计思路之间犹豫:
1. 给每个空间都分配一个对象,所有子类都是Space对象,因此可以通过空间对象本身来定义交互。我可以通过为每种类型的空间实现不同的land()方法来实现这一点。 2. 只给属性和公共设施(因为每个属性都有独特的功能)对象,并在程序的主类(或我称之为Board)中创建处理购买/租赁等的方法。像“go”和“super tax”这样的空间可以通过一小组条件语句来实现,以检查玩家是否在特殊的空间上。
选项1显然是面向对象的(我觉得是正确的)方法,但我希望只需要从程序的主类处理用户交互。换句话说,我不希望空间对象与玩家进行交互。为什么?呃,到目前为止我所编写的许多代码都具有这种简单性,但我不确定对于更大的项目来说,这是否是一种幻想。我真的应该在一个完全分离的类中处理用户交互吗?
正如你所看到的,我对这种情况感到相当困惑。有没有什么方法可以解决这个问题?还有,有没有任何关于实际面向对象设计的建议,可以帮助解决这个问题?
编辑:我只想指出,我觉得我在这个问题上失去了一点重心。我对将OO和任何外部操作(命令行、网络、GUI、文件管理等)结合起来的一般方法感兴趣。

谢谢。所有这些答案都非常好。只是真的需要听听其他人的想法。再次感谢。 - seadowg
1
只是一个观察:垄断游戏实现起来相当棘手 - 规则是一大堆特例。与其他游戏相比,没有任何解决方案会非常简单或优雅。 - Michael Borgwardt
7个回答

5

我认为选项#1更好。

至于“用户交互” - 这要看情况。你可以将一些代码保留在另一个类中。例如,

// in main class
user.landOn(space);
if (space.containsProperties()) doSomething(); // Option #1 for some user-interaction code

// in User.java
public void landOn(Space s) {
    // do some checks
    s.land(this);
    if (s.containsProperties()) {...} // Option #2
    // something else?
}

// in GetMoneySpace.java
@Override
public void land(User u) {
    u.awardCash(200);
    // Option #3 - no properties so nothing here
}

这比像那样的东西更符合面向对象编程(在我看来更好),

if (space.isCashAwardSpace()) {
    user.awardCash(space.getAward());
}
if (user.something()) doSomething(); // Some user-interaction code

+1,好的实例展示了访问者模式,却没有明确地命名它 :-) - Vincent Robert

5
最终决定权在你手中。这就是面向对象编程的优美之处,因为它可以有不同的解释。虽然一些模式通常应该遵循,但总体上,你可以自行决定如何处理。
然而,你应该仔细考虑系统中每个角色应该了解哪些信息。一个属性是否真的需要知道玩家、他的账户余额和其他玩家的情况?可能不需要。一个属性应该知道它的成本、租金等等。
另一方面,主要游戏线程是否应该关心支付租金等琐事?也许不应该。它的主要关注点应该是游戏本身的状态,例如掷骰子、每个玩家是否想交易或购买或抵押/赎回等。
想一想落在一个方格上的动作。一旦落地,玩家有三个选择:
1.购买该物业
2.忽略该物业
3.支付租金
那么,系统中哪个角色知道完成此操作所需的所有信息呢?我们有游戏类,它不关心这样的琐事。我们有属性类,它并不真正关心玩家。但是玩家对象知道所有这些信息。它记录了每个玩家拥有的物品,并且可以轻松访问正确的数据。
因此,如果是我,我会创建一个Player.performMove(Die d)方法。它可以轻松访问账户。这也可以在类之间实现最少耦合。
但最终决定权在你手中。我相信人们已经用完美的面向对象、函数式或过程化语言创建了大富翁克隆版。最终,使用你所知道的,并不断重构,直到你对最终设计感到满意即可。

1

采用第一种设计方案。您可以创建一个Property类,并将特殊属性作为子类,覆盖默认行为。

至于交互,您可以创建一个Token类,并在棋盘上移动该实例。您需要给用户一些选项,但是是的,根据响应,您应该调用对象上的方法,而不是将复杂逻辑放入用户事件中。

示例类:

  • Property
    • 名称
    • 价格
    • 基础租金
    • 房屋数量
    • 酒店数量
    • 抵押
    • getCurrentRent()
  • RailRoad扩展Property
  • Utility扩展Property
  • Board
    • 属性
  • User
    • 令牌
    • 玩家名称
    • 当前属性
    • 拥有的属性
    • 购买物业()
    • 支付物业租金()
    • 抵押物业()
    • 移动()

1

我不完全确定我是否正确理解了它。在设计软件时,您总是有这样的选择。我个人会选择第一种选择。一个论点是我对小游戏(Scrabble)的个人经验,这向我证明了即使对于较小的项目,良好的设计也很重要。面向对象编程的重点在于您可以以不同的方式思考您的设计,并获得一些设计优势。例如,想象一下添加新字段、更改现有字段、在多个字段中重用一个字段的行为将是多么困难。


1

我会选择你的第一种方法。它将行为封装在需要的地方。因此,您将为Utilities、Properties、GotoJail、FreeParking等不同类别的空间创建Space子类。一个类别的共同行为是将其分组。

您的属性空间本身可能具有组对象作为成员,例如将所有深蓝色属性分组在一起。

至于与用户的交互,您将向每个空间传递一个Board(或更好的GameController)实例,以便它知道自己属于哪个游戏并可以影响游戏。然后,Space可以在板上调用特定的操作,例如移动棋子、向用户提问等。主要的一点是有分离——用户交互不发生在每个空间内——但是允许空间请求发生某些交互或移动棋子。由您的GameController实际执行交互或移动棋子等操作。这种分离使得测试变得容易,并且可以根据需要提供替代实现(例如,在不同版本/国家中使用不同的游戏规则?)


0

选项2并不是很有意义,或者至少对我来说不如选项1清晰。使用选项1,您不需要在您的空间对象内处理用户交互。您可以在主类或专门用于处理用户交互的单独类中处理它:

public void move(Player p, int spaces){
    Space landingSpace = board.getLandingSpace(p,spaces);
    landingSpace.land(p); //apply your logic here
}

正如您所看到的,Space类负责检查打算降落在该空间上的Player p。它应用任何自定义逻辑,检查它是否有足够的钱,是否是玩家拥有的东西等。每个Space子类都将有其自己的规则,就像您在选项1中描述的那样。

0
面向对象设计的一部分目的是简化解决方案空间中问题的表示(即,在计算机中建模系统)。在这种情况下,考虑对象之间的关系。在一个 Space 中是否有足够的功能来使其成为一个抽象类,还是由于两者的独特特征,让其成为不相关的 Property 和 Utility 类更有意义?Property 是 Space 的一种特殊类型还是仅仅是 Space 中的一个字段?这些都是您在设计游戏时可能需要应对的问题。

就交互而言,当你有一个 'god class' 来完成所有工作并仅向其他类请求信息时,这通常对设计来说是个坏消息。有很多陷入这种情况的方法;判断你是否正在处理一个 god class 的一种方法是查找包括 ManagerSystem 的类名。因此,最好不要有某种“游戏管理器”来请求所有其他对象的数据、进行所有更改并跟踪所有内容。尽可能消除这些问题。

God类违反了封装的概念,这不仅涉及数据隐藏(虽然这是其中很大一部分)。良好的封装意味着相关方法和数据是单个对象的一部分。例如,属性不需要向其所有者发出请求,因此包含对Player的引用的字段可能会违反封装。其中一些封装违规根本不明显,很难发现。在设计对象时,请尝试确定需要与外部对象共享的关于对象的最小信息量。删除任何不必要的内容。

你可以以许多方式进行这项工作,但我的设计可能是这样的(迭代肯定可以证明它是错误的):

  • Space类包含所有空间共有的基本数据和方法(例如它们在棋盘上的位置,是否被占用等)。
  • 子类从最常见的(PropertyUtility)到最独特的(GoJailFreeParking等;可能是单例),每个子类都有与之相关的字段和方法。
  • Player类包含玩家信息。
  • GameState类关注游戏状态;轮到谁了,银行里还剩下多少房子等等。

祝你在游戏和学习中好运。

当然,Google是你的朋友,但这里是我推荐阅读的一些内容:


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