<?php
header("Content-Type: text/plain");
// ООП. Кошки - мышки
// Константы
const cat = 'Cat';
const mouse = 'Mouse';
// Класс Животного (игрока)
abstract class Animal
{
// Координаты ХY
// Кол-во пропускаемых ходов
protected $restingTime = 0;
// Hp
protected $hp = 100;
// Генератор животного
public function __construct($x, $y)
{
$this->xy['x'] = $x;
$this->xy['y'] = $y;
}
// Выбор наилучшего ВариантаХода (большего веса)
public function chooseBestMoveVariant($moveVariants)
{
// Сортировка ВариантовХода по убыванию веса
function ($moveVariantA, $moveVariantB ) {
$weightA = $moveVariantA->getWeight();
$weightB = $moveVariantB->getWeight();
if ($weightA==$weightB) return 0;
return ($weightA<$weightB) ? 1 : -1;
});
return $moveVariants[0];
}
// Возвращает координаты
public function getXY()
{
return $this->xy;
}
// Установка координат
public function setXY($xy)
{
$this->xy['x'] = $xy['x'];
$this->xy['y'] = $xy['y'];
}
// Возвращает время отдыха
public function getRestingTime()
{
return $this->restingTime;
}
// Возвращает время отдыха
public function setRestingTime($moveQuantity)
{
$this->restingTime = $moveQuantity;
}
// Возвращает время отдыха
public function getHP()
{
return $this->hp;
}
// Игровой ход
abstract function move($animals, $moveVariants);
// Скорость перемещения (клеток за ход)
abstract function getSpeed();
// Возможность ходить по горизонт, вертикали, диагонали
//abstract function getMoveAbility();
// Область видимости вокруг себя
abstract function getVisionLimits();
// Оценка ходов
abstract function setRating($animals, $moveVariants);
// Исключение занятых ходов
abstract function excludingNonEmptyMove($animals, $moveVariants);
// Убийство
public function kill ()
{
$this->hp = 0;
}
}
class Mouse extends Animal
{
// Скорость перемещения (клеток за ход)
public function getSpeed()
{
return 1;
}
// Область видимости вокруг себя
public function getVisionLimits()
{
return 4;
}
// Игровой ход
public function move($animals, $moveVariants)
{
// Исключение занятых ходов
$moveVariants = $this->excludingNonEmptyMove($animals, $moveVariants);
// Исключения вариантов хода по вертикали
$moveVariants = $this->exlusionVerticalMove($moveVariants);
// Оценка ходов
$this->setRating($animals, $moveVariants);
// Выбор наилучшего хода (наибольший вес)
$bestMoveVariant = $this->chooseBestMoveVariant($moveVariants);
// Ход
$this->setXY($bestMoveVariant->getXY());
}
// Оценка ходов
public function setRating($animals, $moveVariants)
{
// Присваиваем вес
foreach ($moveVariants as $moveVariant)
{
$moveVariant->setWeight(rand(0,10)); }
}
// Метод исключения вариантов хода по вертикали
public function exlusionVerticalMove($moveVariants) {
// У вертикальных ходов координаты X Y равны по модулю, относительно текщего положения животного
foreach ($moveVariants as $key => $moveVariant) {
$moveVariantXY=$moveVariant->getXY();
// Исключаем из проверки ход на котором стоим
//echo "an x: {$this->xy['x']} y: {$this->xy['y']}\n";
//echo "mv x: {$moveVariantXY['x']} y: {$moveVariantXY['y']}\n";
if ($moveVariantXY['x'] == $this->xy['x'] &&
$moveVariantXY['y'] == $this->xy['y']) continue;
// Проверяем остальные
if (abs($moveVariantXY['x']-$this->xy['x'])==abs($moveVariantXY['y']-$this->xy['y'])) { unset($moveVariants[$key]); }
}
return $moveVariants;
}
// Исключение занятых ходов
public function excludingNonEmptyMove($animals, $moveVariants)
{
foreach ($moveVariants as $key => $moveVariant) {
$moveVariantXY=$moveVariant->getXY();
foreach ($animals as $animal) {
$animalXY=$animal->getXY();
// Исключаем из проверки ход на котором стоим
if ($animalXY['x'] == $this->xy['x'] &&
$animalXY['y'] == $this->xy['y']) continue;
// Проверяем остальные
if ($moveVariantXY['x']==$animalXY['x'] &&
$moveVariantXY['y']==$animalXY['y']) {
unset ($moveVariants[$key]); }
}
}
return $moveVariants;
}
}
class Cat extends Animal
{
// Скорость перемещения (клеток за ход)
public function getSpeed()
{
return 1;
}
// Возможность ходить по горизонт, вертикали, диагонали
public function getMoveAbility()
{
return array(true, true, true); }
// Область видимости вокруг себя
public function getVisionLimits()
{
return null;
}
// Игровой ход
public function move($animals, $moveVariants)
{
// Проверка кол-ва пропускаемых ходов
if ($this->getRestingTime()>0 ) {
// Уменьшаем счетчик пропускаемых ходов
$this->setRestingTime($this->getRestingTime()-1);
return;
}
if ($this->getRestingTime() > 0)
// Исключение занятых ходов
$moveVariants = $this->excludingNonEmptyMove($animals, $moveVariants);
// Оценка ходов
$this->setRating($animals, $moveVariants);
// Выбор наилучшего хода (наибольший вес)
$bestMoveVariant = $this->chooseBestMoveVariant($moveVariants);
// Проверка съедания мыши
$eatenMouse = $this->checkEatenMouse($animals, $bestMoveVariant);
if ($eatenMouse) $this->eatMouse($eatenMouse);
// Ход
$this->setXY($bestMoveVariant->getXY());
}
// Оценка ходов
public function setRating($animals, $moveVariants)
{
// Находим всех мышей
function ($animal) {
});
foreach ($moveVariants as $moveVariant)
{
$moveVariant->setWeight(rand(0,10));
// Если в клетке мышка, то такой ход +10 баллов
foreach ($mouses as $mouse) {
$mouseXY = $mouse->getXY();
$moveVariantXY = $moveVariant->getXY();
if ($mouseXY['x']==$moveVariantXY['x'] &&
$mouseXY['y']==$moveVariantXY['y']) {
$moveVariant->setWeight(100); //$moveVariant->getWeight() + 10
}
}
}
}
// Исключение занятых ходов
public function excludingNonEmptyMove($animals, $moveVariants)
{
foreach ($moveVariants as $key => $moveVariant) {
$moveVariantXY=$moveVariant->getXY();
// Исключаем только кошек
function ($animal) {
});
foreach ($cats as $cat) {
$catXY=$cat->getXY();
// Исключаем из проверки ход на котором стоим
if ($catXY['x'] == $this->xy['x'] &&
$catXY['y'] == $this->xy['y']) continue;
// Проверяем остальные
if ($moveVariantXY['x']==$catXY['x'] &&
$moveVariantXY['y']==$catXY['y']) {
unset ($moveVariants[$key]); }
}
}
return $moveVariants;
}
// Проверка съедания мыши
public function checkEatenMouse($animals, $bestMoveVariant)
{
$moveVariantXY=$bestMoveVariant->getXY();
// Исключаем только кошек
function ($animal) {
});
foreach ($mouses as $mouse) {
$mouseXY = $mouse->getXY();
if ($mouseXY['x'] == $moveVariantXY['x'] &&
$mouseXY['y'] == $moveVariantXY['y']) {
return $mouse;
}
}
}
// Поедание мыши
public function eatMouse ($mouse)
{
$mouse->kill();
$this->setRestingTime(2);
}
}
// Класс Животные (Игроки)
class Animals
{
private $animals = array();
public function __construct ($mousesQuantity, $catsQuantity)
{
// Создание мышей
for ($mousesQuantity; $mousesQuantity > 0; $mousesQuantity--) {
// Генераруем случайные координаты
$xy = $this->newCoordinat();
$this->animals[] = new Mouse($xy['x'], $xy['y']);
}
// Создание кошек
for ($catsQuantity; $catsQuantity > 0; $catsQuantity--) {
$xy = $this->newCoordinat();
$this->animals[] = new Cat($xy['x'], $xy['y']);
}
}
public function __clone()
{
$animalsClones = array();
foreach ($this->animals as $animal) {
$animalsClones[] = clone $animal;
}
// Заменяем массив животных массивом клонов
$this->animals = $animalsClones;
}
// Запуск цикла ходов для всех животных
public function move()
{
foreach ($this->animals as $animal) {
// Генерация всех возможных ВариантовХода
$moveVariants = fabricMoveVariants::createMoveVariants($animal);
$animal->move($this->animals, $moveVariants);
}
// Чистка убитых животных
$this->cleanUpDeadAnimals();
}
// Убираем с поля убитых животных
private function cleanUpDeadAnimals()
{
function ($animal) {
return ($animal->getHp()>0);
});
$this->animals = $liveAnimal;
}
// Функция генерации координат
private function newCoordinat()
{
$xy['x'] = rand(1, fieldSize
); $xy['y'] = rand(1, fieldSize
);
return $xy;
}
// Уничтожение животного
public function killAnimal($killingAnimal)
{
foreach ($animals as $key => $animal) {
if ($animal === $killingAnimal) unset ($animals[$key]); }
}
public function getAnimalsAsArray ()
{
return $this->animals;
}
}
// Фабрика Вариантов хода
class fabricMoveVariants {
static public function createMoveVariants ($animal)
{
// Создание новых ВариантовХода
$animalXY = $animal->getXY();
$animalSpeed = $animal->getSpeed();
// Координаты начала (верхний левый угол)
$animalSpeed = $animal->getSpeed();
do {
$start['x'] = $animalXY['x']-$animalSpeed;
$animalSpeed--;
} while ($start['x']<=0);
$animalSpeed = $animal->getSpeed();
do {
$start['y'] = $animalXY['y']-$animalSpeed;
$animalSpeed--;
} while ($start['y']<=0);
// Координаты конца (нижний правый угол)
$animalSpeed = $animal->getSpeed();
do {
$end['x'] = $animalXY['x']+$animalSpeed;
$animalSpeed--;
} while ($end['x']>fieldSize);
$animalSpeed = $animal->getSpeed();
do {
$end['y'] = $animalXY['y']+$animalSpeed;
$animalSpeed--;
} while ($end['y']>fieldSize);
// Генерация ходов
$y = $start['y'];
while ($y<=$end['y']) {
$x = $start['x'];
while ($x<=$end['x']) {
$moveVariants[] = new MoveVariant($x, $y);
$x++;
}
$y++;
}
return $moveVariants;
}
}
// Класс ВариантХода
class MoveVariant
{
// Координаты
// Вес
private $weight=0;
public function __construct ($moveX, $moveY)
{
$this->xy['x'] = $moveX;
$this->xy['y'] = $moveY;
}
// Возвращает координаты
public function getXY()
{
return $this->xy;
}
public function setWeight($weight)
{
$this->weight = $weight;
}
public function getWeight()
{
return $this->weight;
}
}
// Кдасс ИгровойРаунд
class GameRaund
{
private $animals; // Объект Животные
private $raundNum; // Номер раунда
public function __construct ($animals)
{
$this->animals = clone $animals;
}
// Представление раунда в виде псевдографики (массива строк)
public function getGameRoundAsGraphics()
{
$gameField = array(); // поле игры, содержит строки из клеток $fieldSize = fieldSize;
// Массив аватаров Животных
$avatars = array(0 => 'm', 1 => 'K');
// Формируем поле из точек
// Повторяем для каждой строки
for ($fieldSize; $fieldSize>0; $fieldSize--) {
// Заполняем строку "."
// Добавляем строку в массив
$gameField[] = $str;
}
// Получаем всех Жиаотных массивом
$animals = $this->animals->getAnimalsAsArray();
// Проходим по массиву животных
foreach ($animals as $key => $animal) {
// Узнаем координаты каждого персонажа
$xy = $animal->getXY();
// Заменяем соответствующую точку в соответствующей строке индексом мышки
$str = $gameField[$xy['y']-1];
// Мышь обозначаем носером
} else {
// Кошку буквой "K" или "@" если спит
if ($animal->getRestingTime()>0) {
} else {
}
}
$gameField[$xy['y']-1] = $str;
}
/*
// Добавляем инфу
foreach ($animals as $key => $animal) {
$xy = $animal->getXY();
$str = $gameField[$key] . " мышь: " . $key . " x: " . $xy['x'] . " y: " . $xy['y'];
$gameField[$key] = $str;
}*/
return $gameField;
}
public function getAnimals ()
{
return $this->animals;
}
}
// Класс ГеймСет (Игра)
class GameSet
{
private $raunds = array(); private $animals;
public function __construct ($mousesQuantity, $catsQuantity)
{
$this->animals = new Animals ($mousesQuantity, $catsQuantity);
// Начальный раунд (раунд: 0)
$this->raunds[] = new GameRaund($this->animals);
}
// Новый игровой раунд
public function newRaund($raundNum)
{
// Ход животных
$this->animals->move();
// Новый раунд номер $raundNum
$this->raunds[] = new GameRaund($this->animals);
}
// Печать раунда
public function printGameRound($raundNum)
{
// Получаем раунд в виде псевдографики (массива строк)
$printingRaund = $this->raunds[$raundNum]->getGameRoundAsGraphics();
// Узнаем че по кошкам (мышам)
$animals = $this->raunds[$raundNum]->getAnimals()->getAnimalsAsArray();
function ($animal) {
});
function ($animal) {
});
$mousesNum = count($mouses);
// Выводим на экран массив построчно
foreach ($printingRaund as $key => $str) {
if ($key == 0) {
echo $str . " " . "Ход: " . "{$raundNum}\n";
} else if ($key == 1) {
echo $str . " " . "Кошек: " . "$catsNum\n";
} else if ($key == 2) {
echo $str . " " . "Мышек: " . "$mousesNum\n";
} else {
echo "{$str}\n";
}
}
echo "\n";
}
public function getRaund($raundNum)
{
return $this->raunds[$raundNum];
}
}
// Создание новой игры
function createNewGame ()
{
// Вводные данные для создания новой игры
$raundsQuantity = 20;
$mousesQuantity = 4;
$catsQuantity = 2;
$fieldSize = 19;
define('fieldSize', $fieldSize);
// Создание новой игры (раунд: 0)
$gameSet= new GameSet($mousesQuantity, $catsQuantity);
// Вывести раунд на печать
$gameSet->printGameRound(0);
// Цикл раундов (начиная с первого)
for ($raundNum=1; $raundNum<=$raundsQuantity; $raundNum++) {
// Новый раунд
$gameSet->newRaund($raundNum);
// Вывести раунд на печатьs
$gameSet->printGameRound($raundNum);;
}
}
createNewGame();
?>