Robots Musterlösung: Unterschied zwischen den Versionen

Aus Vokabulabor
Zur Navigation springen Zur Suche springen
 
(Eine dazwischenliegende Version desselben Benutzers wird nicht angezeigt)
Zeile 8: Zeile 8:
<?php
<?php


define('BLACK', '*');
define('DEFAULT_COLOR', "\t");
define('DEFAULT_COLOR', "\t");
define('WHITE', ' ');
define('WHITE', ' ');
/**
* Implements a sheet area with ascii sheet.
*/


class Sheet
class Sheet
Zeile 24: 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 clearTerminal()
    {
        echo "\x1b\x5b\x48\x1b\x5b\x32\x4a\xc";
     }
     }
     public function setRandomPosition(&$point)
     public function setRandomPosition(&$point)
Zeile 42: Zeile 44:
         $point->y = $y;
         $point->y = $y;
     }
     }
     public function show()
     public function showDrawing()
     {
     {
         $this->clearTerminal();
         $this->clearTerminal();
Zeile 51: Zeile 53:
         echo str_repeat('-', $this->width + 2), "\n";
         echo str_repeat('-', $this->width + 2), "\n";
     }
     }
     public function setPoint(int $x, int $y, string $color)
     public function setPoint(int $x, int $y, string $color = BLACK)
     {
     {
         if ($x >= 0 && $x < $this->width && $y >= 0 && $y < $this->height) {
         if ($x >= 0 && $x < $this->width && $y >= 0 && $y < $this->height) {
Zeile 76: 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 87: Zeile 89:
     public $width;
     public $width;
     public $height;
     public $height;
     public function __construct(int $x, int $y, int $width, int $height, string $color)
     public function __construct(int $x, int $y, int $width, int $height, string $color = BLACK)
     {
     {
         parent::__construct($x, $y, $color);
         parent::__construct($x, $y, $color);
Zeile 95: 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 109: Zeile 111:
{
{
     public $target;
     public $target;
    public string $color;
     public string $colorTarget;
     public string $colorTarget;
     public int $xDirection = 1;
     public int $xDirection = 1;
Zeile 133: 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);
Zeile 143: Zeile 147:
             $this->target->draw($sheet);
             $this->target->draw($sheet);
             $x = $this->x;
             $x = $this->x;
             $y = $this->y;
             $y = $this->y;  
             if (abs($x - $this->target->x) <= 1 && abs($y - $this->target->y) <= 1) {
             if ($this->target !== $x) {
                $x = $this->target->x;
                $y = $this->target->y;
            } else {
                 $x = $this->target->x < $x ? $x - 1 : $x + 1;
                 $x = $this->target->x < $x ? $x - 1 : $x + 1;
            }
            if ($this->target->y !== $y) {
                 $y = $this->target->y < $y ? $y - 1 : $y + 1;
                 $y = $this->target->y < $y ? $y - 1 : $y + 1;
             }
             }
Zeile 171: 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 188: Zeile 189:
     public array $mobiles = [];
     public array $mobiles = [];
     public Sheet $sheet;
     public Sheet $sheet;
    public $stepNo = 0;
     public function __construct(Sheet &$sheet)
     public function __construct(Sheet &$sheet)
     {
     {
Zeile 203: Zeile 203:
         }
         }
     }
     }
     public function buildBarriers(int $rows = 5, int $cols = 5)
     public function buildHouses(int $rows = 5, int $cols = 5)
     {
     {
         $width = ($this->sheet->width - 1) / $rows / 2;
         $width = ($this->sheet->width - 1) / $rows / 2;
Zeile 211: Zeile 211:
                 $x = $width / 2 + $row * 2 * $width;
                 $x = $width / 2 + $row * 2 * $width;
                 $y = $height / 2 + $col * 2 * $height;
                 $y = $height / 2 + $col * 2 * $height;
                 $item = new Rectangle($x, $y, $width, $height, '*');
                 $item = new Rectangle($x, $y, $width, $height);
                 $this->add($item, true);
                 $this->add($item, true);
             }
             }
Zeile 227: Zeile 227:
     {
     {
         $this->sheet->clearTerminal();
         $this->sheet->clearTerminal();
         $this->sheet->show();
         $this->sheet->showDrawing();
     }
     }
     public function step()
     public function step()
     {
     {
        $this->stepNo++;
        $barrier = $this->statics[0];
        if ($this->stepNo % ($barrier->width * 2) == 0) {
            foreach ($this->mobiles as $robot) {
                $robot->xDirection = -$robot->xDirection;
            }
        }
        if ($this->stepNo % ($barrier->height * 2) == 0) {
            foreach ($this->mobiles as $robot) {
                $robot->yDirection = -$robot->yDirection;
            }
        }
         $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;
     }
     }
}
}
srand(44);
$sheet = new Sheet(40, 40);
$sheet = new Sheet(30, 30);
 
$simulator = new Simulator($sheet);
$simulator = new Simulator($sheet);
$simulator->buildBarriers(2, 2);
$simulator->buildHouses(3, 3);
$simulator->buildRobots(12);
$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";