Robots Musterlösung: Unterschied zwischen den Versionen

Aus Vokabulabor
Zur Navigation springen Zur Suche springen
(Die Seite wurde neu angelegt: „= Links = * Robots = Zielsetzung = Dies ist eine funktionierende Lösung der Robotersimulaltion. <syntaxhighlight lang="php"> <?php define('BLACK', '*'); define('DEFAULT_COLOR', "\t"); define('WHITE', ' '); →‎* * Implements a sheet area with ascii sheet.: class Sheet { public array $lines; public int $width; public int $height; public function __construct(int $width = 80, int $height = 40) { $this->width = $width;…“)
 
Zeile 25: Zeile 25:
         $this->width = $width;
         $this->width = $width;
         $this->height = $height;
         $this->height = $height;
         $this->clearSheet();
         $this->lines = [];
        for ($y = 0; $y < $this->height; $y++) {
            array_push($this->lines, str_repeat(' ', $this->width));
        }
     }
     }
     public function clearTerminal()
     public function clearTerminal()
     {
     {
         echo "\x1b\x5b\x48\x1b\x5b\x32\x4a\xc";
         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)
     public function setRandomPosition(&$point)
Zeile 48: Zeile 43:
         $point->y = $y;
         $point->y = $y;
     }
     }
     public function showDrawing()
     public function show()
     {
     {
         $this->clearTerminal();
         $this->clearTerminal();
Zeile 82: Zeile 77:
     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 101: Zeile 96:
     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 115: Zeile 110:
{
{
     public $target;
     public $target;
    public string $color;
     public string $colorTarget;
     public string $colorTarget;
     public int $xDirection = 1;
     public int $xDirection = 1;
Zeile 145: Zeile 139:
     {
     {
         $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 {
             $x = $this->x;
             $x = $this->x;
             $y = $this->y;  
             $y = $this->y;
             if ($this->target !== $x) {
             if ($this->target->x !== $x) {
                 $x = $this->target->x < $x ? $x - 1 : $x + 1;
                 $x = $this->target->x < $x ? $x - 1 : $x + 1;
             }
             }
Zeile 158: Zeile 150:
                 $y = $this->target->y < $y ? $y - 1 : $y + 1;
                 $y = $this->target->y < $y ? $y - 1 : $y + 1;
             }
             }
             for ($round = 1; $x >= 0 && $round < 3; $round++) {
             $this->checkDirection($sheet);
                 $this->checkDirection($sheet);
            if ($sheet->isOccupied($x, $y)) {
                 $x = $this->x + $this->xDirection;
                $y = $this->y;
                 if ($sheet->isOccupied($x, $y)) {
                 if ($sheet->isOccupied($x, $y)) {
                     $x = $this->x + $this->xDirection;
                     $x = $this->x;
                    $y = $this->y;
                     $y = $this->y + $this->yDirection;
                     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;
                    break;
                 }
                 }
            }
            if (!$sheet->isOccupied($x, $y)) {
                // Remove current point:
                $this->draw($sheet, WHITE);
                $this->x = $x;
                $this->y = $y;
                $this->draw($sheet);
                $rc = true;
             }
             }
         }
         }
Zeile 182: Zeile 171:
     }
     }


     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 211: Zeile 201:
         }
         }
     }
     }
     public function buildHouses(int $rows = 5, int $cols = 5)
     public function buildBarriers(int $rows = 5, int $cols = 5)
     {
     {
         $width = ($this->sheet->width - 1) / $rows / 2;
         $width = ($this->sheet->width - 1) / $rows / 2;
Zeile 235: Zeile 225:
     {
     {
         $this->sheet->clearTerminal();
         $this->sheet->clearTerminal();
         $this->sheet->showDrawing();
         $this->sheet->show();
     }
     }
     public function step()
     public function step()
Zeile 241: Zeile 231:
         $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 251: Zeile 242:


$simulator = new Simulator($sheet);
$simulator = new Simulator($sheet);
$simulator->buildHouses(3, 3);
$simulator->buildBarriers(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();

Version vom 28. November 2023, 12:29 Uhr

Links

Zielsetzung

Dies ist eine funktionierende Lösung der Robotersimulaltion.

<?php

define('BLACK', '*');
define('DEFAULT_COLOR', "\t");
define('WHITE', ' ');

/**
 * Implements a sheet area with ascii sheet.
 */

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->lines = [];
        for ($y = 0; $y < $this->height; $y++) {
            array_push($this->lines, str_repeat(' ', $this->width));
        }
    }
    public function clearTerminal()
    {
        echo "\x1b\x5b\x48\x1b\x5b\x32\x4a\xc";
    }
    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 show()
    {
        $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 $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;
        if ($this->target->x == $this->x && $this->target->y == $this->y) {
            // $sheet->setRandomPosition($this->target, $sheet);
        } else {
            $x = $this->x;
            $y = $this->y;
            if ($this->target->x !== $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 buildBarriers(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->show();
    }
    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->buildBarriers(3, 3);
$simulator->buildRobots(5);
$simulator->show();

$rounds = 0;
while ($simulator->step()) {
    $rounds++;
    $simulator->show();
    sleep(1);
}
echo "== ready after $rounds rounds\n";