3

我不知道它叫什么,我相信它是实例。

假设我们有一个“怪物”类。此类应包含“健康”值。在创建类时设置为“5”。它还应该包含每个怪物的唯一 ID 值。

我想这样的事情:

$monster_1 = new Monster(); //sets monster ID to 1
$monster_2 = new Monster(); //sets monster ID to 2
$monster_3 = new Monster(); //sets monster ID to 3

所以,假设我想计算所有怪物的总生命值。

$totalHp = $monster_1->getHp() + $monster_2->getHp() + $monster_3->getHp();

它也可以,但是如果我添加一个名为$monster_4. 我必须手动将其添加到 $totalHp 计算中。

我可以创建一个数组而不是$monster变量,并使用 foreach 计算 $totalHp - 但它看起来很奇怪......

我不知道它是如何在其他语言中完成的。

有没有其他方法来归档这个?

附言。我试图了解“ http://www.scirra.com/demos/ghosttutorial/ ”游戏背后的逻辑。你创建了一个 Monster 类,每个 Monster 都使用这个类作为实例。我的解决方案肯定会奏效,但我不确定这是否是一种破解方法。

4

10 回答 10

3

创建一个包含一组怪物的辅助类,可能是一个 MonsterTeam 类;

class Monster {
     ...
}

class MonsterTeam {
    private $_monsters = [];

    public function addMonster(Monster &$monster) {
        array_push($this->_monsters, $monster);
    }

    public function getTotalHp() {
        $hp = 0;

        foreach ($this->_monsters as $monster) {
            $hp += $monster->getHp();
        }

        return $hp;
    }
}


$team = new MonsterTeam();

$monsterA = new Monster();
$team->addMonster($monsterA);

$monsterB = new Monster();
$team->addMonster($monsterB);

echo "Total HP: " . $team->getTotalHp();
于 2012-06-08T19:38:23.743 回答
2

首先,它们被称为ObjectsInstances,就像在面向对象的编程中一样?

其次,没有什么能阻止你创建一个怪物数组(看起来并不奇怪):

$monsters = array(
    new Monster(),
    new Monster(),
    new Monster(),
    new Monster()
);

foreach($monsters as $monster) {
    $totalHP += $monster->hp;
}

关于唯一ID,应该是那个人的责任MonsterFactory,意思是怪物应该被分配一个ID,它不应该分配给它自己,而是ID应该分配给它。创建怪物时是这样的:

new Monster(4); //ID is 4

谁跟踪它?别人,不是怪物。

于 2012-06-08T19:34:32.303 回答
1

您可以使用一个对象作为怪物的容器并使用它来跟踪您:

class MonsterContainer
{
    private $monsters = array();

    public function __construct()
    {
       // do stuff   
    }   

    public function addMonster(Monster $monster)
    {
        $this->monsters[] = $monster;   
    }

    public function totalMonstersHP()
    {
        $hp = 0;
        foreach ($this->monsters as $monster)
        {
            $hp += $monster->getHp()
        }
        return $hp;
    }
}

$monster_1 = new Monster(); 
$monster_2 = new Monster(); 
$monster_3 = new Monster(); 

$container = new MonsterContainer();
$container->addMonster(monster_1);
$container->addMonster(monster_2);
$container->addMonster(monster_3);
echo $container->totalMonstersHP();
于 2012-06-08T19:34:30.130 回答
1

你可以像这样创建一个$monsters数组:

$monsters = array();

然后每次你想添加一个怪物,你这样做:

$monsters[] = new Monster();

然后,您可以循环遍历您的数组以获得总生命值,如下所示:

$totalHP = 0;
foreach($monsters as $monster) {
    $totalHP += $monster->getHp();
}

在该循环之后,$totalHP将包含阵列中所有怪物的总生命值。

于 2012-06-08T19:36:01.700 回答
1

您可以创建一个集合工厂;它将负责创造新的怪物。将两个类融合在一起通常不是我的事,但我喜欢这样一个事实,即我可以通过这种方式将构造函数设为私有 :)

它使用两个静态变量(我想是全局变量),一个用于怪物 id,一个用于怪物集合,使用SplObjectStorage.

需要遍历所有怪物的方法使用该each()方法,因此您想要的任何逻辑都可以在类之外定义。

class Monster
{
  private $id;
  public $health;

  private static $instances;
  private static $nextid = 1;

  // private constructor
  private function __construct($id)
  {
    $this->id = $id;
    $this->health = 5;
  }

  public static function create()
  {
    if (!self::$instances) {
      self::$instances = new SplObjectStorage;
    }
    $o = new self(self::$nextid++);
    self::$instances->attach($o);

    return $o;
  }

  public static function remove($o)
  {
    if (!self::$instances) { return; }
    self::$instances->detach($o);
  }

  // iterate over all objects
  public static function each($cb)
  {
    if (!self::$instances) { return; }
    foreach (self::$instances as $o) {
      $cb($o);
    }
  }
}

小用法示例

$m1 = Monster::create();
$m2 = Monster::create();

$total_health = 0;
Monster::each(function(Monster $m) use (&$total_health) {
  $total_health += $m->health;
});
echo "Total health: $total_health\n";
于 2012-06-08T19:45:20.393 回答
0

我第二个 alexn,使用数组来存储你的类实例(是的,这是正确的术语)非常好。

然后你可以用它foreach来计算总HP。

于 2012-06-08T19:34:56.000 回答
0

创建 MonstersCollection 类,该类将包含方法getNewMonster()getTotalHP().

伪代码:

class MonstersCollection
{
   private $Monsters;

   public function getNewMonster()
   {
       $Monster=new Monster();
       $this->monsters[]=$Monster;
       return $Monster;
    }

   //and you know how to write method to get total HP :)
}
于 2012-06-08T19:34:59.057 回答
-1

类跟踪其实例是很常见的。

class Monster {
    private $monsters = array();
    public function __construct() {
       self::monsters[] = $this;
    }

    public  function __destruct() {
        array_splice(self::monsters, array_search($this, self::monsters), 1 );
    }

    public static function getTotalHp() {
         $total = 0;
         foreach(self::monsters as $monster) {
            $total += $monster->getHp();
         }
         return $total;
    }    
}
于 2012-06-08T19:47:13.690 回答
-2

也许您可以在构造函数中调用的同一个 Monster 类中创建一个新类或函数,并且每次创建该类时,它都会调用一个增加的全局变量。

于 2012-06-08T19:36:46.673 回答
-2

您可以创建观察者模式,该模式可以在 Monster 实例化时自动更新集中对象中的 totalHp 属性。

但是在你的 Monster 类中,一个更快/更简单的方法是这样的:

class Monster {

   ...
   private $hp = 5;
   private static $totalHp = 0;
   ...

   public function getHp() {
       return $this->hp;
   }

   public function __construct(...) {
       ...
       self::totalHp += $this->getHp();
       ...
   }

   public function __destruct(...) {
       ...
       self::totalHp -= $this->getHp();
       ...
   }

   ...

   public static function getTotalHp() {
       return self::totalHp;
   }

   /**
    * Provide negative number to reduce HP or positive to increase HP.
    */
   public function alterHp($hp) {
       $this->hp += $hp;
       self::totalHp += $hp;
   }
}

然后要获取当前的 totalHp 值,您必须在客户端代码中执行以下操作:

$totalHp = Monster::getTotalHp();
于 2012-06-08T19:38:45.030 回答