<?php
abstract class Animal
{
protected $x;
protected $y;
protected $icon;
protected $field;
public function __construct($coordinateX, $coordinateY, $symbol)
{
$this->x = $coordinateX;
$this->y = $coordinateY;
$this->icon = $symbol;
}
public function getCoordinateX()
{
return $this->x;
}
public function getCoordinateY()
{
return $this->y;
}
public function showCoordinates()
{
echo "Координата X = [$this->x] ";
echo "Координата Y = [$this->y]";
}
public function getIcon()
{
return $this->icon;
}
public function moveX($x)
{
if (($this->field->isXOnMap($this->x + $x)) && !$this->field->checkTile($this->x + $x, $this->y)) {
$this->x = $this->x + $x;
}
}
public function moveY($y)
{
if (($this->field->isYOnMap($this->y + $y)) && !$this->field->checkTile($this->x, $this->y + $y)) {
$this->y = $this->y + $y;
}
}
public function setField(GameField $field)
{
$this->field = $field;
}
public function unsetField()
{
$this->field = null;
}
}
class Mouse extends Animal
{
public function findAllCats()
{
$animals = $this->field->shareAnimals();
foreach ($animals as $animal) {
if ($animal instanceof Cat
&& (abs($this->x - $animal->getCoordinateX()) <= 9 || abs($this->y - $animal->getCoordinateY()) <= 9)) { $cats[] = $animal;
}
}
return $cats;
}
public function defineAllAvaibleTurns()
{
'x' => 1,
'y' => 0,
'score' => INF
),
'x' => -1,
'y' => 0,
'score' => INF
),
'x' => 0,
'y' => -1,
'score' => INF
),
'x' => 0,
'y' => 1,
'score' => INF
)
);
'x' => 0,
'y' => 0,
'score' => 1
)
);
foreach ($ways as $key => $value) {
if ($this->field->isXOnMap($this->x + $value['x']) && $this->field->isYOnMap($this->y + $value['y']) && !$this->field->checkTile($this->x + $value['x'], $this->y + $value['y'])) {
$list[$key] = $value;
}
}
return $list;
}
public function calculateScore($list)
{
$cats = $this->findAllCats();
$previousUp = INF;
$previousDown = INF;
$previousRight = INF;
$previousLeft = INF;
foreach ($cats as $cat) {
$differenceX = $this->x - $cat->getCoordinateX();
$differenceY = $this->y - $cat->getCoordinateY();
if (abs($differenceX) > abs($differenceY) && $differenceX < 0 && abs($differenceX) < $previousUp && array_key_exists('up', $list)) { $list['up']['score'] = abs($differenceX); $previousUp = abs($differenceX);
} elseif (abs($differenceX) > abs($differenceY) && $differenceX > 0 && abs($differenceX) < $previousDown && array_key_exists('down', $list)) { $list['down']['score'] = abs($differenceX); $previousDown = abs($differenceX); } elseif (abs($differenceX) < abs($differenceY) && $differenceY < 0 && abs($differenceY) < $previousRight && array_key_exists('right', $list)) { $list['right']['score'] = abs($differenceY); $previousRight = abs($differenceY);
} elseif (abs($differenceX) < abs($differenceY) && $differenceY > 0 && abs($differenceY) < $previousLeft && array_key_exists('left', $list)) { $list['left']['score'] = abs($differenceY); $previousLeft = abs($differenceY); }
}
return $list;
}
public function chooseBestTurn()
{
$list = $this->calculateScore($this->defineAllAvaibleTurns());
$turn = 0;
$previous = 0;
foreach ($list as $key => $value) {
if ($value['score'] > $previous) {
$turn = $value;
}
}
return $turn;
}
public function makeMove()
{
$turn = $this->chooseBestTurn();
$this->moveX($turn['x']);
$this->moveY($turn['y']);
}
}
class Cat extends Animal
{
protected $sleepCount = 0;
protected $moveCount = 0;
public function getIcon()
{
if ($this->sleepCount == 0) {
return parent::getIcon();
} else {
return "@";
}
}
public function fallAsleep()
{
$this->sleepCount = 1;
$this->moveCount = 0;
}
public function move($x, $y)
{
if ($this->sleepCount == 0) {
if (!($this->field->checkTile($this->x + $x, $this->y + $y) instanceof Cat)) {
$this->x = $this->x + $x;
$this->y = $this->y + $y;
$this->moveCount++;
}
if ($this->moveCount == 8) {
$this->fallAsleep();
}
$tile = $this->field->checkTile($this->x, $this->y);
if ($tile instanceof Mouse) {
$this->field->killMouse($tile->getCoordinateX(), $tile->getCoordinateY());
$this->fallAsleep();
}
}
else {
$this->sleepCount--;
}
}
public function makeMove()
{
$x = 0;
$y = 0;
$target = $this->findClosestMouse();
if ($target) {
if ($target->getCoordinateX() > $this->x) {
$x = 1;
} elseif ($target->getCoordinateX() < $this->x) {
$x = -1;
}
if ($target->getCoordinateY() > $this->y) {
$y = 1;
} elseif ($target->getCoordinateY() < $this->y) {
$y = -1;
}
$this->move($x, $y);
}
}
public function findClosestMouse()
{
$previous = INF;
$target = 0;
foreach ($this->field->shareAnimals() as $animal) {
if (!($animal instanceof Mouse)) {
continue;
}
$distance = abs($this->x - $animal->getCoordinateX()) + abs($this->y - $animal->getCoordinateY()); if ($distance < $previous) {
$target = $animal;
$previous = $distance;
}
}
if ($target) {
return $target;
}
}
}
class GameField
{
protected $field;
protected $animals = array(); protected $height;
protected $width;
public function __construct($height, $width)
{
$this->height = $height;
$this->width = $width;
}
public function printField()
{
foreach ($this->animals as $animal) {
$x = $animal->getCoordinateX();
$y = $animal->getCoordinateY();
$this->field[$x][$y] = $animal->getIcon();
}
foreach ($this->field as $value) {
foreach ($value as $dot) {
echo $dot;
}
echo "\n";
}
}
public function acquireAnimal(Animal $animal)
{
$this->animals[] = $animal;
$animal->setField($this);
}
public function shareAnimals()
{
return $this->animals;
}
public function shareHeight()
{
return $this->height - 1;
}
public function shareWidth()
{
return $this->width - 1;
}
public function killMouse($x, $y)
{
for ($i = 0; $i < count($this->animals); $i++) {
if ($this->animals[$i] instanceof Mouse && $this->animals[$i]->getCoordinateX() == $x && $this->animals[$i]->getCoordinateY() == $y) {
$this->animals[$i]->unsetField();
unset($this->animals[$i]); }
}
}
public function checkTile($x, $y)
{
foreach ($this->animals as $animal) {
if ($animal->getCoordinateX() == $x && $animal->getCoordinateY() == $y) {
return $animal;
}
}
return false;
}
public function isXOnMap($x)
{
if ($x < 0 || $x > ($this->height - 1)) {
return false;
} else {
return true;
}
}
public function isYOnMap($y)
{
if ($y < 0 || $y > ($this->width - 1)) {
return false;
} else {
return true;
}
}
public function testTheKitty()
{
foreach ($this->animals as $animal) {
if ($animal instanceof Cat) {
$animal->makeMove();
}
}
foreach ($this->animals as $animal) {
if ($animal instanceof Mouse) {
$animal->makeMove();
}
}
}
}
$test = new GameField(7, 7);
$mouse1 = new Mouse(3, 1, "1");
$mouse2 = new Mouse(5, 2, "2");
$kitty = new Cat(6, 6, "K");
$kitty2 = new Cat(5, 5, "k");
$test->acquireAnimal($mouse1);
$test->acquireAnimal($mouse2);
$test->acquireAnimal($kitty);
$test->acquireAnimal($kitty2);
$test->printField();
echo "\n";
for ($i = 0; $i < 40; $i++) {
$test->testTheKitty();
$test->printField();
echo "\n";
}