fork download
  1. <?php
  2. header("Content-Type: text/plain");
  3. //ini_set('html_errors', false);
  4. //xdebug_disable();
  5.  
  6. // ООП. Кошки - мышки
  7.  
  8. // Константы
  9. const cat = 'Cat';
  10. const mouse = 'Mouse';
  11. const dog = 'Dog';
  12.  
  13. // Класс Животного (игрока)
  14. abstract class Animal
  15. {
  16. // Id
  17. private $id;
  18.  
  19. // Счетчик экземпляров класса
  20. protected static $counter = 1;
  21.  
  22. // Координаты ХY
  23. protected $xy = array();
  24.  
  25. // Кол-во пропускаемых ходов
  26. protected $restingTime = 0;
  27.  
  28. // Hp
  29. protected $hp = 100;
  30.  
  31. // Генератор животного
  32. public function __construct($x, $y)
  33. {
  34. $this->xy['x'] = $x;
  35. $this->xy['y'] = $y;
  36. $this->id = self::$counter++;
  37. }
  38. public function getId()
  39. {
  40. return $this->id;
  41. }
  42.  
  43. // Выбор наилучшего ВариантаХода (большего веса)
  44. protected function chooseBestMoveVariant($moveVariants)
  45. {
  46. // Сортировка ВариантовХода по убыванию веса
  47. usort ($moveVariants,
  48. function ($moveVariantA, $moveVariantB ) {
  49. $weightA = $moveVariantA->getWeight();
  50. $weightB = $moveVariantB->getWeight();
  51. if ($weightA==$weightB) return 0;
  52. return ($weightA<$weightB) ? 1 : -1;
  53. });
  54. // Выбираем ходы с наибольшим весом
  55. $bestMoveVariantWeight = $moveVariants[0]->getWeight();
  56. $bestMoveVariants = array_filter ($moveVariants,
  57. function ($moveVariant) use ($bestMoveVariantWeight) {
  58. return ($bestMoveVariantWeight == $moveVariant->getWeight());
  59. });
  60. $bestMoveVariantKey = array_rand($bestMoveVariants, 1);
  61. return $bestMoveVariants[$bestMoveVariantKey];
  62. }
  63.  
  64. // Возвращает координаты
  65. public function getXY()
  66. {
  67. return $this->xy;
  68. }
  69.  
  70. // Установка координат
  71. public function setXY($xy)
  72. {
  73. $this->xy['x'] = $xy['x'];
  74. $this->xy['y'] = $xy['y'];
  75. }
  76.  
  77. // Возвращает время отдыха
  78. public function getRestingTime()
  79. {
  80. return $this->restingTime;
  81. }
  82.  
  83. public function setRestingTime($moveQuantity)
  84. {
  85. $this->restingTime = $moveQuantity;
  86. }
  87.  
  88. public function getHP()
  89. {
  90. return $this->hp;
  91. }
  92.  
  93. // Находим животных в зоне видимости
  94. protected function getScope($animals)
  95. {
  96. $xy = $this->xy;
  97. $visionLimits = $this->getVisionLimits();
  98. $scope = array_filter($animals, function ($animal) use ($xy, $visionLimits) {
  99. $animalXY = $animal->getXY();
  100. return (abs($animalXY['x'] - $xy['x']) <= $visionLimits &&
  101. abs($animalXY['y'] - $xy['y']) <= $visionLimits);
  102. });
  103. return $scope;
  104. }
  105. // Находим определенных животных
  106. protected function getAnimal($animals, $animalType)
  107. {
  108. $scope = array_filter($animals, function ($animal) use ($animalType) {
  109. return (get_class($animal) == $animalType);
  110. });
  111. return $scope;
  112. }
  113. // Определяет направление
  114. // Знак "+" значения косинуса указывает направление в сторону цели, "-" от нее
  115. protected function getDirections($moveVariant, $target)
  116. {
  117. $moveVariantVector = new Vector($this->xy, $moveVariant->getXY());
  118. $targetsVector = new Vector($this->xy, $target->getXY());
  119. $cos = round($targetsVector->getCos($moveVariantVector, $targetsVector));
  120. return $cos;
  121. }
  122. protected function getDistance($target)
  123. {
  124. $target = $target;
  125. $targetsVector = new Vector($this->xy, $target->getXY());
  126. return $targetsVector->getLenght();
  127. }
  128.  
  129. // Присваивает вес вариантам хода на основе
  130. // совпадения напрвления до целей и растоянию до них умноженный на коэфициент
  131. protected function getWeightsByDirections($targets, $moveVariants, $k = 1)
  132. {
  133. // Если целей нет
  134. if (count($targets)==0) return;
  135.  
  136. foreach ($moveVariants as $moveVariant) {
  137. foreach ($targets as $target) {
  138. // Вес хода прямо пропорционален напрвлению к цели
  139. // и обратно пропорционален растоянию до цели
  140. $distance = $this->getDistance($target);
  141. $direction = $this->getDirections($moveVariant, $target);
  142. // Исключаем варианты когда длина или кос не определены
  143. if ($distance==0 && $direction==null) {
  144. continue;
  145. } else {
  146. // Вычисляем вес умноженный на коэфициент
  147. $weight = $moveVariant->getWeight() + ($k*$direction/pow($distance,2));
  148. // Присваиваем вес хода
  149. $moveVariant->setWeight($weight);
  150. }
  151. }
  152. }
  153. }
  154. // Исключение ходов занятых оживотными
  155. protected function removeMoveByAnimals($animals, $moveVariants)
  156. {
  157. foreach ($moveVariants as $key => $moveVariant) {
  158. $moveVariantXY=$moveVariant->getXY();
  159. foreach ($animals as $animal) {
  160. $animalXY=$animal->getXY();
  161. // Исключаем из проверки ход на котором стоим
  162. if ($animalXY['x'] == $this->xy['x'] &&
  163. $animalXY['y'] == $this->xy['y']) continue;
  164. // Проверяем остальные
  165. if ($moveVariantXY['x']==$animalXY['x'] &&
  166. $moveVariantXY['y']==$animalXY['y']) {
  167. unset ($moveVariants[$key]);
  168.  
  169. }
  170. }
  171. }
  172. $moveVariants = $moveVariants;
  173. return $moveVariants;
  174. }
  175. // Определение углов в поле видимости
  176. protected function getCorners ()
  177. {
  178. // Определяем координаты углов
  179. $fieldSizeX = fieldSize;
  180. $fieldSizeY = fieldSize;
  181. // Создаем углы координаты углов
  182. $corner['x']=fieldSize;
  183.  
  184. // Оставляем углы которые видим
  185. // Возвращаем их
  186. }
  187. // Убийство
  188. public function toDie()
  189. {
  190. $this->hp = 0;
  191. return true;
  192. }
  193.  
  194. // Игровой ход
  195. abstract function move($animals, $moveVariants, $corners);
  196.  
  197. // Скорость перемещения (клеток за ход)
  198. abstract protected function getSpeed();
  199.  
  200. // Возможность ходить по горизонт, вертикали, диагонали
  201. //abstract function getMoveAbility();
  202.  
  203. // Область видимости вокруг себя
  204. abstract protected function getVisionLimits();
  205.  
  206. // Оценка ходов
  207. abstract protected function setRating($animals, $moveVariants, $corners);
  208.  
  209. // Исключение занятых ходов
  210. abstract protected function removeOccupiedMove($animals, $moveVariants);
  211. }
  212.  
  213. class Mouse extends Animal
  214. {
  215. // Неуязвимость
  216. private $megaMouse = false;
  217.  
  218. // Скорость перемещения (клеток за ход)
  219. public function getSpeed()
  220. {
  221. return 1;
  222. }
  223. // Область видимости вокруг себя
  224. public function getVisionLimits()
  225. {
  226. return 4;
  227. }
  228. // Игровой ход
  229. public function move($animals, $moveVariants, $corners)
  230. {
  231. // Исключение занятых ходов
  232. $moveVariants = $this->removeOccupiedMove($animals, $moveVariants);
  233. // Исключения вариантов хода по вертикали
  234. $moveVariants = $this->removeDiagonalMove($moveVariants);
  235. // Оценка ходов
  236. $this->setRating($animals, $moveVariants, $corners);
  237. // Выбор наилучшего хода (наибольший вес)
  238. $bestMoveVariant = $this->chooseBestMoveVariant($moveVariants);
  239. // Ход
  240. $this->setXY($bestMoveVariant->getXY());
  241. // Проверка неуязвимости
  242. $this->transformMegaMouse($animals);
  243. }
  244.  
  245. // Убийство
  246. public function toDie()
  247. {
  248. if (!$this->megaMouse) {
  249. return parent::toDie();
  250. } else {
  251. return false;
  252. }
  253. }
  254.  
  255. // Оценка ходов
  256. protected function setRating($animals, $moveVariants, $corners)
  257. {
  258. // Область видимости
  259. $animals = $this->getScope($animals);
  260. $corners = $this->getScope($corners);
  261.  
  262. // Находим мышей в поле видимости
  263. $mouses = ($this->getAnimal($animals, mouse));
  264.  
  265. // Присвиваем реитинг = 1 вариантам ходов по направлению к мышам
  266. $this->getWeightsByDirections($mouses, $moveVariants, 2);
  267.  
  268. // Находим кошек в поле видимости
  269. $cats = ($this->getAnimal($animals, cat));
  270.  
  271. // Присвиваем реитинг = 2 вариантам ходов по направлению к кошкам
  272. $this->getWeightsByDirections($cats, $moveVariants, -10);
  273.  
  274. // Присвиваем реитинг = -1 вариантам ходов по направлению к углам
  275. $this->getWeightsByDirections($corners, $moveVariants, -1);
  276.  
  277. // Находим собак в поле видимости
  278. $dog = ($this->getAnimal($animals, dog));
  279. // Если на соседней клетке есть собака, то такой ход +10
  280.  
  281. // Присвиваем реитинг = -1 вариантам ходов по направлению к углам
  282. $this->getWeightsByDirections($dog, $moveVariants, 1);
  283. }
  284.  
  285. // Исключение занятых ходов
  286. protected function removeOccupiedMove($animals, $moveVariants)
  287. {
  288. $moveVariants = $this->removeMoveByAnimals($animals, $moveVariants);
  289. return $moveVariants;
  290. }
  291.  
  292. // Метод исключения вариантов хода по вертикали
  293. private function removeDiagonalMove($moveVariants) {
  294.  
  295. // У вертикальных ходов координаты X Y равны по модулю, относительно текщего положения животного
  296. foreach ($moveVariants as $key => $moveVariant) {
  297. $moveVariantXY=$moveVariant->getXY();
  298. // Исключаем из проверки ход на котором стоим
  299. if ($moveVariantXY['x'] == $this->xy['x'] &&
  300. $moveVariantXY['y'] == $this->xy['y']) continue;
  301. // Проверяем остальные
  302. if (abs($moveVariantXY['x']-$this->xy['x'])==abs($moveVariantXY['y']-$this->xy['y'])) {
  303. unset($moveVariants[$key]);
  304. }
  305. }
  306. return $moveVariants;
  307. }
  308. // Трансформирует 3х мышей в мегамышь неуязвимую для кошек
  309. private function transformMegaMouse ($animals)
  310. {
  311. $mouses = $this->cheсkNeighborMouses($animals);
  312. if ($mouses>=3) {
  313. $this->megaMouse = true;
  314. } else {
  315. $this->megaMouse = false;
  316. }
  317. }
  318. // Считает кол-во мышей в соседних клетках
  319. private function cheсkNeighborMouses($animals)
  320. {
  321. // Извлекаем мышей
  322. $mouses = $this->getAnimal($animals, mouse);
  323. // Сравнить координаты текущей мыши с координатами остальных
  324. // Если модуль разницы координат в пределах 1 то ОК
  325. $xy = $this->xy;
  326. $mouses = array_filter($mouses,
  327. function ($mouse) use ($xy) {
  328. $mouseXY = $mouse->getXY();
  329. return ((abs($xy['x'] - $mouseXY['x'])<=1) &&
  330. (abs($xy['y'] - $mouseXY['y'])<=1));
  331. });
  332. return count($mouses);
  333. }
  334. }
  335. class Cat extends Animal
  336. {
  337. // Счетчик ходов
  338. private $moveCounter = 0;
  339.  
  340. // Скорость перемещения (клеток за ход)
  341. public function getSpeed()
  342. {
  343. return 1;
  344. }
  345.  
  346. // Возможность ходить по горизонт, вертикали, диагонали
  347. public function getMoveAbility()
  348. {
  349. return array(true, true, true);
  350. }
  351. // Область видимости вокруг себя
  352. public function getVisionLimits()
  353. {
  354. return INF;
  355. }
  356.  
  357. // Игровой ход
  358. public function move($animals, $moveVariants, $corners)
  359. {
  360. // Проверка кол-ва пропускаемых ходов
  361. if ($this->getRestingTime()>0 ) {
  362. // Уменьшаем счетчик пропускаемых ходов
  363. $this->setRestingTime($this->getRestingTime()-1);
  364. return;
  365. }
  366. // Исключение занятых ходов
  367. $moveVariants = $this->removeOccupiedMove($animals, $moveVariants);
  368. // Оценка ходов
  369. $this->setRating($animals, $moveVariants, $corners);
  370. // Выбор наилучшего хода (наибольший вес)
  371. $bestMoveVariant = $this->chooseBestMoveVariant($moveVariants);
  372. // Проверка съедания мыши
  373. $eatenMouse = $this->checkEatenMouse($animals, $bestMoveVariant);
  374. if ($eatenMouse) $this->eatMouse($eatenMouse);
  375. // Ход
  376. $this->setXY($bestMoveVariant->getXY());
  377. // Прибавляем счетчик
  378. $this->moveCounter++;
  379. if ($this->moveCounter>=8) {
  380. $this->setRestingTime(1);
  381. $this->moveCounter=0;
  382. }
  383. }
  384. // Оценка ходов
  385. protected function getWeightsByDirections($targets, $moveVariants, $coeficient = 1)
  386. {
  387. // Если в соседней клетке есть мышь, рейтинг = INF
  388. foreach ($moveVariants as $moveVariant)
  389. {
  390. foreach ($targets as $mouse) {
  391. $mouseXY = $mouse->getXY();
  392. $moveVariantXY = $moveVariant->getXY();
  393.  
  394. if ($mouseXY['x']==$moveVariantXY['x'] &&
  395. $mouseXY['y']==$moveVariantXY['y']) {
  396. $moveVariant->setWeight(INF); //$moveVariant->getWeight() + 10
  397. }
  398. }
  399. }
  400. parent::getWeightsByDirections($targets, $moveVariants, $coeficient = 1);
  401. }
  402.  
  403. // Оценка ходов
  404. protected function setRating($animals, $moveVariants, $corners)
  405. {
  406. // Область видимости
  407. $scope = $this->getScope($animals);
  408.  
  409. // Находим мышей в поле видимости
  410. $mouses = ($this->getAnimal($animals, mouse));
  411.  
  412. // Присвиваем реитинг = 1 вариантам ходов по направлению к мышам
  413. $this->getWeightsByDirections($mouses, $moveVariants, 2);
  414. }
  415. // Исключение занятых ходов
  416. protected function removeOccupiedMove($animals, $moveVariants)
  417. {
  418. // Исключаем кошек
  419. $cats = $this->getAnimal($animals, cat);
  420. $moveVariants = $this->removeMoveByAnimals($cats, $moveVariants);
  421. // Исключаем соседние с собакой ходы
  422. $dogs = $this->getAnimal($animals, dog);
  423. $xy = $this->xy;
  424. /*
  425.   $moveVariants = array_udiff($moveVariants, $dogs,
  426.   function($move, $dog) use ($xy){
  427.   $moveXY = $move->getXY();
  428.   $dogXY = $dog->getXY();
  429.   $absX = abs($moveXY['x']-$dogXY['x']);
  430.   $absY = abs($moveXY['y']-$dogXY['y']);
  431.   if ($moveXY['x']-$dogXY['x'] && $moveXY['y']==$xy['y']) {
  432.   return 1;
  433.   }
  434.   });
  435.   */
  436. foreach ($moveVariants as $moveVariant) {
  437. foreach($dogs as $dog) {
  438. $moveXY = $moveVariant->getXY();
  439. $dogXY = $dog->getXY();
  440. $xy = $this->xy;
  441. $absX = abs($moveXY['x']-$dogXY['x']);
  442. $absY = abs($moveXY['y']-$dogXY['y']);
  443. if (($moveXY['x']==$xy['x'] && $moveXY['y']==$xy['y']) |
  444. ($absX>1 && $absY>1)) {
  445. $resultMoves[]=$moveVariant;
  446. }
  447. }
  448. }
  449. $moveVariants = $this->removeMoveByAnimals($dogs, $moveVariants);
  450. // Исключаем cобак
  451. return $resultMoves;
  452. }
  453. // Проверка съедания мыши
  454. private function checkEatenMouse($animals, $bestMoveVariant)
  455. {
  456. $moveVariantXY=$bestMoveVariant->getXY();
  457. $mouses = $this->getAnimal($animals, mouse);
  458. foreach ($mouses as $mouse) {
  459. $mouseXY = $mouse->getXY();
  460. if ($mouseXY['x'] == $moveVariantXY['x'] &&
  461. $mouseXY['y'] == $moveVariantXY['y']) {
  462. return $mouse;
  463. }
  464. }
  465. }
  466. // Поедание мыши
  467. private function eatMouse ($mouse)
  468. {
  469. $isDead = $mouse->toDie();
  470. if ($isDead) $this->setRestingTime(1);
  471. }
  472. }
  473. class Dog extends Animal
  474. {
  475. // Скорость перемещения (клеток за ход)
  476. public function getSpeed()
  477. {
  478. return 2;
  479. }
  480.  
  481. // Возможность ходить по горизонт, вертикали, диагонали
  482. public function getMoveAbility()
  483. {
  484. return array(true, true, true);
  485. }
  486.  
  487. // Область видимости вокруг себя
  488. public function getVisionLimits()
  489. {
  490. return INF;
  491. }
  492.  
  493. // Игровой ход
  494. public function move($animals, $moveVariants, $corners)
  495. {
  496. // Метод исключения ходов соседних к текущему положению
  497. $moveVariants = $this->exlusionNeighborMove($moveVariants);
  498. // Исключение занятых ходов
  499. $moveVariants = $this->removeOccupiedMove($animals, $moveVariants);
  500. // Оценка ходов
  501. $this->setRating($animals, $moveVariants, $corners);
  502. // Выбор наилучшего хода (наибольший вес)
  503. $bestMoveVariant = $this->chooseBestMoveVariant($moveVariants);
  504. // Ход
  505. $this->setXY($bestMoveVariant->getXY());
  506. }
  507.  
  508. // Оценка ходов
  509. protected function setRating($animals, $moveVariants, $corners)
  510. {
  511. // Присвиваем случайный рейтинг вариантам ходов
  512. $moveVariants = array_map(function ($moveVariant) {
  513. $moveVariant->setWeight(rand(0,10));},
  514. $moveVariants);
  515. return $moveVariants;
  516. }
  517. // Исключение занятых ходов
  518. protected function removeOccupiedMove($animals, $moveVariants)
  519. {
  520. // Исключаем всех животных
  521. $moveVariants = $this->removeMoveByAnimals($animals, $moveVariants);
  522. return $moveVariants;
  523. }
  524. // Метод исключения ходов соседних к текущему положению
  525. private function exlusionNeighborMove($moveVariants)
  526. {
  527. $xy = $this->xy;
  528. $moveVariants = array_filter($moveVariants,
  529. function ($moveVariant) use ($xy) {
  530. $moveVariantXY = $moveVariant->getXY();
  531. return ((abs($xy['x'] - $moveVariantXY['x'])>1) |
  532. (abs($xy['y'] - $moveVariantXY['y'])>1) |
  533. (($xy['x'] == $moveVariantXY['x']) &&
  534. ($xy['y'] == $moveVariantXY['y'])));
  535. });
  536. return $moveVariants;
  537. }
  538. }
  539. // Класс Животные (Игроки)
  540. class Animals
  541. {
  542. private $animals = array();
  543.  
  544. public function __construct ($mousesQuantity, $catsQuantity, $dogsQuantity)
  545. {
  546. // Создание мышей
  547. for ($mousesQuantity; $mousesQuantity > 0; $mousesQuantity--) {
  548. // Генераруем случайные координаты
  549. $xy = $this->newCoordinat();
  550. $this->animals[] = new Mouse($xy['x'], $xy['y']);
  551. }
  552. // Создание кошек
  553. for ($catsQuantity; $catsQuantity > 0; $catsQuantity--) {
  554. $xy = $this->newCoordinat();
  555. $this->animals[] = new Cat($xy['x'], $xy['y']);
  556. }
  557. // Создание собак
  558. for ($dogsQuantity; $dogsQuantity > 0; $dogsQuantity--) {
  559. $xy = $this->newCoordinat();
  560. $this->animals[] = new Dog($xy['x'], $xy['y']);
  561. }
  562. }
  563.  
  564. // Запуск цикла ходов для всех животных
  565. public function move($corners)
  566. {
  567. foreach ($this->animals as $animal) {
  568. // Генерация всех возможных ВариантовХода
  569. $moveVariants = MoveVariant::createMoveVariants($animal);
  570. $animal->move($this->animals, $moveVariants, $corners);
  571. }
  572. // Чистка убитых животных
  573. $this->cleanUpDeadAnimals();
  574. }
  575.  
  576. // Убираем с поля убитых животных
  577. private function cleanUpDeadAnimals()
  578. {
  579. $liveAnimal = array_filter($this->animals,
  580. function ($animal) {
  581. return ($animal->getHp()>0);
  582. });
  583. $this->animals = $liveAnimal;
  584. }
  585.  
  586. // Функция генерации координат
  587. private function newCoordinat()
  588. {
  589. $xy = array();
  590. $xy['x'] = rand(1, fieldSize);
  591. $xy['y'] = rand(1, fieldSize);
  592.  
  593. return $xy;
  594. }
  595. // Уничтожение животного
  596. public function killAnimal($killingAnimal)
  597. {
  598. foreach ($animals as $key => $animal) {
  599. if ($animal === $killingAnimal) unset ($animals[$key]);
  600. }
  601. }
  602. public function getAnimalsAsArray ()
  603. {
  604. return $this->animals;
  605. }
  606. }
  607.  
  608. // Класс ВариантХода
  609. class MoveVariant
  610. {
  611. // Координаты
  612. private $xy = array();
  613. // Вес
  614. private $weight=0;
  615.  
  616. public function __construct ($moveX, $moveY)
  617. {
  618. $this->xy['x'] = $moveX;
  619. $this->xy['y'] = $moveY;
  620. }
  621.  
  622. // Возвращает координаты
  623. public function getXY()
  624. {
  625. return $this->xy;
  626. }
  627. public function setWeight($weight)
  628. {
  629. $this->weight = $weight;
  630. }
  631. public function getWeight()
  632. {
  633. return $this->weight;
  634. }
  635. // Фабрика ВариантовXода
  636. static public function createMoveVariants ($animal)
  637. {
  638. // Создание новых ВариантовХода
  639. $moveVariants = array();
  640. $animalXY = $animal->getXY();
  641. $animalSpeed = $animal->getSpeed();
  642.  
  643. // Координаты начала (верхний левый угол)
  644. $animalSpeed = $animal->getSpeed();
  645. do {
  646. $start['x'] = $animalXY['x']-$animalSpeed;
  647. $animalSpeed--;
  648. } while ($start['x']<=0);
  649.  
  650. $animalSpeed = $animal->getSpeed();
  651. do {
  652. $start['y'] = $animalXY['y']-$animalSpeed;
  653. $animalSpeed--;
  654. } while ($start['y']<=0);
  655. // Координаты конца (нижний правый угол)
  656. $animalSpeed = $animal->getSpeed();
  657. do {
  658. $end['x'] = $animalXY['x']+$animalSpeed;
  659. $animalSpeed--;
  660. } while ($end['x']>fieldSize);
  661.  
  662. $animalSpeed = $animal->getSpeed();
  663. do {
  664. $end['y'] = $animalXY['y']+$animalSpeed;
  665. $animalSpeed--;
  666. } while ($end['y']>fieldSize);
  667.  
  668. // Генерация ходов
  669. $y = $start['y'];
  670. while ($y<=$end['y']) {
  671. $x = $start['x'];
  672. while ($x<=$end['x']) {
  673. $moveVariants[] = new MoveVariant($x, $y);
  674. $x++;
  675. }
  676. $y++;
  677. }
  678. return $moveVariants;
  679. }
  680. }
  681. // Класс Вектор
  682. class Vector
  683. {
  684. private $xy = array();
  685. private $vectorNorm; // нормализованный вектор
  686. private $zero; // нулевой вектор
  687.  
  688. // Можно создать задавая координаты x и y,
  689. // либо двумя точками (массивы содержащие координаты)
  690. public function __construct($startXY, $endXY)
  691. {
  692.  
  693. if ((is_int($startXY) && is_int($endXY)) |
  694. (is_float($startXY) && is_float($endXY))) {
  695. $this->xy['x'] = $startXY;
  696. $this->xy['y'] = $endXY;
  697. } else if (is_array($startXY) && is_array($endXY)) {
  698. $this->xy['x'] = $endXY['x'] - $startXY['x'];
  699. $this->xy['y'] = $endXY['y'] - $startXY['y'];
  700. } else {
  701. //throw new Exception ("Аргументы для создания класса Вектор
  702. // должны быть или (int, int) или (array, array)");
  703. }
  704. }
  705. public function getXY()
  706. {
  707. return $this->xy;
  708. }
  709. public function isZero()
  710. {
  711. if (!isset($this->zero)) {
  712. if (round($this->xy['x']) == 0 && round($this->xy['y']) == 0) {
  713. $this->zero = true;
  714. } else {
  715. $this->zero = false;
  716. }
  717. }
  718. return $this->zero;
  719. }
  720. public function getLenght()
  721. {
  722. $sumQuad = pow($this->xy['x'], 2) + pow($this->xy['y'], 2);
  723. $sqrt = sqrt($sumQuad);
  724. return $sqrt; //$sqrt;
  725. }
  726.  
  727. public function getAngle($vector1, $vector2)
  728. {
  729. $vector1Norm = $vector1->getNormalyze();
  730. $vector2Norm = $vector2->getNormalyze();
  731. $multiplyResult = $this->multiply($vector1Norm, $vector2Norm);
  732. // Проверка на нулевые вектора
  733. if (($vector1->isZero()) | ($vector2->isZero())) {
  734. $acos = null;
  735. } else {
  736. $acos = acos($multiplyResult);
  737. }
  738. return $acos;
  739. }
  740.  
  741. public function getNormalyze()
  742. {
  743. if (!isset($this->vectorNorm)) {
  744. // Проверка на нулевой вектор
  745. $length = $this->getLenght();
  746. if ($length!=0) {
  747. $x = $this->xy['x']/$length;
  748. $y = $this->xy['y']/$length;
  749. } else {
  750. $x = 0;
  751. $y = 0;
  752. }
  753.  
  754. $this->vectorNorm = new Vector($x, $y);
  755. }
  756. return $this->vectorNorm;
  757. }
  758. public function getCos($vector1, $vector2)
  759. {
  760. $multiplyResult = $this->multiply($vector1, $vector2);
  761. $multiplyLenghtResult = $vector1->getLenght() * $vector2->getLenght();
  762. if ($multiplyLenghtResult==0) {
  763. // Если как минимум один из векторов нулевой, к черту такое сравнение
  764. $cos = null;
  765. } else {
  766. $cos = $multiplyResult / $multiplyLenghtResult;
  767. }
  768. /*$cos = cos($this->getAngle($vector1, $vector2));*/
  769. return $cos;
  770. }
  771. public function multiply($vector1, $vector2)
  772. {
  773. $vector1XY = $vector1->getXY();
  774. $vector2XY = $vector2->getXY();
  775. $multiplyResult = $vector1XY['x'] * $vector2XY['x'] + $vector1XY['y'] * $vector2XY['y'];
  776. return $multiplyResult;
  777. }
  778. }
  779. class Corner
  780. {
  781. public static function getCorners()
  782. {
  783. for ($y = fieldSize; $y>=0; $y=$y-fieldSize) {
  784. for ($x = fieldSize; $x>=0; $x=$x-fieldSize) {
  785. // Создаем новый угол
  786. $corners[] = new MoveVariant ($x, $y);
  787. }
  788. }
  789. return $corners;
  790. }
  791. }
  792. // Класс ГеймСет (Игра)
  793. class GameSet
  794. {
  795. private $raunds = array();
  796. private $animals;
  797. private $corners;
  798. //private $raundCounter = 0; // Номер раунда
  799.  
  800. public function __construct ($mousesQuantity, $catsQuantity, $dogsQuantity)
  801. {
  802. $this->animals = new Animals ($mousesQuantity, $catsQuantity, $dogsQuantity);
  803. $this->corners = Corner::getCorners();
  804. }
  805.  
  806. // Новый игровой раунд
  807. public function newRaund($raundNum)
  808. {
  809. // Ход животных
  810. $this->animals->move($this->corners);
  811. }
  812. // Представление раунда в виде псевдографики (массива строк)
  813. public function getGameRoundAsGraphics()
  814. {
  815. $gameField = array(); // поле игры, содержит строки из клеток
  816. $fieldSize = fieldSize;
  817. // Массив аватаров Животных
  818. $avatars = array(0 => 'm', 1 => 'K');
  819.  
  820. // Формируем поле из точек
  821. // Повторяем для каждой строки
  822. for ($fieldSize; $fieldSize>0; $fieldSize--) {
  823. // Заполняем строку "."
  824. $str = str_repeat(".", fieldSize);
  825. // Добавляем строку в массив
  826. $gameField[] = $str;
  827. }
  828. // Получаем всех Жиаотных массивом
  829. $animals = $this->animals->getAnimalsAsArray();
  830.  
  831. // Проходим по массиву животных
  832. foreach ($animals as $key => $animal) {
  833. // Узнаем координаты каждого персонажа
  834. $xy = $animal->getXY();
  835.  
  836. // Заменяем соответствующую точку в соответствующей строке id мышки
  837. $str = $gameField[$xy['y']-1];
  838. // Мышь обозначаем носером
  839. if (get_class($animal)==mouse) {
  840. $str = substr_replace($str, $animal->getId(), $xy['x']-1, 1);
  841. } elseif (get_class($animal)==dog) {
  842. $str = substr_replace($str, "D", $xy['x']-1, 1);
  843. } else {
  844. // Кошку буквой "K" или "@" если спит
  845. if ($animal->getRestingTime()>0) {
  846. $str = substr_replace($str, "@", $xy['x']-1, 1);
  847. } else {
  848. $str = substr_replace($str, "K", $xy['x']-1, 1);
  849. }
  850.  
  851. }
  852. $gameField[$xy['y']-1] = $str;
  853. }
  854. return $gameField;
  855. }
  856. // Печать раунда
  857. public function printGameRound($raundNum)
  858. {
  859. // Получаем раунд в виде псевдографики (массива строк)
  860. $printingRaund = $this->getGameRoundAsGraphics();
  861. // Узнаем че по кошкам (мышам)
  862. $animals = $this->animals->getAnimalsAsArray();
  863. $cats = array_filter($animals,
  864. function ($animal) {
  865. return (get_class($animal) == cat);
  866. });
  867. $mouses = array_filter($animals,
  868. function ($animal) {
  869. return (get_class($animal) == mouse);
  870. });
  871. $dog = array_filter($animals,
  872. function ($animal) {
  873. return (get_class($animal) == dog);
  874. });
  875. $dogsNum = count($dog);
  876. $catsNum = count($cats);
  877. $mousesNum = count($mouses);
  878.  
  879. // Выводим на экран массив построчно
  880. foreach ($printingRaund as $key => $str) {
  881. if ($key == 0) {
  882. echo $str . " " . "Ход: " . "{$raundNum}\n";
  883. } else if ($key == 1) {
  884. echo $str . " " . "Кошек: " . "$catsNum\n";
  885. } else if ($key == 2) {
  886. echo $str . " " . "Мышек: " . "$mousesNum\n";
  887. } else if ($key == 2) {
  888. echo $str . " " . "Собак: " . "$dogsNum\n";
  889. } else {
  890. echo "{$str}\n";
  891. }
  892. }
  893. echo "\n";
  894. }
  895. }
  896.  
  897. // Создание новой игры
  898. function createNewGame ()
  899. {
  900. // Вводные данные для создания новой игры
  901. $raundsQuantity = 20;
  902. $mousesQuantity = 4;
  903. $catsQuantity = 2;
  904. $dogQuantity = 2;
  905. $fieldSize = 19;
  906.  
  907. define('fieldSize', $fieldSize);
  908.  
  909. // Создание новой игры (раунд: 0)
  910. $gameSet= new GameSet($mousesQuantity, $catsQuantity, $dogQuantity);
  911. // Вывести раунд на печать
  912. $gameSet->printGameRound(0);
  913.  
  914. // Цикл раундов (начиная с первого)
  915. for ($raundNum=1; $raundNum<=$raundsQuantity; $raundNum++) {
  916. // Новый раунд
  917. $gameSet->newRaund($raundNum);
  918. // Вывести раунд на печатьs
  919. $gameSet->printGameRound($raundNum);;
  920. }
  921. }
  922. createNewGame();
  923.  
  924. ?>
Success #stdin #stdout 0.12s 52472KB
stdin
Standard input is empty
stdout
...................    Ход: 0
........3..........    Кошек: 2
...................    Мышек: 4
...................
.............D.....
...................
...................
..........4....K...
...................
......D............
...................
...................
...................
...................
...............1...
...................
...................
.K.................
...............2...

...................    Ход: 1
.......3...........    Кошек: 2
...................    Мышек: 4
...........D.......
...................
...................
..........4........
..............K....
...................
........D..........
...................
...................
...................
...................
...................
...............1...
..K................
...............2...
...................

...................    Ход: 2
........3.D........    Кошек: 2
...................    Мышек: 4
...................
...................
...................
.........4.........
......D......K.....
...................
...................
...................
...................
...................
...................
...................
...K...............
...............1...
..............2....
...................

...................    Ход: 3
.........3D........    Кошек: 2
...................    Мышек: 4
...................
...................
...................
........4..........
...................
............K......
.......D...........
...................
...................
...................
...................
....K..............
...................
..............1....
.............2.....
...................

.........3.........    Ход: 4
...................    Кошек: 2
...................    Мышек: 4
.........D.........
...................
...................
.......4...........
...........K.......
...................
...................
...................
.......D...........
...................
.....K.............
...................
...................
.............1.....
.............2.....
...................

...................    Ход: 5
.........3.........    Кошек: 2
...................    Мышек: 4
...................
...........D.......
...................
......4............
...................
..........K........
...................
...................
...................
......K..D.........
...................
...................
...................
.............21....
...................
...................

...................    Ход: 6
...................    Кошек: 2
.........3.........    Мышек: 4
.........D.........
...................
...................
.....4.............
...................
.........K.........
...................
...................
.......K...........
...................
...................
..........D........
.............2.....
..............1....
...................
...................

...................    Ход: 7
...................    Кошек: 2
........3..........    Мышек: 4
...................
.......D...........
...................
....4..............
...................
........K..........
...................
........K..........
...................
...................
...................
...................
........D...2......
.............1.....
...................
...................

...................    Ход: 8
...................    Кошек: 2
...................    Мышек: 4
........3..........
...................
.....D.............
...4...............
.........@.........
...................
...................
.........@.........
...................
...................
.........D.........
............2......
.............1.....
...................
...................
...................

...................    Ход: 9
...................    Кошек: 2
........3..........    Мышек: 4
...................
...................
.......D...........
....4..............
.........K.........
...................
...................
.........K.........
...........D.......
...................
...................
.............2.....
............1......
...................
...................
...................

...................    Ход: 10
...................    Кошек: 2
...................    Мышек: 4
......D.3..........
...................
...................
.....4..K..........
...................
...................
...................
..........K..D.....
...................
...................
...................
............1......
.............2.....
...................
...................
...................

...................    Ход: 11
...................    Кошек: 2
........3..........    Мышек: 4
........D..........
...................
.......K...........
....4..............
...................
..............D....
...................
...................
..........K........
...................
...................
...................
............1......
.............2.....
...................
...................

...................    Ход: 12
...................    Кошек: 2
.......3...........    Мышек: 4
........D..........
......K............
...................
...4..........D....
...................
...................
...................
...................
...................
..........K........
...................
...................
...................
............1......
.............2.....
...................

...................    Ход: 13
.......3..D........    Кошек: 2
...................    Мышек: 4
......K............
...................
...................
..4................
...................
............D......
...................
...................
...................
...................
...........K.......
...................
...................
...................
............1......
.............2.....

.......3...........    Ход: 14
...................    Кошек: 2
.......K...........    Мышек: 4
........D..........
...................
...................
.4.................
...................
............D......
...................
...................
...................
...................
...................
............K......
...................
...................
.............2.....
............1......

........3..........    Ход: 15
........K..........    Кошек: 2
......D............    Мышек: 4
...................
...................
...................
...................
.4.................
...................
...................
............D......
...................
...................
...................
...................
...........K.......
...................
............2......
.............1.....

.......@D..........    Ход: 16
...................    Кошек: 2
...................    Мышек: 3
...................
...................
...................
...................
..4................
..............D....
...................
...................
...................
...................
...................
...................
...................
............K......
.............1.....
............2......

.......K...........    Ход: 17
...................    Кошек: 2
......D............    Мышек: 3
...................
...................
...................
...................
..4................
...................
...................
.............D.....
...................
...................
...................
...................
...................
...................
............@......
............21.....

...................    Ход: 18
.......@...........    Кошек: 2
...................    Мышек: 3
...................
......D............
...................
...................
..4................
...........D.......
...................
...................
...................
...................
...................
...................
...................
...................
............K......
.............21....

...................    Ход: 19
.......K...........    Кошек: 2
......D............    Мышек: 2
...................
...................
...................
.............D.....
...4...............
...................
...................
...................
...................
...................
...................
...................
...................
...................
...................
.............@1....

....D..............    Ход: 20
...................    Кошек: 2
.......K...........    Мышек: 2
...................
.............D.....
...................
...................
...4...............
...................
...................
...................
...................
...................
...................
...................
...................
...................
...................
.............K.1...