Robots Musterlösung: Unterschied zwischen den Versionen
Zur Navigation springen
Zur Suche springen
(4 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
Zeile 11: | Zeile 11: | ||
define('DEFAULT_COLOR', "\t"); | define('DEFAULT_COLOR', "\t"); | ||
define('WHITE', ' '); | define('WHITE', ' '); | ||
class Sheet | class Sheet | ||
Zeile 25: | Zeile 21: | ||
$this->width = $width; | $this->width = $width; | ||
$this->height = $height; | $this->height = $height; | ||
$this->clearSheet(); | |||
} | |||
public function clearTerminal() | |||
{ | |||
echo "\x1b\x5b\x48\x1b\x5b\x32\x4a\xc"; | |||
} | |||
public function clearSheet() | |||
{ | |||
$this->lines = []; | $this->lines = []; | ||
for ($y = 0; $y < $this->height; $y++) { | for ($y = 0; $y < $this->height; $y++) { | ||
array_push($this->lines, str_repeat(' ', $this->width)); | array_push($this->lines, str_repeat(' ', $this->width)); | ||
} | } | ||
} | } | ||
public function setRandomPosition(&$point) | public function setRandomPosition(&$point) | ||
Zeile 43: | Zeile 44: | ||
$point->y = $y; | $point->y = $y; | ||
} | } | ||
public function | public function showDrawing() | ||
{ | { | ||
$this->clearTerminal(); | $this->clearTerminal(); | ||
Zeile 77: | Zeile 78: | ||
public function draw(Sheet &$sheet, string $color = DEFAULT_COLOR) | public function draw(Sheet &$sheet, string $color = DEFAULT_COLOR) | ||
{ | { | ||
if ($color == DEFAULT_COLOR) { | if ($color == DEFAULT_COLOR){ | ||
$color = $this->color; | $color = $this->color; | ||
} | } | ||
Zeile 96: | Zeile 97: | ||
public function draw(Sheet &$sheet, string $color = DEFAULT_COLOR) | public function draw(Sheet &$sheet, string $color = DEFAULT_COLOR) | ||
{ | { | ||
if ($color === DEFAULT_COLOR) { | if ($color === DEFAULT_COLOR){ | ||
$color = $this->color; | $color = $this->color; | ||
} | } | ||
Zeile 110: | Zeile 111: | ||
{ | { | ||
public $target; | public $target; | ||
public string $color; | |||
public string $colorTarget; | public string $colorTarget; | ||
public int $xDirection = 1; | public int $xDirection = 1; | ||
Zeile 134: | Zeile 136: | ||
$this->yDirection = -1; | $this->yDirection = -1; | ||
} | } | ||
} | } | ||
public function move(Sheet &$sheet): bool | public function move(Sheet &$sheet): bool | ||
{ | { | ||
$rc = false; | $rc = false; | ||
$x = -1; | |||
$y = -1; | |||
if ($this->target->x == $this->x && $this->target->y == $this->y) { | if ($this->target->x == $this->x && $this->target->y == $this->y) { | ||
// $sheet->setRandomPosition($this->target, $sheet); | // $sheet->setRandomPosition($this->target, $sheet); | ||
} else { | } else { | ||
$this->target->draw($sheet); | |||
$x = $this->x; | $x = $this->x; | ||
$y = $this->y; | $y = $this->y; | ||
if ($this->target | if ($this->target !== $x) { | ||
$x = $this->target->x < $x ? $x - 1 : $x + 1; | $x = $this->target->x < $x ? $x - 1 : $x + 1; | ||
} | } | ||
Zeile 170: | Zeile 174: | ||
return $rc; | return $rc; | ||
} | } | ||
public function setTarget(Sheet &$sheet){ | |||
public function setTarget(Sheet &$sheet) | if ($this->target == null){ | ||
if ($this->target == null) { | |||
$this->target = new Point(0, 0, $this->colorTarget); | $this->target = new Point(0, 0, $this->colorTarget); | ||
} else { | } else { | ||
Zeile 201: | Zeile 203: | ||
} | } | ||
} | } | ||
public function | public function buildHouses(int $rows = 5, int $cols = 5) | ||
{ | { | ||
$width = ($this->sheet->width - 1) / $rows / 2; | $width = ($this->sheet->width - 1) / $rows / 2; | ||
Zeile 225: | Zeile 227: | ||
{ | { | ||
$this->sheet->clearTerminal(); | $this->sheet->clearTerminal(); | ||
$this->sheet-> | $this->sheet->showDrawing(); | ||
} | } | ||
public function step() | public function step() | ||
Zeile 231: | Zeile 233: | ||
$moves = 0; | $moves = 0; | ||
foreach ($this->mobiles as $car) { | foreach ($this->mobiles as $car) { | ||
if ($car->move($this->sheet)) { | if ($car->move($this->sheet)){ | ||
$moves++; | $moves++; | ||
} | }; | ||
} | } | ||
return $moves > 0; | return $moves > 0; | ||
Zeile 242: | Zeile 243: | ||
$simulator = new Simulator($sheet); | $simulator = new Simulator($sheet); | ||
$simulator-> | $simulator->buildHouses(3, 3); | ||
$simulator->buildRobots(5); | $simulator->buildRobots(5); | ||
$simulator->show(); | $simulator->show(); | ||
$rounds = 0; | $rounds = 0; | ||
while ($simulator->step()) { | while ($simulator->step()){ | ||
$rounds++; | $rounds++; | ||
$simulator->show(); | $simulator->show(); | ||
sleep(1); | sleep(1); | ||
} | } | ||
echo "== ready after $rounds rounds\n"; | echo "== ready after $rounds rounds\n";</syntaxhighlight> | ||
</syntaxhighlight> |
Aktuelle Version vom 3. Dezember 2023, 17:39 Uhr
Links
Zielsetzung
Dies ist eine funktionierende Lösung der Robotersimulaltion.
<?php
define('BLACK', '*');
define('DEFAULT_COLOR', "\t");
define('WHITE', ' ');
class Sheet
{
public array $lines;
public int $width;
public int $height;
public function __construct(int $width = 80, int $height = 40)
{
$this->width = $width;
$this->height = $height;
$this->clearSheet();
}
public function clearTerminal()
{
echo "\x1b\x5b\x48\x1b\x5b\x32\x4a\xc";
}
public function clearSheet()
{
$this->lines = [];
for ($y = 0; $y < $this->height; $y++) {
array_push($this->lines, str_repeat(' ', $this->width));
}
}
public function setRandomPosition(&$point)
{
do {
$x = rand(0, $this->width - 1);
$y = rand(0, $this->height - 1);
} while ($this->isOccupied($x, $y));
$point->x = $x;
$point->y = $y;
}
public function showDrawing()
{
$this->clearTerminal();
echo str_repeat('-', $this->width + 2), "\n";
for ($y = $this->height - 1; $y >= 0; $y--) {
echo '|', $this->lines[$y], "|\n";
}
echo str_repeat('-', $this->width + 2), "\n";
}
public function setPoint(int $x, int $y, string $color = BLACK)
{
if ($x >= 0 && $x < $this->width && $y >= 0 && $y < $this->height) {
$this->lines[$y][$x] = $color;
}
}
public function isOccupied(int $x, int $y): bool
{
$color = $this->lines[$y][$x];
return $color !== WHITE && $color < "a";
}
}
class Point
{
public int $x;
public int $y;
public string $color;
public function __construct(int $x, int $y, string $color)
{
$this->x = $x;
$this->y = $y;
$this->color = $color;
}
public function draw(Sheet &$sheet, string $color = DEFAULT_COLOR)
{
if ($color == DEFAULT_COLOR){
$color = $this->color;
}
$sheet->setPoint($this->x, $this->y, $color);
}
}
class Rectangle extends Point
{
public $width;
public $height;
public function __construct(int $x, int $y, int $width, int $height, string $color = BLACK)
{
parent::__construct($x, $y, $color);
$this->width = $width;
$this->height = $height;
}
public function draw(Sheet &$sheet, string $color = DEFAULT_COLOR)
{
if ($color === DEFAULT_COLOR){
$color = $this->color;
}
for ($x = $this->x; $x < $this->x + $this->width; $x++) {
for ($y = $this->y; $y <= $this->y + $this->height; $y++) {
$sheet->setPoint($x, $y, $color);
}
}
}
}
class Robot extends Point
{
public $target;
public string $color;
public string $colorTarget;
public int $xDirection = 1;
public int $yDirection = 1;
public function __construct(string $color, Sheet &$sheet)
{
parent::__construct(0, 0, $color);
$this->target = null;
$this->color = $color;
$this->colorTarget = strtolower($color);
$sheet->setRandomPosition($this);
$this->setTarget($sheet);
}
public function checkDirection(Sheet &$sheet)
{
if ($this->x <= 0) {
$this->xDirection = 1;
} elseif ($this->x >= $sheet->width - 1) {
$this->xDirection = -1;
}
if ($this->y <= 0) {
$this->yDirection = 1;
} elseif ($this->y >= $sheet->height - 1) {
$this->yDirection = -1;
}
}
public function move(Sheet &$sheet): bool
{
$rc = false;
$x = -1;
$y = -1;
if ($this->target->x == $this->x && $this->target->y == $this->y) {
// $sheet->setRandomPosition($this->target, $sheet);
} else {
$this->target->draw($sheet);
$x = $this->x;
$y = $this->y;
if ($this->target !== $x) {
$x = $this->target->x < $x ? $x - 1 : $x + 1;
}
if ($this->target->y !== $y) {
$y = $this->target->y < $y ? $y - 1 : $y + 1;
}
$this->checkDirection($sheet);
if ($sheet->isOccupied($x, $y)) {
$x = $this->x + $this->xDirection;
$y = $this->y;
if ($sheet->isOccupied($x, $y)) {
$x = $this->x;
$y = $this->y + $this->yDirection;
}
}
if (!$sheet->isOccupied($x, $y)) {
// Remove current point:
$this->draw($sheet, WHITE);
$this->x = $x;
$this->y = $y;
$this->draw($sheet);
$rc = true;
}
}
return $rc;
}
public function setTarget(Sheet &$sheet){
if ($this->target == null){
$this->target = new Point(0, 0, $this->colorTarget);
} else {
$sheet->setPoint($this->target->x, $this->target->y, WHITE);
}
$sheet->setRandomPosition($this->target);
$sheet->setPoint($this->target->x, $this->target->y, $this->colorTarget);
}
}
class Simulator
{
public array $statics = [];
public array $mobiles = [];
public Sheet $sheet;
public function __construct(Sheet &$sheet)
{
$this->sheet = $sheet;
}
public function add($item, bool $isStatic)
{
if ($isStatic) {
array_push($this->statics, $item);
$item->draw($this->sheet);
} else {
array_push($this->mobiles, $item);
$item->draw($this->sheet);
}
}
public function buildHouses(int $rows = 5, int $cols = 5)
{
$width = ($this->sheet->width - 1) / $rows / 2;
$height = ($this->sheet->height - 1) / $cols / 2;
for ($row = 0; $row < $rows; $row++) {
for ($col = 0; $col < $cols; $col++) {
$x = $width / 2 + $row * 2 * $width;
$y = $height / 2 + $col * 2 * $height;
$item = new Rectangle($x, $y, $width, $height);
$this->add($item, true);
}
}
}
public function buildRobots(int $count)
{
$names = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for ($ix = 0; $ix < $count; $ix++) {
$car = new Robot($names[$ix], $this->sheet);
$this->add($car, false);
}
}
public function show()
{
$this->sheet->clearTerminal();
$this->sheet->showDrawing();
}
public function step()
{
$moves = 0;
foreach ($this->mobiles as $car) {
if ($car->move($this->sheet)){
$moves++;
};
}
return $moves > 0;
}
}
$sheet = new Sheet(40, 40);
$simulator = new Simulator($sheet);
$simulator->buildHouses(3, 3);
$simulator->buildRobots(5);
$simulator->show();
$rounds = 0;
while ($simulator->step()){
$rounds++;
$simulator->show();
sleep(1);
}
echo "== ready after $rounds rounds\n";