PHP

POO PHP : exemples de classes avec un challenge débutant

Un bon exercice pour mettre en pratique les principes de la POO.

→ Corrigé du Challenge : Batmobile et IA

La plupart des challenges de Tainix peuvent être réalisés en créant un seul programme. Créer des classes n’est pas obligatoire. Mais Tainix, c’est aussi l’occasion de s’entrainer ! Illustration ici avec un challenge débutant que l’on va résoudre en différents objets en PHP.

V1, sans classe

$reponse = '';

$ennemisDetails = [];
foreach ($ennemis as $ennemi) {
	[$position, $pv] = sscanf($ennemi, 'x:%d pv:%d');
	$ennemisDetails[$position] = $pv;
}

ksort($ennemisDetails);

$batmobile = 0;
foreach ($ennemisDetails as $position => $pv) {
	$nbDeplacements = ($position - $batmobile);
	$reponsereponse .= str_repeat('D', $nbDeplacements);

	$batmobile = $position;

	$nbFire = ceil($pv / 10);
	$reponse .= str_repeat('F', $nbFire);
}

Explications

On commence par parcourir les ennemis pour extraire les données importantes.

On utilise la fonction sscanf, qui permet d’extraire les données selon leur format. Là on définit, qu’il y a « x: » puis un nombre (%d), puis  » pv: », puis un autre nombre (%d). Et on utilise une double attribution pour renseigner à la fois $position et $pv.

On crée donc un nouveau tableau, indexé par la position.

La fonction ksort, qui fonctionne par référence, me permet de trier selon les cles (keys) du tableau.

La batmobile démarre en position 0.

Je parcours à nouveau chaque ennemi.

Le nombre de déplacement vers la Droite correspond à la différence entre la position de l’ennemi et la position courante de la batmobile. Puis elle avance.

Le nombre de coup de F correspond à l’arrondi supérieur des points de vie de l’ennemi divisés par 10.

J’utilise la fonction str_repeat pour répéter mes caractères D ou F.

V2, avec des classes

final class Enemy
{
	private int $position;
	private int $pv;

	public function __construct(string $informations)
	{
		[$this->position, $this->pv] = sscanf($informations, 'x:%d pv:%d');
	}

	public function getPosition(): int
	{
		return $this->position;
	}

	public function getPv(): int
	{
		return $this->pv;
	}
}

final class Enemies
{
	private array $enemies;

	public function __construct(array $informations)
	{
		foreach ($informations as $enemy) {
			$this->enemies[] = new Enemy($enemy);
		}

		usort($this->enemies, [$this, 'sortEnemis']);
	}

	public function sortEnemis(Enemy $e1, Enemy $e2): int
	{
		return ($e1->getPosition() < $e2->getPosition()) ? -1 : 1;
	}

	public function getEnemies(): array
	{
		return $this->enemies;
	}
}

final class Batmobile
{
	private const INSTRUCTION_MOVE = 'D';
	private const INSTRUCTION_FIRE = 'F';
	private const POWER_FIRE = 10;

	private $position = 0;

	public function getInstructionsToMove(int $position): string
	{
		$distance = $position - $this->position;
		$this->move($distance);

		return str_repeat(
			self::INSTRUCTION_MOVE,
			$distance
		);
	}

	private function move(int $distance): void
	{
		$this->position += $distance;
	}

	public function getInstructionsToFire(int $pv): string
	{
		return str_repeat(
			self::INSTRUCTION_FIRE,
			ceil($pv / self::POWER_FIRE)
		);
	}
}

Explications

Je crée 3 classes.

La classe Enemy traite les informations via sscanf lors de la construction.

La classe Enemies regroupe tous les Enemy. Elle utilise usort avec la méthode dédiée sortEnemis, qui permet de créer une méthode de tri spécifique. Ici je vais donc pouvoir trier mes ennemis selon leur attribut position.

La classe Batmobile a quelques constantes liées à l’énoncé du challenge. Elle a ensuite 2 méthodes publiques « getInstructions… » qui vont retourner les instructions permettant de déplacer ou de faire feu. La position courante de la batmobile est mise à jour via la méthode privée move.

V2, code principal

$reponse = '';

$batmobile = new Batmobile;
$enemies = new Enemies($data['ennemis']);

foreach ($enemies->getEnemies() as $enemy) {
	$reponse .= $batmobile->getInstructionsToMove($enemy->getPosition());
	$reponse .= $batmobile->getInstructionsToFire($enemy->getPv());
}

echo $reponse;

Aller + loin

D’autres techniques de parsing en PHP

D’autres challenges Débutant qui se prêtent bien à la programmation orientée objet :


Qui a codé ce superbe contenu ?


Ta newsletter chaque mois

Corrigés, challenges, actualités, veille technique... aucun spam.