/** * Checks if coordinates are inside the field * * @param Coords $coords * @return bool */ public function has(Coords $coords) { $x = $coords->x(); if ($x < 0 || $x >= $this->width) { return false; } $y = $coords->y(); if ($y < 0 || $y >= $this->height) { return false; } return true; }
/** * @param int $width * @param int $height * @param array $shipSizes * @return Fields */ public static function generate($width, $height, array $shipSizes) { Assertion::integer($width); Assertion::integer($height); Assertion::allInteger($shipSizes); $elements = []; for ($y = 0; $y < $height; $y++) { for ($x = 0; $x < $width; $x++) { $elements[] = Field::generate($x, $y); } } $fields = Fields::create($elements); foreach ($shipSizes as $shipSize) { $attempts = 0; while (true) { if ($attempts == static::MAX_ATTEMPTS) { throw new CannotPlaceShipOnGridException(); } $direction = mt_rand(0, 1) == 0 ? 'right' : 'below'; $spot = Coords::create(mt_rand(0, $width - 1), mt_rand(0, $height - 1)); $endPoint = static::validEndpoint($fields, $spot, $shipSize, $direction); if ($endPoint === null) { $attempts++; continue; } // If we end up here the ship can fit at the determined spot $fields->place(Ship::create($spot, $endPoint)); break; } } return $fields; }
/** * @test */ public function it_should_win_the_game_when_all_ships_have_sunk() { $game = Game::create(1, 2, [2]); $result = $game->fire(Coords::fromArray(['x' => 0, 'y' => 0])); $this->assertFalse($result->isWon()); $result = $game->fire(Coords::fromArray(['x' => 0, 'y' => 1])); $this->assertTrue($result->isWon()); }
/** * @param Coords $coords * @return bool */ public function on(Coords $coords) { if ($coords->x() == $this->startPoint->x() && $coords->y() >= $this->startPoint->y() && $coords->y() <= $this->endPoint->y()) { return true; } if ($coords->y() == $this->startPoint->y() && $coords->x() >= $this->startPoint->x() && $coords->x() <= $this->endPoint->x()) { return true; } return false; }
/** * @param array $fireResult * * @return static */ public static function fromArray(array $fireResult) { return new static($fireResult['result'], Coords::fromArray($fireResult['target']), array_key_exists('x', $fireResult['startPoint']) ? Coords::fromArray($fireResult['startPoint']) : null, array_key_exists('y', $fireResult['endPoint']) ? Coords::fromArray($fireResult['endPoint']) : null); }
/** * @param Coords $coords * @return boolean */ public function at(Coords $coords) { return $this->coords->equals($coords); }
/** * fire on $location * @param string $location * @return string */ private function fire($location) { $identifier = GameIdentifier::fromString($this->id()); $game = $this->repository()->get($identifier); $coordElements = explode('.', $location); $coords = Coords::create((int) $coordElements[0], (int) $coordElements[1]); $result = $game->fire($coords); $this->repository()->save($game); echo 'Firing on ' . $location . ' in game: ' . $game->id() . PHP_EOL; echo (string) $game; return $result; }
/** * Retrieve the coords a specified distance below these coords. * * @param int $distance * * @return Coords */ public function below($distance) { return Coords::create($this->x(), $this->y() + $distance); }
<?php require __DIR__ . '/vendor/autoload.php'; $game = Wecamp\FlyingLiquorice\Domain\Game::create(10, 10); echo $game; while (true) { try { $game->fire(\Wecamp\FlyingLiquorice\Domain\Game\Coords::create(mt_rand(0, 9), mt_rand(0, 9))); } catch (Wecamp\FlyingLiquorice\Domain\Game\FieldAlreadyBeenShotException $e) { // Ignore } catch (Wecamp\FlyingLiquorice\Domain\Game\GameIsLockedException $e) { // Won the game break; } } echo $game;