Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 44 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,48 +1,61 @@
Chess
=====
Шахматы
=======

`chess.php` is a CLI program that displays chess games.
It receives players' moves as arguments and prints the board state
with figure positions after those moves.
`chess.php` — консольный проигрыватель шахматных партий.
Программа получает ходы игроков в качестве аргументов и выводит
состояние доски с фигурами после этих ходов.

Example:
Например:

`php chess.php e2-e4 e7-e5`
```bash
php chess.php e2-e4 e7-e5
```
```
8 ♜♞♝♛♚♝♞♜
7 ♟♟♟♟-♟♟♟
6 --------
5 ----♟---
4 ----♙---
3 --------
2 ♙♙♙♙-♙♙♙
1 ♖♘♗♕♔♗♘♖
abcdefgh
```

<img src="example.png" width="405" height="349" alt="Example of the program execution"/>

Validation:
В текущем виде `chess.php` никак не проверяет правильность ходов.

Currently `chess.php` does nothing to verify chess rules in those moves.
And you don't need to implement each rule for the game.
## Задача 1

Add only the validations required by the tasks below.
Задача 1: дописать программу таким образом, чтобы она выкидывала исключение
при нарушении очерёдности хода (например, два раза подряд ход белых).

## Task 1
Чтобы проверить корректность решения, запустите тесты:

Task 1: modify the program so that it throws an exception
when player move order is wrong (e.g. if whites make two moves in a row).
```bash
./vendor/bin/phpunit --group=rotation
```

To verify your solution, run tests:
## Задача 2

$ ./vendor/bin/phpunit --group=rotation
Задача 2: дописать программу таким образом, чтобы она выкидывала исключение
при нарушении правил хода пешкой (pawn).

## Task 2
Чтобы проверить корректность решения, запустите тесты:

Task 2: modify the program so that it throws an exception
when a pawn makes an illegal move.
```bash
./vendor/bin/phpunit --group=pawn
```

To verify your solution, run tests:
В тестах проверяются только ходы пешками, для других фигур валидацию ходов делать не нужно.

$ ./vendor/bin/phpunit --group=pawn
### Как ходит пешка

Tests only move pawns, other figures are not moved,
so you are safe to ignore non-pawn specifics in your solution.
* Пешка может ходить вперёд (по вертикали) на одну клетку;
* Если пешка ещё ни разу не ходила, она может пойти вперёд на две клетки;
* Пешка не может перепрыгивать через другие фигуры;
* Пешка может бить фигуры противника только по диагонали вперёд на одну клетку;
* Также существует взятие на проходе, но им можно пренебречь :)

### Chess pawn rules

* A pawn can move forward (vertically) by 1 square;
* The first time a pawn moves, it may move forward by 2 squares instead of 1;
* Pawns cannot jump over other figures;
* Pawns can capture enemy figures only by diagonally moving 1 square forward;
* En passant capture also exists, but don't bother about it :)
## Комментарии к выполнению
Класс Figure изменил на абстрактный класс и добавил абстрактный метод. Сделал так потому что если надо будет добавить правила для других фигур то это решение выглядит лучше чем добавления интерфейса каждой фигуре. Во всех фигурах кроме пешки метод для описания правил пустой. Логика работы метода следующая, если ход соответствует одной из проверок то метод просто завершает работу, если нет то метод выбрасывает исключение. В начале поставил базовую проверку (возможно избыточна) для проверки того что пешка не пошла более чем на 2 клетки.
11 changes: 9 additions & 2 deletions src/Bishop.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
<?php

class Bishop extends Figure {
public function __toString() {
class Bishop extends Figure
{
public function __toString()
{
return $this->isBlack ? '♝' : '♗';
}

public function checkMove(Path $path)
{
// TODO: Implement checkMove() method.
}
}
46 changes: 38 additions & 8 deletions src/Board.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
<?php

class Board {
class Board
{
private $figures = [];

public function __construct() {
private ?Figure $lastMoveFigure;

public function __construct()
{
$this->figures['a'][1] = new Rook(false);
$this->figures['b'][1] = new Knight(false);
$this->figures['c'][1] = new Bishop(false);
Expand Down Expand Up @@ -41,23 +45,49 @@ public function __construct() {
$this->figures['h'][8] = new Rook(true);
}

public function move($move) {
public function move($move)
{
if (!preg_match('/^([a-h])(\d)-([a-h])(\d)$/', $move, $match)) {
throw new \Exception("Incorrect move");
}

$xFrom = $match[1];
$yFrom = $match[2];
$xTo = $match[3];
$yTo = $match[4];
$xTo = $match[3];
$yTo = $match[4];

if (!isset($this->figures[$xFrom][$yFrom])) {
return;
}

/** @var Figure $movingFigure */
$movingFigure = $this->figures[$xFrom][$yFrom];

$isBlackLastMoveFigure = isset($this->lastMoveFigure) ? $this->lastMoveFigure->isBlack() : true;

if (isset($this->figures[$xFrom][$yFrom])) {
$this->figures[$xTo][$yTo] = $this->figures[$xFrom][$yFrom];
if ($isBlackLastMoveFigure === $movingFigure->isBlack()) {
throw new \Exception("Incorrect color");
}

$movingFigure->checkMove(
new Path(
figures: $this->figures,
xFrom: $xFrom,
yFrom: $yFrom,
xTo: $xTo,
yTo: $yTo
)
);

$this->lastMoveFigure = $movingFigure;

$this->figures[$xTo][$yTo] = $movingFigure;

unset($this->figures[$xFrom][$yFrom]);
}

public function dump() {
public function dump()
{
for ($y = 8; $y >= 1; $y--) {
echo "$y ";
for ($x = 'a'; $x <= 'h'; $x++) {
Expand Down
18 changes: 18 additions & 0 deletions src/DirectionMovement.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

enum DirectionMovement
{
case Up;
case Right;
case Down;
case Left;

case UpLeft;
case UpRight;
case DownLeft;
case DownRight;

case Indefinite;
}
16 changes: 13 additions & 3 deletions src/Figure.php
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
<?php

class Figure {
abstract class Figure
{
protected $isBlack;

public function __construct($isBlack) {
public function __construct($isBlack)
{
$this->isBlack = $isBlack;
}

/** @noinspection PhpToStringReturnInspection */
public function __toString() {
public function __toString()
{
throw new \Exception("Not implemented");
}

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

abstract public function checkMove(Path $path);
}
11 changes: 9 additions & 2 deletions src/King.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
<?php

class King extends Figure {
public function __toString() {
class King extends Figure
{
public function __toString()
{
return $this->isBlack ? '♚' : '♔';
}

public function checkMove(Path $path)
{
// TODO: Implement checkMove() method.
}
}
11 changes: 9 additions & 2 deletions src/Knight.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
<?php

class Knight extends Figure {
public function __toString() {
class Knight extends Figure
{
public function __toString()
{
return $this->isBlack ? '♞' : '♘';
}

public function checkMove(Path $path)
{
// TODO: Implement checkMove() method.
}
}
Loading