【问题标题】:Looking for a good design pattern for this set of objects为这组对象寻找一个好的设计模式
【发布时间】:2010-10-17 15:15:45
【问题描述】:

我最初在programmers.stackexchange.com 上询问this question,因为我认为对于stackoverflow 来说答案过于主观。但是,在 cmets Muad'Dib 中指出了这一点:

这可能更适合 StackOverflow ... 这是一个直接与编程问题相关的问题,并讨论编程解决方案。一种解决方案可能与另一种解决方案相同,其中它们之间的选择是主观的,但对整体问题本身的讨论并不是因为某些解决方案显然不适用。所以这个问题确实有一个或几个好的答案,而诸如“哪个是最好的文本编辑器?”之类的问题。没有……

所以,在考虑了更多情况之后(并查看了一些似乎不适合的模式),这是我的困境:

设置

我正在设计一个简单的战斗策略游戏。

  1. 两个战斗人员在一定时间内互相攻击。
  2. 获胜者是时间结束后最健康的人。
  3. 在战斗中玩家没有直接干预。玩家在战斗前为他们的战斗人员定义了一些策略,而“AI”(宽松的术语)决定了战斗人员会做什么。
  4. 战斗由一个“滴答”秒的任意计时器组成,战斗人员的攻击速度(除其他外)决定了他们做某事的频率。
  5. 除了战斗对象之外,还有一个“天气”对象可以对战斗人员的能力产生一些随机的环境影响。
  6. 整个过程每秒钟循环一次,确定并执行环境影响和攻击,并全部记录下来,然后将日志作为逐个播放显示给用户。

问题

我不确定哪种设计模式最能帮助我完成上述任务。我正在寻找一种模式,可以让我增加“战斗”的复杂性。可能是通过在战斗中添加更多对象(更多的战斗人员,可能是一个新的环境对象等)

起初我认为观察者模式会起作用。我会有一个代表“观察者/主题”的战斗对象。它跟踪一个计时器,随着计时器的增加,它会更新所有参与者观察者对象。但是,很多防御方战斗人员的参数会影响攻击方战斗人员的行动,因此该场景中的“观察者”需要相互了解,因此我不确定这是否正确。

最后,我并不是要完美地确定设计模式。也许没有“最合适的”。我只是在寻找一个坚实的基础。

【问题讨论】:

  • 不确定您是否只使用一个 DP 来管理游戏。 DP 可能会帮助您解决在编写代码时出现的一些问题。例如,我可以看到#3“定义一些策略”将与策略模式一起使用;)
  • 是的,战斗对象将使用策略模式和状态模式的组合。我感兴趣的是战斗的整体“管理”。

标签: design-patterns language-agnostic


【解决方案1】:

试图为相当详细的情况找到一个“正确”的设计模式是徒劳的。设计模式解决了在特定编程语言中出现的某些常见的低级情况 - 您可能会发现的每种可能情况都不一定存在特定的情况,您也不一定只使用一个来解决您的问题问题。

特别是这种情况并不是设计模式的真正用途 - 设计模式主要关注类和对象之间的静态关系,而您在这里谈论的本质上是算法。设计模式提供了实现算法的方法,但它们本身并不是真正的算法。

这应该很简单。您有一个运行指定持续时间的 while 循环。每次迭代代表一秒的经过时间,并且在该迭代中,它将调用战斗中涉及的每个相关对象的一个​​或多个方法 - 战斗人员、天气等。(有多少方法,哪些是一个游戏设计问题,而不是(还)编程问题。)如果您愿意,这些对象可以来自包含整个上下文的战斗对象。

这里并没有真正需要观察者模式,事实上,如果将其从易于理解的迭代过程更改为事件驱动的过程,这会使事情变得非常复杂。如果需要访问各种属性,战斗员可以直接查询另一个战斗员。

【讨论】:

  • +1 表示“试图找到‘正确’的设计模式是徒劳的。”
  • 我不同意。我认为看看是否有适合您问题的设计模式是个好主意。如果有那么好,使用它。如果没有,请不要尝试将您的问题压缩成一种模式。
  • 我同意有时手头的问题存在某种模式。我不同意的是这个问题中的假设,即每个问题都有“一个”模式,而设计模式并不能完全解决制作软件时可能出现的所有问题。我将尝试编辑此答案以更清楚地表达这一点。
  • 感谢您回答我的问题。但是,您为了什么目的而谴责对设计模式的追求?你读过我询问的最后一句话吗? “假设......每个问题都有'a'模式”在哪里? 因为我没有掌握模式,我觉得有必要去寻找一个。在实现我自己的解决方案之前,我是否不应该发现我的“低级情况”是否已经被模式简洁地解决了?你的建议是不必要的反建制——或者你没有完全阅读我的问题。无论哪种方式,你的自我膨胀似乎都是为了扼杀自我教育。
  • 斯蒂芬,你误解了设计模式的目的。它们不存在解决应用程序设计问题或这样的算法问题。它们的存在是为了克服在编程语言中表达某些低级概念的特定低级问题。我根本不是反设计模式——只是他们解决的问题不是你的问题。
【解决方案2】:

如果您真的想在这里使用模式,我会考虑使用命令模式。 例如,您可以将一串“战斗动作”命令排成队列,以便在一段时间内执行。您还可以根据对手的行为轻松而通用地轻松取消命令。在您开发游戏时,您可以轻松地为此添加动作/策略。

但这并不是整个游戏的模式,它更像是它的一个方面的解决方案。

【讨论】:

  • 最终我使用了几种模式的组合,但对于手头的主要任务,我实现了一个命令模式。
【解决方案3】:

嗯,一切都可以通过对象建模:)

假设您不需要“真实”秒数 - 您可以计算整个战斗,将每个步骤保存在日志中,将日志保存在数据库中的某个位置,然后每秒向玩家显示一条“线”日志。您的日志不仅可以是字符串,还可以包含“此时”的序列化战斗人员数据,因此您甚至可以进行“交互式”战斗(玩家可以在战斗中更改他们的战斗策略,您可以重新计算战斗,将反序列化的战斗状态作为新的开始点)。

下一个。让我们每个战斗人员都是对象:

class Combatant {
  public $strategy;
  public takeDamage($damageType,$damageAmount){
     if($this->strategy->tryAvoidDamage($damageType,$damageAmount)) return;
     $newDamageAmount=$this->reduceDamageByArmor($damageType,$damageAmount);
     $newDamageAmount=$this->reduceDamageByAbilities($damageType,$newDamageAmount);
     // change your health below...
  }

  public dealDamage($weapoon, $enemy){
     $damageType = $weapoon->damageType;
     $damageAmount = $weapoon->damageAmount;
     $damageAmount = this->applySkills($weapoon, $damageType, $damageAmount);
     $enemy->takeDamage($damageType, $damageAmount);
  }

}  

策略也是对象:

class Strategy{
   public $combatant;
   public tryAvoidDamage($damageType,$damageAmount){
     if($damageType=="melee" && $combatant->actionPoints>10){
       // try to block punch (roll dice for skills etc)
       return $combatant->tryBlockPunch();
     }
     return false; // can't avoid bullet
   }
   public DoAction($enviroment){
      if($combatant->hp<10){
         $combatant->tryCastHealing();
      } else {
        var $enemy = $enviroment->findEnemes()->whereDistanceLessThan(2)->mostWeak();
        if($enemy != null) {
           $combatant->dealDamage($combatant->hands, $enemy) 
        }
      }
   }   
}

接下来你需要在运行循环时创建和初始化适当的对象

while($combatantA->isAlive() && $combatantB->isAlive()){
  $combatantA->strategy->DoAction(...)
  $combatantB->strategy->DoAction(...)
} 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-24
    • 1970-01-01
    相关资源
    最近更新 更多