gpt4 book ai didi

events - 为两个竞争对象建模的设计模式

转载 作者:行者123 更新时间:2023-12-04 10:47:46 25 4
gpt4 key购买 nike

我试图找出用于管理两个交互对象之间的“竞争”的最佳设计模式。例如,如果我想要一个 Fox追逐Rabbit的类(class)通过简单的环境上课。我想让他们“竞争”并找出谁获胜。最终它将成为学生可以用来试验继承和其他面向对象编程技能的教学工具。

此用例是否有既定的设计模式?

这是我能想到的最好的方法:一个类来表示承载其他两个对象的环境。我保持非常简单,并假设动物只沿直线奔跑,如果狐狸靠得足够近以咬住兔子,它就会捕获兔子。下面是一些代码来演示我所描述的内容。我使用 PHP 是因为我可以快速编写它,但我不想关注语言的细节。我的问题实际上是关于设计模式/架构的。

class Forrest() {
        public $fox;
        public $rabbit;
        public $width = 100; //meters?
        public $length = 100;

        __construct() {
                $this->fox = new Fox();
                $this->rabbit = new Rabbit();
                $this->theChase();
        }

        public function theChase() {
                 while (!$this->rabbit->isBitten) {
                         $this->rabbit->react($fox);
                         $this->fox->react($rabbit);
                 }
                 log('The fox got the rabbit!');
        }
}

abstract class Animal() {
        public $speed;
        public $hasTeeth = false;
        public $position;
        public $direction;
        public $isBitten = false;
        public function run($distance) {
                // update coordinates based on direction and speed
        }

        public function bite($someone) {
                 if (isCloseEnough( $someone ) && $this->hasTeeth) {
                          $someone->isBitten = true;
                          log(get_class($this) . ' bit the ' . get_class($someone)); //the Fox bit the Rabbit
                 }
        }

        public abstract function react($someone);
}

class Rabbit extends Animal {
         __construct() {
                  $this->speed = 30;
                  $this->position = [0,0];
                  $this->direction = 'north';
                  log(get_class($this) . ' starts at 0,0');
         }

         public react($fox) {
                //avoid the fox
         }
}

class Fox extends Animal {
          __construct() {
                  $this->speed = 20;
                  $this->position = [100,100];
                  $this->direction = 'south';
                  log (get_class($this) . ' starts at 100,100');
          }

          public react($rabbit) {
                  //try to catch the rabbit
          }
}

我看到这种方法有两个直接的问题:
  • 这种架构导致顺序的、交替的 Action 。换句话说,首先兔子做某事,然后狐狸做某事,然后兔子做某事……这更像是一个纸牌游戏,每个玩家轮流移动。如果两个对象能够同时使用react,那就更有趣了。
  • 目前还没有用于限制每“回合”事件量的系统。需要对单个“转弯”中可能发生的事情进行某种限制以保持其有趣。否则狐狸可以简单地run() run() run() ... run()直到它在第一回合捕获兔子。

  • 可能还有其他我没有注意到的问题。我怀疑上面 (1) 和 (2) 的答案是某种事件系统,它允许一种动物的 Action 触发另一只动物的 Action ,反之亦然。我还认为可能需要对每个 Action 相关的时间进行一些表示,但我不完全确定。

    最佳答案

    因此,您的任务是在设计模式下安装诸如游戏之类的东西,这些设计模式最初仅为企业类软件创建。从定义上来说,游戏不是企业软件,这就是为什么许多人在设计游戏时避免考虑设计模式的原因。但这并不意味着它不可行。

    我的建议:

  • 首先考虑模型:按照您的设想设计您的问题。
  • 记住它仍然是一个游戏,所以它需要遵循游戏开发模式:实际上只有一个 - 游戏循环。

  • 所以,如果你把上面的两个结合起来(我希望第二个不在那里),那么我会这样设计(如果我的建议让我想起一个,我会提到设计模式):
  • 标记当前时间点。
  • 环境开始游戏循环。
  • 对于每个循环步骤,计算自上一个时间点以来耗时。这将为您提供某些单位的时间跨度(例如,经过 N 毫秒)。
  • 给定时间跨度,您需要要求每个对象更新其状态(从概念上来说,问他们 - 如果 N 毫秒过去了,您现在会在哪里?)。这让我想起了访问者模式。
  • 在所有对象更新其状态后,Environment 在屏幕上显示结果(在实际游戏中,这意味着绘制游戏的当前状态 - 每个对象都在屏幕上重新绘制;对于您的简单应用程序,您可以检查 Fox 是否报告了它捕获了兔子)。
  • 显然,在循环步骤中,您需要不断标记当前时间,以便可以计算每个步骤的时间跨度差异。

  • 第 4 步涉及一些复杂性,尤其是在准确性至关重要的情况下。例如如果时间跨度大约为一秒,并且在那一秒内(在某个地方的中间)狐狸会捕获兔子,但最终还是有距离呢?如果狐狸和兔子的速度是时间的函数(有时会变慢,有时会加快),就会发生这种情况[顺便说一句,这听起来像是一种策略模式 - 计算当前速度的变化 - 例如线性与时间函数)。显然,如果狐狸和兔子都只是在时间跨度结束时报告他们的位置,则会错过捕捉时刻,这是不可取的。

    这是我将如何解决它:对于给定的时间跨度,如果它超过一个毫秒(假设毫秒是最短的可接受原子时间以获得足够好的精度),然后将其拆分为每个毫秒长度的时间跨度,对于每毫秒,要求每个对象更新其状态。毕竟,如果对象可以根据时间跨度更新其状态,我们可以在更短的时间跨度内任意多次调用它。显然,存在不可避免的副作用——您需要按某种顺序更新状态,但考虑到毫秒时间太短,这样做应该没问题。

    伪代码如下所示:
    var foxAndRabbitGame = new FoxAndRabbitGame();
    foxAndRabbitGame.RunGame(screen); //visitor
    /* when this line is reached, game is over. Do something with it. */
    class FoxAndRabbitGame
    {
    private fox = new Fox(Speed.Linear()); //strategy
    private rabbit = new Rabbit(Speed.Linear()); //strategy


    void RunGame(screen)
    {
    var currentTime = NOW;
    while (true)
    {
    var timePassed = NOW - currentTime;
    currentTime = NOW;

    foreach (millisecond in timePassed)
    {
    fox.UpdateState ( millisecond , rabbit );
    rabbit.UpdateState ( millisecond, fox );

    if (fox.TryBite(rabbit))
    {
    //game over.
    return;
    }
    }

    //usually, drawing is much slower than calculating state,
    //so we do it once, after all calculations.
    screen.Draw(this); //visitor
    screen.Draw(Fox); //visitor
    screen.Draw(rabbit); //visitor
    }
    }

    }

    关于events - 为两个竞争对象建模的设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39049562/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com